mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-11-02 03:51:18 +00:00
Compare commits
547 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f57fc06347 | ||
|
|
32a14ab8e0 | ||
|
|
5fafe6e4f4 | ||
|
|
ee907aba34 | ||
|
|
2ae9a6f020 | ||
|
|
479841a609 | ||
|
|
10da45edce | ||
|
|
36c4a30fe3 | ||
|
|
d4542cc3fc | ||
|
|
dea02e374f | ||
|
|
91deac706c | ||
|
|
17e85ca2cf | ||
|
|
91593335ef | ||
|
|
d27176c0b3 | ||
|
|
070e1e81ae | ||
|
|
2c7d94e5e9 | ||
|
|
a5520d45e7 | ||
|
|
922c8703f5 | ||
|
|
75cc024e28 | ||
|
|
75c6da7730 | ||
|
|
35c8b2fce8 | ||
|
|
4f5d8f830e | ||
|
|
78cb6da21a | ||
|
|
a7e1a51476 | ||
|
|
a8ff77addd | ||
|
|
3c9c46d574 | ||
|
|
8ede404b8a | ||
|
|
a7585e3040 | ||
|
|
cd47b45fce | ||
|
|
b6c23b8eb3 | ||
|
|
297e12f6e4 | ||
|
|
29b02fcac2 | ||
|
|
0c2218762c | ||
|
|
27bc03fc20 | ||
|
|
84b3195e9b | ||
|
|
6f54f41946 | ||
|
|
c1ae0ab57d | ||
|
|
446ff81335 | ||
|
|
03b4a50317 | ||
|
|
06c3362332 | ||
|
|
5f059d02ad | ||
|
|
3e71a103a2 | ||
|
|
e46561347d | ||
|
|
a3f33ae888 | ||
|
|
f71359e73d | ||
|
|
a0b475d8ef | ||
|
|
f3a597cd12 | ||
|
|
29f2ee93d1 | ||
|
|
454b3ebd97 | ||
|
|
89942ee49c | ||
|
|
746bd2ce92 | ||
|
|
747602a9cb | ||
|
|
8ce43a3fe1 | ||
|
|
1284f9cecc | ||
|
|
c54541b839 | ||
|
|
4bd94e5450 | ||
|
|
2a30293905 | ||
|
|
159fffef2e | ||
|
|
5313652d7a | ||
|
|
ae4612f134 | ||
|
|
97f6e68164 | ||
|
|
108d43f967 | ||
|
|
b0e1c85c55 | ||
|
|
82e4055fa6 | ||
|
|
2a68ce6c90 | ||
|
|
05b0425929 | ||
|
|
3b15415a1b | ||
|
|
00fb809ab9 | ||
|
|
494aa15567 | ||
|
|
07450f9f23 | ||
|
|
f0de469053 | ||
|
|
8e4092e7d7 | ||
|
|
9a2e5c36a1 | ||
|
|
b782316cc0 | ||
|
|
3e84f9664f | ||
|
|
01e789f5ce | ||
|
|
b2381f4657 | ||
|
|
64a3e46cbe | ||
|
|
c0d6d0e28e | ||
|
|
c13d0da9fa | ||
|
|
050334a648 | ||
|
|
0256337855 | ||
|
|
bb073e4b6e | ||
|
|
40341ac14e | ||
|
|
4420df6e5d | ||
|
|
99cc7a9a60 | ||
|
|
7ec1b985d0 | ||
|
|
9f19d26a23 | ||
|
|
e766614630 | ||
|
|
ad49553b9c | ||
|
|
1b3b39d2ea | ||
|
|
cb68505204 | ||
|
|
a574dca0cc | ||
|
|
c3fa1612d6 | ||
|
|
7a8f6d8660 | ||
|
|
9dda801fae | ||
|
|
344742c493 | ||
|
|
886d05d436 | ||
|
|
baac2ad921 | ||
|
|
c3337c9bac | ||
|
|
6a6ca22bf0 | ||
|
|
f873f5488f | ||
|
|
e18f843a57 | ||
|
|
56a92505bd | ||
|
|
a8bc7dd7c1 | ||
|
|
94614550fc | ||
|
|
b2052615e3 | ||
|
|
f51b9217f5 | ||
|
|
d892a87d1d | ||
|
|
b7182f9462 | ||
|
|
79518753ad | ||
|
|
01634ed5e9 | ||
|
|
f7abf8a02d | ||
|
|
3f7f1a50e7 | ||
|
|
a5a770e750 | ||
|
|
9cd10f58ed | ||
|
|
5011531066 | ||
|
|
d1c7a9767a | ||
|
|
d78e11170b | ||
|
|
74f8dceb38 | ||
|
|
1fbf91c768 | ||
|
|
edf764aaf4 | ||
|
|
7380c5096e | ||
|
|
45699f13fc | ||
|
|
1fd8c9adc2 | ||
|
|
5cc840e390 | ||
|
|
e491dda229 | ||
|
|
daa8aa5c9d | ||
|
|
0561554726 | ||
|
|
34abc6490c | ||
|
|
66f309f5ed | ||
|
|
2283f3e786 | ||
|
|
d261c793ae | ||
|
|
31448a3add | ||
|
|
d85ccb6ab2 | ||
|
|
bd0be97137 | ||
|
|
81d70a57ca | ||
|
|
b17f2f5d1f | ||
|
|
53ed5b2975 | ||
|
|
5626fee282 | ||
|
|
cb9aefc489 | ||
|
|
a9c83beb4f | ||
|
|
4a64a1bd46 | ||
|
|
4152179f10 | ||
|
|
400219a9fc | ||
|
|
933105a721 | ||
|
|
bb39781848 | ||
|
|
f90b7bed5e | ||
|
|
80bf94c009 | ||
|
|
f46904c644 | ||
|
|
057619b157 | ||
|
|
fd505b77b2 | ||
|
|
81a23b5b22 | ||
|
|
c0ab0b5af5 | ||
|
|
970cc91938 | ||
|
|
749d373c95 | ||
|
|
3a427dd0f4 | ||
|
|
e1402d5d8a | ||
|
|
864a6883d4 | ||
|
|
9b58c28be8 | ||
|
|
69fe6ecb7d | ||
|
|
321676c97f | ||
|
|
d2e1493530 | ||
|
|
1c8375d0c2 | ||
|
|
e164e22e13 | ||
|
|
c1c4c96918 | ||
|
|
742e03944d | ||
|
|
60f2c19d9d | ||
|
|
21a8d9a109 | ||
|
|
9abedf3160 | ||
|
|
4e48961c2b | ||
|
|
78cd1629de | ||
|
|
dd0cc2d173 | ||
|
|
8f00d2b616 | ||
|
|
c26d98b308 | ||
|
|
913774850b | ||
|
|
43c9737e6e | ||
|
|
67cd3b6f81 | ||
|
|
d0d2189d55 | ||
|
|
b12773bc99 | ||
|
|
da5a1fe264 | ||
|
|
ea48c23535 | ||
|
|
8cd0d5e1ef | ||
|
|
9b46e62eb6 | ||
|
|
1653152dad | ||
|
|
db7e3d725e | ||
|
|
329b34f7d1 | ||
|
|
d624f20107 | ||
|
|
20bebeb7de | ||
|
|
4e9456b33b | ||
|
|
26c03552c6 | ||
|
|
ac6c3496d4 | ||
|
|
2f1760f358 | ||
|
|
53db8912d6 | ||
|
|
91ef21a665 | ||
|
|
5b1153ab65 | ||
|
|
5196bb9281 | ||
|
|
8fd6f8177f | ||
|
|
7b68716a3d | ||
|
|
d8ecc63e66 | ||
|
|
2575f61828 | ||
|
|
c6370ebe48 | ||
|
|
3bc38570a2 | ||
|
|
0d36d43eda | ||
|
|
a5a012738e | ||
|
|
7cce6504e3 | ||
|
|
f696353e2c | ||
|
|
cf11dfe73b | ||
|
|
940323c0b7 | ||
|
|
9f768396c2 | ||
|
|
160e57bfde | ||
|
|
429bec66f2 | ||
|
|
7f9b5e1e5e | ||
|
|
8088c28235 | ||
|
|
2ec310da18 | ||
|
|
d8addc3175 | ||
|
|
7887655077 | ||
|
|
209c42b316 | ||
|
|
011d8a2b9a | ||
|
|
6f70791239 | ||
|
|
7ac439fd0e | ||
|
|
0cda098b4f | ||
|
|
aaff40c4ad | ||
|
|
306e1081e3 | ||
|
|
a1e2dac658 | ||
|
|
07382d5c6d | ||
|
|
56fdb57d24 | ||
|
|
336a9a97f9 | ||
|
|
88083c5b38 | ||
|
|
7e590fb6b3 | ||
|
|
4bb4ffbac4 | ||
|
|
7de3c7f80a | ||
|
|
84d0e44a08 | ||
|
|
d7ca7e4cd8 | ||
|
|
3ba41d712f | ||
|
|
ce917298ed | ||
|
|
91e0e33a04 | ||
|
|
c32e9fabd9 | ||
|
|
dc73db2a07 | ||
|
|
89cc01ce44 | ||
|
|
efa3eb1981 | ||
|
|
50ab1fa3f0 | ||
|
|
e50641e969 | ||
|
|
d4c763df84 | ||
|
|
c0669c158a | ||
|
|
e33bbc6f16 | ||
|
|
ea5ab54c3a | ||
|
|
3c18ea1e14 | ||
|
|
25ba86b5d8 | ||
|
|
ecdf59ee3e | ||
|
|
cc1f3bba7e | ||
|
|
b501c47187 | ||
|
|
791b028dc4 | ||
|
|
ab5b7f7893 | ||
|
|
4b1aa29269 | ||
|
|
de34538d96 | ||
|
|
53eb93fc4d | ||
|
|
a3841855e4 | ||
|
|
b1e742c26c | ||
|
|
2c2814c998 | ||
|
|
214c7a6f3e | ||
|
|
6c4f967c39 | ||
|
|
e0152d3df4 | ||
|
|
989ffc2f07 | ||
|
|
f87a4c1e7c | ||
|
|
fea5510700 | ||
|
|
aa1ae18dbb | ||
|
|
b5efd38ded | ||
|
|
2a457c40db | ||
|
|
e38b64547f | ||
|
|
bafa96b9c0 | ||
|
|
d49a13b091 | ||
|
|
0bd818956f | ||
|
|
c119b9cc7b | ||
|
|
958c7e7939 | ||
|
|
254a46b54c | ||
|
|
6ed31dc4c9 | ||
|
|
fe8f5573d2 | ||
|
|
51dfb8ebf1 | ||
|
|
8fd64791d6 | ||
|
|
82e7202ad2 | ||
|
|
1f70782f7e | ||
|
|
eefb1c4a47 | ||
|
|
069015c9b1 | ||
|
|
c1583d19fb | ||
|
|
0556433ce4 | ||
|
|
ec072cee23 | ||
|
|
e29e6c147c | ||
|
|
972721b183 | ||
|
|
9bf43ce80d | ||
|
|
5941b5c07e | ||
|
|
3d91a186d5 | ||
|
|
744d45fb04 | ||
|
|
f76fdedd25 | ||
|
|
93ca07d812 | ||
|
|
d69042daee | ||
|
|
d9f515900c | ||
|
|
57b4a5be08 | ||
|
|
fa347f5f75 | ||
|
|
35e3404ced | ||
|
|
f7344ec6c9 | ||
|
|
63a1e560ee | ||
|
|
98463f8258 | ||
|
|
2c95bfa701 | ||
|
|
2de3a2c98e | ||
|
|
314c0c9e3f | ||
|
|
4377627332 | ||
|
|
71d3f452ed | ||
|
|
e117222dc2 | ||
|
|
6286daa881 | ||
|
|
0b3b9af623 | ||
|
|
1492f5611e | ||
|
|
efeffaa49f | ||
|
|
d77112955d | ||
|
|
9a34bb7e7a | ||
|
|
b30445a5f3 | ||
|
|
0bf5c6ee3d | ||
|
|
155480b335 | ||
|
|
34202dea1d | ||
|
|
38d58f0354 | ||
|
|
d4b82a33c5 | ||
|
|
06f3463dbc | ||
|
|
9df2d86ac2 | ||
|
|
c83d93971f | ||
|
|
7e3ba3c27f | ||
|
|
c7043dffc2 | ||
|
|
d2c1e30979 | ||
|
|
d5679c372f | ||
|
|
b33f8b70d4 | ||
|
|
d5773ab5d0 | ||
|
|
1903292202 | ||
|
|
c3a9415208 | ||
|
|
9ece209c72 | ||
|
|
03956af88a | ||
|
|
013c8707ac | ||
|
|
32ed9c59ea | ||
|
|
4ef663669c | ||
|
|
b855c54e81 | ||
|
|
8b65c8b909 | ||
|
|
28e7440726 | ||
|
|
7bca2298a0 | ||
|
|
b1cc17d96e | ||
|
|
2afbef63aa | ||
|
|
f0d2caec67 | ||
|
|
ac2a317fd2 | ||
|
|
bc4ac303e2 | ||
|
|
0e9fbecbe4 | ||
|
|
226b3cfdd8 | ||
|
|
d43fa3790d | ||
|
|
ca04113aa7 | ||
|
|
817c157db4 | ||
|
|
07edbe758a | ||
|
|
46ba0a5a5a | ||
|
|
480b636c7e | ||
|
|
20340dff7b | ||
|
|
cfbabb500f | ||
|
|
a4cb2c1cb1 | ||
|
|
bd31b7e943 | ||
|
|
b2e7c767df | ||
|
|
bb9f763729 | ||
|
|
fb61229bf3 | ||
|
|
fc30d41ee5 | ||
|
|
7666147f3c | ||
|
|
52f8b24041 | ||
|
|
eaf2667abb | ||
|
|
de754ca4e0 | ||
|
|
96dd89fbeb | ||
|
|
bae40e2cbc | ||
|
|
6a647dab8b | ||
|
|
ebcf5b71d2 | ||
|
|
02370fb65d | ||
|
|
1e4f4907e3 | ||
|
|
13f72c73fb | ||
|
|
69b4632ef6 | ||
|
|
ede8c293fc | ||
|
|
0cfe991482 | ||
|
|
6377459e2f | ||
|
|
33fe6dbfa3 | ||
|
|
e158b9b64e | ||
|
|
dfa9e537b3 | ||
|
|
6d28ece616 | ||
|
|
59f4ecdaa6 | ||
|
|
10d953f336 | ||
|
|
5b771f7def | ||
|
|
4a8e3ee845 | ||
|
|
9a1f559dd2 | ||
|
|
62321a03ca | ||
|
|
40ca72c656 | ||
|
|
34fcff7a9d | ||
|
|
e1c829f4fa | ||
|
|
46136d94e9 | ||
|
|
0e2e8d1be5 | ||
|
|
1d1aa5dd3a | ||
|
|
0d82589916 | ||
|
|
4fc13037d2 | ||
|
|
3764499714 | ||
|
|
c4bbbc49b4 | ||
|
|
503158ab97 | ||
|
|
8c1d1d1db0 | ||
|
|
7dc72a2894 | ||
|
|
07cfba1b3a | ||
|
|
c55b80f467 | ||
|
|
2099da7142 | ||
|
|
ea125936e7 | ||
|
|
5de01628a6 | ||
|
|
2834aca597 | ||
|
|
88bab888d8 | ||
|
|
dfdbace298 | ||
|
|
a9590d2bb6 | ||
|
|
29a81eb05e | ||
|
|
20490fcd80 | ||
|
|
e775927f60 | ||
|
|
835a421909 | ||
|
|
850a0ae17e | ||
|
|
2b54363dd7 | ||
|
|
b174a06b86 | ||
|
|
d4096103cb | ||
|
|
3f493aceb2 | ||
|
|
05309da76d | ||
|
|
179f720806 | ||
|
|
7c34144ccd | ||
|
|
cc234b594d | ||
|
|
024cf610a8 | ||
|
|
a1896a6336 | ||
|
|
d30da7bf5d | ||
|
|
f8e914416d | ||
|
|
433da921bb | ||
|
|
4876053018 | ||
|
|
0c3a580b33 | ||
|
|
7689b7b4b0 | ||
|
|
21bff39e31 | ||
|
|
ba09901228 | ||
|
|
90bf2e58b2 | ||
|
|
004807aa32 | ||
|
|
35bacf2ad0 | ||
|
|
81d17409d4 | ||
|
|
a8080f55f0 | ||
|
|
379c540bd8 | ||
|
|
f319005357 | ||
|
|
df0e2dd2a2 | ||
|
|
219a0cd612 | ||
|
|
3ca3ce0726 | ||
|
|
566be8dc63 | ||
|
|
6bd4fa1c0a | ||
|
|
c767ee04f4 | ||
|
|
a5f89e0967 | ||
|
|
7355d14159 | ||
|
|
efd5ceb405 | ||
|
|
035dc8ceb4 | ||
|
|
11be33e942 | ||
|
|
e125254687 | ||
|
|
a2b997ba20 | ||
|
|
7327941c77 | ||
|
|
6c9eb1b699 | ||
|
|
60e262dece | ||
|
|
9c5463e515 | ||
|
|
6941176519 | ||
|
|
cb2c52cddb | ||
|
|
dd95776144 | ||
|
|
b95ca98be9 | ||
|
|
67b090b4d8 | ||
|
|
54b76a03ce | ||
|
|
cd6c727730 | ||
|
|
a35c6e29b6 | ||
|
|
95ce72fce7 | ||
|
|
a803dfc7fa | ||
|
|
c465d1c059 | ||
|
|
9914c0791e | ||
|
|
96baf5d3c7 | ||
|
|
a205367b62 | ||
|
|
6218fa90de | ||
|
|
51a770cfdc | ||
|
|
16fba15b5c | ||
|
|
ec2463a3ba | ||
|
|
b605ede74e | ||
|
|
b1b13d3696 | ||
|
|
51b11e5188 | ||
|
|
eefa84a77b | ||
|
|
5908b4b000 | ||
|
|
2ed433c96d | ||
|
|
9865800e39 | ||
|
|
4f697e77d5 | ||
|
|
c957aded98 | ||
|
|
aa0758cd2b | ||
|
|
0c2093753d | ||
|
|
136f983353 | ||
|
|
7943164375 | ||
|
|
32e58d0a60 | ||
|
|
bc807965ab | ||
|
|
477788658b | ||
|
|
723abf44bd | ||
|
|
fd1298d4d2 | ||
|
|
42f39536a1 | ||
|
|
6f0ac91bd2 | ||
|
|
6dea9156ab | ||
|
|
c5051b3e46 | ||
|
|
229d033e1a | ||
|
|
f494ba7065 | ||
|
|
201bc7db53 | ||
|
|
cd2a251f22 | ||
|
|
ff44ad4994 | ||
|
|
b496ca6a2c | ||
|
|
5908c0ce8c | ||
|
|
f7eef25fed | ||
|
|
049c93465a | ||
|
|
33294dd9f0 | ||
|
|
0a89f4000d | ||
|
|
422e80530b | ||
|
|
07a8c69ba8 | ||
|
|
5449879a7d | ||
|
|
8dbc846314 | ||
|
|
f0d3ca5d53 | ||
|
|
5af026674f | ||
|
|
2ebb4778cd | ||
|
|
bf3c57d26b | ||
|
|
cb9c87102f | ||
|
|
c73b003de4 | ||
|
|
771d448a7b | ||
|
|
de12db5f05 | ||
|
|
dd49926cc2 | ||
|
|
7a9ab190eb | ||
|
|
2290fcde22 | ||
|
|
ae85876965 | ||
|
|
f07d8e958f | ||
|
|
610af45dee | ||
|
|
138a5bc3fe | ||
|
|
427e9c5637 | ||
|
|
e3e8336602 | ||
|
|
194073e49a | ||
|
|
1af45aff73 | ||
|
|
56518ea028 | ||
|
|
c1ac2bb156 | ||
|
|
a004f27361 | ||
|
|
7843c55409 | ||
|
|
41da7d9f9a | ||
|
|
2add644706 | ||
|
|
dfd9cf0874 | ||
|
|
7ad09da4e9 | ||
|
|
8efbeb14d2 | ||
|
|
a1005d91df | ||
|
|
a681f1ce3c | ||
|
|
5a0714ca1a | ||
|
|
bd5c790043 | ||
|
|
2ae3cf79e4 | ||
|
|
fb122ba097 | ||
|
|
0c104cd86c | ||
|
|
a687f4ad68 |
@@ -1,12 +0,0 @@
|
||||
---
|
||||
exclude_patterns:
|
||||
- public/lib/
|
||||
- public/js/lib/
|
||||
- public/fonts/
|
||||
- public/css/jquery-ui/
|
||||
- public/css/bootstrap-multiselect.css
|
||||
- public/css/bootstrap-sortable.css
|
||||
- public/css/bootstrap-tagsinput.css
|
||||
- public/css/daterangepicker.css
|
||||
- public/css/google-fonts.css
|
||||
- .sandstorm/
|
||||
3314
.deploy/docker/cacert.pem
Normal file
3314
.deploy/docker/cacert.pem
Normal file
File diff suppressed because it is too large
Load Diff
11
.deploy/docker/cronjob.conf
Normal file
11
.deploy/docker/cronjob.conf
Normal file
@@ -0,0 +1,11 @@
|
||||
[program:cron]
|
||||
command=/usr/sbin/cron -f -L 15
|
||||
user=root
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_events_enabled=true
|
||||
stderr_events_enabled=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
startsecs=10
|
||||
startretries=3
|
||||
@@ -8,6 +8,7 @@ mkdir -p $FIREFLY_PATH/storage/database
|
||||
mkdir -p $FIREFLY_PATH/storage/debugbar
|
||||
mkdir -p $FIREFLY_PATH/storage/export
|
||||
mkdir -p $FIREFLY_PATH/storage/framework/cache
|
||||
mkdir -p $FIREFLY_PATH/storage/framework/cache/data
|
||||
mkdir -p $FIREFLY_PATH/storage/framework/sessions
|
||||
mkdir -p $FIREFLY_PATH/storage/framework/testing
|
||||
mkdir -p $FIREFLY_PATH/storage/framework/views
|
||||
@@ -15,6 +16,11 @@ mkdir -p $FIREFLY_PATH/storage/logs
|
||||
mkdir -p $FIREFLY_PATH/storage/upload
|
||||
|
||||
|
||||
if [[ $DB_CONNECTION == "sqlite" ]]
|
||||
then
|
||||
touch $FIREFLY_PATH/storage/database/database.sqlite
|
||||
fi
|
||||
|
||||
# make sure we own the volumes:
|
||||
chown -R www-data:www-data -R $FIREFLY_PATH/storage
|
||||
chmod -R 775 $FIREFLY_PATH/storage
|
||||
@@ -22,8 +28,15 @@ chmod -R 775 $FIREFLY_PATH/storage
|
||||
# remove any lingering files that may break upgrades:
|
||||
rm -f $FIREFLY_PATH/storage/logs/laravel.log
|
||||
|
||||
cat .env.docker | envsubst > .env && cat .env
|
||||
cat .env.docker | envsubst > .env
|
||||
composer dump-autoload
|
||||
php artisan package:discover
|
||||
|
||||
php artisan migrate --seed
|
||||
php artisan firefly:upgrade-database
|
||||
php artisan firefly:verify
|
||||
php artisan passport:install
|
||||
php artisan cache:clear
|
||||
|
||||
php artisan firefly:instructions install
|
||||
exec apache2-foreground
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf --nodaemon
|
||||
6
.deploy/docker/firefly-iii.conf
Normal file
6
.deploy/docker/firefly-iii.conf
Normal file
@@ -0,0 +1,6 @@
|
||||
[program:apache2]
|
||||
command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2 -DFOREGROUND"
|
||||
stdout_events_enabled=true
|
||||
stderr_events_enabled=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
30
.deploy/docker/supervisord.conf
Normal file
30
.deploy/docker/supervisord.conf
Normal file
@@ -0,0 +1,30 @@
|
||||
# supervisor config file
|
||||
# Adapted from the config file distributed with the supervisor package on Debian
|
||||
# Jessie
|
||||
|
||||
# Enable supervisord in non-daemon mode. Disable the logfile as we receive
|
||||
# log messages via stdout/err. Set up the child process log directory in case
|
||||
# the user doesn't set logging to stdout/err.
|
||||
[supervisord]
|
||||
nodaemon = true
|
||||
logfile = NONE
|
||||
pidfile = /var/run/supervisord.pid
|
||||
childlogdir = /var/log/supervisor
|
||||
loglevel=debug
|
||||
|
||||
# Enable supervisorctl via RPC interface over Unix socket
|
||||
[unix_http_server]
|
||||
file = /var/run/supervisor.sock
|
||||
chmod = 0700
|
||||
|
||||
[rpcinterface:supervisor]
|
||||
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
|
||||
|
||||
[supervisorctl]
|
||||
serverurl = unix:///var/run/supervisor.sock
|
||||
|
||||
|
||||
# Include conf files for child processes
|
||||
# Debian/Ubuntu packages use /etc/supervisor/conf.d
|
||||
[include]
|
||||
files = /etc/supervisor/conf.d/*.conf
|
||||
26
.deploy/docker/vhost.conf
Normal file
26
.deploy/docker/vhost.conf
Normal file
@@ -0,0 +1,26 @@
|
||||
server {
|
||||
listen 80 default_server;
|
||||
|
||||
server_name _ *.vm docker;
|
||||
|
||||
root "/app/public";
|
||||
index index.php;
|
||||
|
||||
include /opt/docker/etc/nginx/vhost.common.d/*.conf;
|
||||
}
|
||||
|
||||
##############
|
||||
# SSL
|
||||
##############
|
||||
|
||||
server {
|
||||
listen 443 default_server;
|
||||
|
||||
server_name _ *.vm docker;
|
||||
|
||||
root "/app/public";
|
||||
index index.php;
|
||||
|
||||
include /opt/docker/etc/nginx/vhost.common.d/*.conf;
|
||||
include /opt/docker/etc/nginx/vhost.ssl.conf;
|
||||
}
|
||||
101
.env.docker
101
.env.docker
@@ -13,37 +13,55 @@ SITE_OWNER=${SITE_OWNER}
|
||||
# Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it
|
||||
APP_KEY=${FF_APP_KEY}
|
||||
|
||||
# APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy.
|
||||
# Change this value to your preferred time zone.
|
||||
# Example: Europe/Amsterdam
|
||||
TZ=${TZ}
|
||||
|
||||
# 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=${APP_URL}
|
||||
|
||||
# TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy.
|
||||
TRUSTED_PROXIES=${TRUSTED_PROXIES}
|
||||
|
||||
# The log channel defines where your log entries go to.
|
||||
LOG_CHANNEL=${LOG_CHANNEL}
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# If you use SQLite, set connection to `sqlite` and remove the database, username and password settings.
|
||||
DB_CONNECTION=${FF_DB_CONNECTION}
|
||||
DB_HOST=${FF_DB_HOST}
|
||||
DB_PORT=${FF_DB_PORT}
|
||||
DB_DATABASE=${FF_DB_NAME}
|
||||
DB_USERNAME=${FF_DB_USER}
|
||||
DB_PASSWORD=${FF_DB_PASSWORD}
|
||||
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# Several other options exist. You can use 'single' for one big fat error log (not recommended).
|
||||
# Also available are 'syslog' and 'errorlog' which will log to the system itself.
|
||||
APP_LOG=syslog
|
||||
# Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself.
|
||||
LOG_CHANNEL=stdout
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=info
|
||||
APP_LOG_LEVEL=${APP_LOG_LEVEL}
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html
|
||||
DB_CONNECTION=${FF_DB_CONNECTION}
|
||||
DB_HOST=${FF_DB_HOST}
|
||||
DB_PORT=${FF_DB_PORT}
|
||||
DB_DATABASE=${FF_DB_NAME}
|
||||
DB_USERNAME=${FF_DB_USER}
|
||||
DB_PASSWORD="${FF_DB_PASSWORD}"
|
||||
|
||||
# If you're looking for performance improvements, you could install memcached.
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
# You can configure another file storage backend if you cannot use the local storage option.
|
||||
# To set this up, fill in the following variables. The upload path is used to store uploaded
|
||||
# files and the export path is to store exported data (before download).
|
||||
SFTP_HOST=${SFTP_HOST}
|
||||
SFTP_PORT=${SFTP_PORT}
|
||||
SFTP_UPLOAD_PATH=${SFTP_UPLOAD_PATH}
|
||||
SFTP_EXPORT_PATH=${SFTP_EXPORT_PATH}
|
||||
|
||||
# SFTP uses either the username/password combination or the private key to authenticate.
|
||||
SFTP_USERNAME=${SFTP_USERNAME}
|
||||
SFTP_PASSWORD="${SFTP_PASSWORD}"
|
||||
SFTP_PRIV_KEY=${SFTP_PRIV_KEY}
|
||||
|
||||
# Cookie settings. Should not be necessary to change these.
|
||||
COOKIE_PATH="/"
|
||||
COOKIE_DOMAIN=
|
||||
@@ -56,7 +74,7 @@ MAIL_HOST=${MAIL_HOST}
|
||||
MAIL_PORT=${MAIL_PORT}
|
||||
MAIL_FROM=${MAIL_FROM}
|
||||
MAIL_USERNAME=${MAIL_USERNAME}
|
||||
MAIL_PASSWORD=${MAIL_PASSWORD}
|
||||
MAIL_PASSWORD="${MAIL_PASSWORD}"
|
||||
MAIL_ENCRYPTION=${MAIL_ENCRYPTION}
|
||||
|
||||
# Other mail drivers:
|
||||
@@ -69,6 +87,9 @@ SPARKPOST_SECRET=${SPARKPOST_SECRET}
|
||||
SEND_REGISTRATION_MAIL=true
|
||||
SEND_ERROR_MESSAGE=false
|
||||
|
||||
# These messages contain (sensitive) transaction information:
|
||||
SEND_REPORT_JOURNALS=${SEND_REPORT_JOURNALS}
|
||||
|
||||
# Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places.
|
||||
MAPBOX_API_KEY=${MAPBOX_API_KEY}
|
||||
|
||||
@@ -84,9 +105,55 @@ ANALYTICS_ID=${ANALYTICS_ID}
|
||||
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
||||
USE_ENCRYPTION=true
|
||||
|
||||
# Firefly III has two options for user authentication. "eloquent" is the default,
|
||||
# and "adldap" for LDAP servers.
|
||||
# For full instructions on these settings please visit:
|
||||
# https://firefly-iii.readthedocs.io/en/latest/installation/authentication.html
|
||||
LOGIN_PROVIDER=${LOGIN_PROVIDER}
|
||||
|
||||
# LDAP connection configuration
|
||||
ADLDAP_CONNECTION_SCHEME=${ADLDAP_CONNECTION_SCHEME}
|
||||
ADLDAP_AUTO_CONNECT=${ADLDAP_AUTO_CONNECT}
|
||||
|
||||
# LDAP connection settings
|
||||
ADLDAP_CONTROLLERS=${ADLDAP_CONTROLLERS}
|
||||
ADLDAP_PORT=${ADLDAP_PORT}
|
||||
ADLDAP_TIMEOUT=${ADLDAP_TIMEOUT}
|
||||
ADLDAP_BASEDN="${ADLDAP_BASEDN}"
|
||||
ADLDAP_FOLLOW_REFFERALS=${ADLDAP_FOLLOW_REFFERALS}
|
||||
ADLDAP_USE_SSL=${ADLDAP_USE_SSL}
|
||||
ADLDAP_USE_TLS=${ADLDAP_USE_TLS}
|
||||
|
||||
ADLDAP_ADMIN_USERNAME=${ADLDAP_ADMIN_USERNAME}
|
||||
ADLDAP_ADMIN_PASSWORD="${ADLDAP_ADMIN_PASSWORD}"
|
||||
|
||||
ADLDAP_ACCOUNT_PREFIX="${ADLDAP_ACCOUNT_PREFIX}"
|
||||
ADLDAP_ACCOUNT_SUFFIX="${ADLDAP_ACCOUNT_SUFFIX}"
|
||||
ADLDAP_ADMIN_ACCOUNT_PREFIX="${ADLDAP_ADMIN_ACCOUNT_PREFIX}"
|
||||
ADLDAP_ADMIN_ACCOUNT_SUFFIX="${ADLDAP_ADMIN_ACCOUNT_SUFFIX}"
|
||||
|
||||
# LDAP authentication settings.
|
||||
ADLDAP_PASSWORD_SYNC=${ADLDAP_PASSWORD_SYNC}
|
||||
ADLDAP_LOGIN_FALLBACK=${ADLDAP_LOGIN_FALLBACK}
|
||||
|
||||
ADLDAP_DISCOVER_FIELD=${ADLDAP_DISCOVER_FIELD}
|
||||
ADLDAP_AUTH_FIELD=${ADLDAP_AUTH_FIELD}
|
||||
|
||||
# Will allow SSO if your server provides an AUTH_USER field.
|
||||
WINDOWS_SSO_DISCOVER=${WINDOWS_SSO_DISCOVER}
|
||||
WINDOWS_SSO_KEY=${WINDOWS_SSO_KEY}
|
||||
|
||||
# field to sync as local username.
|
||||
ADLDAP_SYNC_FIELD=${ADLDAP_SYNC_FIELD}
|
||||
|
||||
# You can disable the X-Frame-Options header if it interfears with tools like
|
||||
# Organizr. This is at your own risk.
|
||||
DISABLE_FRAME_HEADER=${DISABLE_FRAME_HEADER}
|
||||
|
||||
# Leave the following configuration vars as is.
|
||||
# Unless you like to tinker and know what you're doing.
|
||||
APP_NAME=FireflyIII
|
||||
ADLDAP_CONNECTION=default
|
||||
BROADCAST_DRIVER=log
|
||||
QUEUE_DRIVER=sync
|
||||
REDIS_HOST=127.0.0.1
|
||||
@@ -103,4 +170,4 @@ IS_DOCKER=true
|
||||
IS_SANDSTORM=false
|
||||
IS_HEROKU=false
|
||||
BUNQ_USE_SANDBOX=false
|
||||
TZ=${TZ}
|
||||
FFIII_LAYOUT=v1
|
||||
|
||||
95
.env.example
95
.env.example
@@ -15,15 +15,27 @@ APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
|
||||
# Change this value to your preferred time zone.
|
||||
# Example: Europe/Amsterdam
|
||||
TZ=UTC
|
||||
TZ=Europe/Amsterdam
|
||||
|
||||
# APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy.
|
||||
# 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.
|
||||
TRUSTED_PROXIES=
|
||||
|
||||
# The log channel defines where your log entries go to.
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# 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.
|
||||
LOG_CHANNEL=daily
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
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: http://firefly-iii.readthedocs.io/en/latest/support/faq.html
|
||||
DB_CONNECTION=mysql
|
||||
@@ -33,21 +45,23 @@ DB_DATABASE=homestead
|
||||
DB_USERNAME=homestead
|
||||
DB_PASSWORD=secret
|
||||
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# Several other options exist. You can use 'single' for one big fat error log (not recommended).
|
||||
# Also available are 'syslog' and 'errorlog' which will log to the system itself.
|
||||
APP_LOG=daily
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=notice
|
||||
|
||||
# If you're looking for performance improvements, you could install memcached.
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
# You can configure another file storage backend if you cannot use the local storage option.
|
||||
# To set this up, fill in the following variables. The upload path is used to store uploaded
|
||||
# files and the export path is to store exported data (before download).
|
||||
SFTP_HOST=
|
||||
SFTP_PORT=
|
||||
SFTP_UPLOAD_PATH=
|
||||
SFTP_EXPORT_PATH=
|
||||
|
||||
# SFTP uses either the username/password combination or the private key to authenticate.
|
||||
SFTP_USERNAME=
|
||||
SFTP_PASSWORD=
|
||||
SFTP_PRIV_KEY=
|
||||
|
||||
# Cookie settings. Should not be necessary to change these.
|
||||
COOKIE_PATH="/"
|
||||
COOKIE_DOMAIN=
|
||||
@@ -73,6 +87,9 @@ SPARKPOST_SECRET=
|
||||
SEND_REGISTRATION_MAIL=true
|
||||
SEND_ERROR_MESSAGE=true
|
||||
|
||||
# These messages contain (sensitive) transaction information:
|
||||
SEND_REPORT_JOURNALS=true
|
||||
|
||||
# Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places.
|
||||
MAPBOX_API_KEY=
|
||||
|
||||
@@ -88,9 +105,56 @@ ANALYTICS_ID=
|
||||
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
||||
USE_ENCRYPTION=true
|
||||
|
||||
# Firefly III has two options for user authentication. "eloquent" is the default,
|
||||
# and "adldap" for LDAP servers.
|
||||
# For full instructions on these settings please visit:
|
||||
# https://firefly-iii.readthedocs.io/en/latest/installation/authentication.html
|
||||
LOGIN_PROVIDER=eloquent
|
||||
|
||||
# LDAP connection configuration
|
||||
# OpenLDAP, FreeIPA or ActiveDirectory
|
||||
ADLDAP_CONNECTION_SCHEME=OpenLDAP
|
||||
ADLDAP_AUTO_CONNECT=true
|
||||
|
||||
# LDAP connection settings
|
||||
ADLDAP_CONTROLLERS=
|
||||
ADLDAP_PORT=389
|
||||
ADLDAP_TIMEOUT=5
|
||||
ADLDAP_BASEDN=""
|
||||
ADLDAP_FOLLOW_REFFERALS=false
|
||||
ADLDAP_USE_SSL=false
|
||||
ADLDAP_USE_TLS=false
|
||||
|
||||
ADLDAP_ADMIN_USERNAME=
|
||||
ADLDAP_ADMIN_PASSWORD=
|
||||
|
||||
ADLDAP_ACCOUNT_PREFIX=
|
||||
ADLDAP_ACCOUNT_SUFFIX=
|
||||
ADLDAP_ADMIN_ACCOUNT_PREFIX=
|
||||
ADLDAP_ADMIN_ACCOUNT_SUFFIX=
|
||||
|
||||
# LDAP authentication settings.
|
||||
ADLDAP_PASSWORD_SYNC=false
|
||||
ADLDAP_LOGIN_FALLBACK=false
|
||||
|
||||
ADLDAP_DISCOVER_FIELD=distinguishedname
|
||||
ADLDAP_AUTH_FIELD=distinguishedname
|
||||
|
||||
# Will allow SSO if your server provides an AUTH_USER field.
|
||||
WINDOWS_SSO_DISCOVER=samaccountname
|
||||
WINDOWS_SSO_KEY=AUTH_USER
|
||||
|
||||
# field to sync as local username.
|
||||
ADLDAP_SYNC_FIELD=userprincipalname
|
||||
|
||||
# You can disable the X-Frame-Options header if it interfears with tools like
|
||||
# Organizr. This is at your own risk.
|
||||
DISABLE_FRAME_HEADER=false
|
||||
|
||||
# Leave the following configuration vars as is.
|
||||
# Unless you like to tinker and know what you're doing.
|
||||
APP_NAME=FireflyIII
|
||||
ADLDAP_CONNECTION=default
|
||||
BROADCAST_DRIVER=log
|
||||
QUEUE_DRIVER=sync
|
||||
REDIS_HOST=127.0.0.1
|
||||
@@ -105,7 +169,6 @@ DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
IS_DOCKER=false
|
||||
IS_SANDSTORM=false
|
||||
BUNQ_USE_SANDBOX=false
|
||||
IS_HEROKU=false
|
||||
MAILGUN_DOMAIN=
|
||||
MAILGUN_SECRET=
|
||||
BUNQ_USE_SANDBOX=false
|
||||
FFIII_LAYOUT=v1
|
||||
|
||||
97
.env.heroku
97
.env.heroku
@@ -17,12 +17,24 @@ APP_KEY=7ahyYVPVsmxjdhsweWCauGeJfwc92NP2
|
||||
# Example: Europe/Amsterdam
|
||||
TZ=UTC
|
||||
|
||||
# APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy.
|
||||
# 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=
|
||||
|
||||
# TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy.
|
||||
TRUSTED_PROXIES=**
|
||||
|
||||
# The log channel defines where your log entries go to.
|
||||
LOG_CHANNEL=syslog
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# 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.
|
||||
LOG_CHANNEL=stdout
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=debug
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# If you use SQLite, set connection to `sqlite` and remove the database, username and password settings.
|
||||
@@ -33,21 +45,23 @@ DB_CONNECTION=pgsql
|
||||
|
||||
|
||||
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# Several other options exist. You can use 'single' for one big fat error log (not recommended).
|
||||
# Also available are 'syslog' and 'errorlog' which will log to the system itself.
|
||||
APP_LOG=errorlog
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=debug
|
||||
|
||||
# If you're looking for performance improvements, you could install memcached.
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
# You can configure another file storage backend if you cannot use the local storage option.
|
||||
# To set this up, fill in the following variables. The upload path is used to store uploaded
|
||||
# files and the export path is to store exported data (before download).
|
||||
SFTP_HOST=
|
||||
SFTP_PORT=
|
||||
SFTP_UPLOAD_PATH=
|
||||
SFTP_EXPORT_PATH=
|
||||
|
||||
# SFTP uses either the username/password combination or the private key to authenticate.
|
||||
SFTP_USERNAME=
|
||||
SFTP_PASSWORD=
|
||||
SFTP_PRIV_KEY=
|
||||
|
||||
# Cookie settings. Should not be necessary to change these.
|
||||
COOKIE_PATH="/"
|
||||
COOKIE_DOMAIN=
|
||||
@@ -73,6 +87,9 @@ SPARKPOST_SECRET=
|
||||
SEND_REGISTRATION_MAIL=true
|
||||
SEND_ERROR_MESSAGE=true
|
||||
|
||||
# These messages contain (sensitive) transaction information:
|
||||
SEND_REPORT_JOURNALS=true
|
||||
|
||||
# Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places.
|
||||
MAPBOX_API_KEY=
|
||||
|
||||
@@ -88,9 +105,56 @@ ANALYTICS_ID=
|
||||
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
||||
USE_ENCRYPTION=true
|
||||
|
||||
# Firefly III has two options for user authentication. "eloquent" is the default,
|
||||
# and "adldap" for LDAP servers.
|
||||
# For full instructions on these settings please visit:
|
||||
# https://firefly-iii.readthedocs.io/en/latest/installation/authentication.html
|
||||
LOGIN_PROVIDER=eloquent
|
||||
|
||||
# LDAP connection configuration
|
||||
# OpenLDAP, FreeIPA or ActiveDirectory
|
||||
ADLDAP_CONNECTION_SCHEME=OpenLDAP
|
||||
ADLDAP_AUTO_CONNECT=true
|
||||
|
||||
# LDAP connection settings
|
||||
ADLDAP_CONTROLLERS=
|
||||
ADLDAP_PORT=389
|
||||
ADLDAP_TIMEOUT=5
|
||||
ADLDAP_BASEDN=""
|
||||
ADLDAP_FOLLOW_REFFERALS=false
|
||||
ADLDAP_USE_SSL=false
|
||||
ADLDAP_USE_TLS=false
|
||||
|
||||
ADLDAP_ADMIN_USERNAME=
|
||||
ADLDAP_ADMIN_PASSWORD=
|
||||
|
||||
ADLDAP_ACCOUNT_PREFIX=
|
||||
ADLDAP_ACCOUNT_SUFFIX=
|
||||
ADLDAP_ADMIN_ACCOUNT_PREFIX=
|
||||
ADLDAP_ADMIN_ACCOUNT_SUFFIX=
|
||||
|
||||
# LDAP authentication settings.
|
||||
ADLDAP_PASSWORD_SYNC=false
|
||||
ADLDAP_LOGIN_FALLBACK=false
|
||||
|
||||
ADLDAP_DISCOVER_FIELD=distinguishedname
|
||||
ADLDAP_AUTH_FIELD=distinguishedname
|
||||
|
||||
# Will allow SSO if your server provides an AUTH_USER field.
|
||||
WINDOWS_SSO_DISCOVER=samaccountname
|
||||
WINDOWS_SSO_KEY=AUTH_USER
|
||||
|
||||
# field to sync as local username.
|
||||
ADLDAP_SYNC_FIELD=userprincipalname
|
||||
|
||||
# You can disable the X-Frame-Options header if it interfears with tools like
|
||||
# Organizr. This is at your own risk.
|
||||
DISABLE_FRAME_HEADER=false
|
||||
|
||||
# Leave the following configuration vars as is.
|
||||
# Unless you like to tinker and know what you're doing.
|
||||
APP_NAME=FireflyIII
|
||||
ADLDAP_CONNECTION=default
|
||||
BROADCAST_DRIVER=log
|
||||
QUEUE_DRIVER=sync
|
||||
REDIS_HOST=127.0.0.1
|
||||
@@ -105,7 +169,6 @@ DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
IS_DOCKER=false
|
||||
IS_SANDSTORM=false
|
||||
BUNQ_USE_SANDBOX=false
|
||||
IS_HEROKU=true
|
||||
MAILGUN_DOMAIN=
|
||||
MAILGUN_SECRET=
|
||||
BUNQ_USE_SANDBOX=false
|
||||
FFIII_LAYOUT=v1
|
||||
|
||||
@@ -17,12 +17,24 @@ APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
# Example: Europe/Amsterdam
|
||||
TZ=UTC
|
||||
|
||||
# APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy.
|
||||
# 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.
|
||||
TRUSTED_PROXIES=
|
||||
|
||||
# The log channel defines where your log entries go to.
|
||||
LOG_CHANNEL=syslog
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# 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.
|
||||
LOG_CHANNEL=stdout
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=debug
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# If you use SQLite, set connection to `sqlite` and remove the database, username and password settings.
|
||||
@@ -33,21 +45,23 @@ DB_DATABASE=firefly
|
||||
DB_USERNAME=firefly
|
||||
DB_PASSWORD=firefly
|
||||
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# Several other options exist. You can use 'single' for one big fat error log (not recommended).
|
||||
# Also available are 'syslog' and 'errorlog' which will log to the system itself.
|
||||
APP_LOG=syslog
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=info
|
||||
|
||||
# If you're looking for performance improvements, you could install memcached.
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
# You can configure another file storage backend if you cannot use the local storage option.
|
||||
# To set this up, fill in the following variables. The upload path is used to store uploaded
|
||||
# files and the export path is to store exported data (before download).
|
||||
SFTP_HOST=
|
||||
SFTP_PORT=
|
||||
SFTP_UPLOAD_PATH=
|
||||
SFTP_EXPORT_PATH=
|
||||
|
||||
# SFTP uses either the username/password combination or the private key to authenticate.
|
||||
SFTP_USERNAME=
|
||||
SFTP_PASSWORD=
|
||||
SFTP_PRIV_KEY=
|
||||
|
||||
# Cookie settings. Should not be necessary to change these.
|
||||
COOKIE_PATH="/"
|
||||
COOKIE_DOMAIN=
|
||||
@@ -73,6 +87,9 @@ SPARKPOST_SECRET=
|
||||
SEND_REGISTRATION_MAIL=true
|
||||
SEND_ERROR_MESSAGE=true
|
||||
|
||||
# These messages contain (sensitive) transaction information:
|
||||
SEND_REPORT_JOURNALS=true
|
||||
|
||||
# Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places.
|
||||
MAPBOX_API_KEY=
|
||||
|
||||
@@ -88,9 +105,56 @@ ANALYTICS_ID=
|
||||
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
||||
USE_ENCRYPTION=true
|
||||
|
||||
# Firefly III has two options for user authentication. "eloquent" is the default,
|
||||
# and "adldap" for LDAP servers.
|
||||
# For full instructions on these settings please visit:
|
||||
# https://firefly-iii.readthedocs.io/en/latest/installation/authentication.html
|
||||
LOGIN_PROVIDER=eloquent
|
||||
|
||||
# LDAP connection configuration
|
||||
# or FreeIPA or ActiveDirectory
|
||||
ADLDAP_CONNECTION_SCHEME=OpenLDAP
|
||||
ADLDAP_AUTO_CONNECT=true
|
||||
|
||||
# LDAP connection settings
|
||||
ADLDAP_CONTROLLERS=
|
||||
ADLDAP_PORT=389
|
||||
ADLDAP_TIMEOUT=5
|
||||
ADLDAP_BASEDN=""
|
||||
ADLDAP_FOLLOW_REFFERALS=false
|
||||
ADLDAP_USE_SSL=false
|
||||
ADLDAP_USE_TLS=false
|
||||
|
||||
ADLDAP_ADMIN_USERNAME=
|
||||
ADLDAP_ADMIN_PASSWORD=
|
||||
|
||||
ADLDAP_ACCOUNT_PREFIX=
|
||||
ADLDAP_ACCOUNT_SUFFIX=
|
||||
ADLDAP_ADMIN_ACCOUNT_PREFIX=
|
||||
ADLDAP_ADMIN_ACCOUNT_SUFFIX=
|
||||
|
||||
# LDAP authentication settings.
|
||||
ADLDAP_PASSWORD_SYNC=false
|
||||
ADLDAP_LOGIN_FALLBACK=false
|
||||
|
||||
ADLDAP_DISCOVER_FIELD=distinguishedname
|
||||
ADLDAP_AUTH_FIELD=distinguishedname
|
||||
|
||||
# Will allow SSO if your server provides an AUTH_USER field.
|
||||
WINDOWS_SSO_DISCOVER=samaccountname
|
||||
WINDOWS_SSO_KEY=AUTH_USER
|
||||
|
||||
# field to sync as local username.
|
||||
ADLDAP_SYNC_FIELD=userprincipalname
|
||||
|
||||
# You can disable the X-Frame-Options header if it interfears with tools like
|
||||
# Organizr. This is at your own risk.
|
||||
DISABLE_FRAME_HEADER=true
|
||||
|
||||
# Leave the following configuration vars as is.
|
||||
# Unless you like to tinker and know what you're doing.
|
||||
APP_NAME=FireflyIII
|
||||
ADLDAP_CONNECTION=default
|
||||
BROADCAST_DRIVER=log
|
||||
QUEUE_DRIVER=sync
|
||||
REDIS_HOST=127.0.0.1
|
||||
@@ -105,7 +169,6 @@ DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
IS_DOCKER=false
|
||||
IS_SANDSTORM=true
|
||||
BUNQ_USE_SANDBOX=false
|
||||
IS_HEROKU=false
|
||||
MAILGUN_DOMAIN=
|
||||
MAILGUN_SECRET=
|
||||
BUNQ_USE_SANDBOX=false
|
||||
FFIII_LAYOUT=v1
|
||||
|
||||
97
.env.testing
97
.env.testing
@@ -17,32 +17,51 @@ APP_KEY=TestTestTestTestTestTestTestTest
|
||||
# Example: Europe/Amsterdam
|
||||
TZ=Europe/Amsterdam
|
||||
|
||||
# APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy.
|
||||
# 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.
|
||||
TRUSTED_PROXIES=
|
||||
|
||||
# The log channel defines where your log entries go to.
|
||||
LOG_CHANNEL=dailytest
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html
|
||||
DB_CONNECTION=sqlite
|
||||
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# Several other options exist. You can use 'single' for one big fat error log (not recommended).
|
||||
# Also available are 'syslog' and 'errorlog' which will log to the system itself.
|
||||
APP_LOG=daily
|
||||
# Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself.
|
||||
LOG_CHANNEL=dailytest
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=debug
|
||||
APP_LOG_LEVEL=info
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html
|
||||
DB_CONNECTION=sqlite
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# If you're looking for performance improvements, you could install memcached.
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
# You can configure another file storage backend if you cannot use the local storage option.
|
||||
# To set this up, fill in the following variables. The upload path is used to store uploaded
|
||||
# files and the export path is to store exported data (before download).
|
||||
SFTP_HOST=
|
||||
SFTP_PORT=
|
||||
SFTP_UPLOAD_PATH=
|
||||
SFTP_EXPORT_PATH=
|
||||
|
||||
# SFTP uses either the username/password combination or the private key to authenticate.
|
||||
SFTP_USERNAME=
|
||||
SFTP_PASSWORD=
|
||||
SFTP_PRIV_KEY=
|
||||
|
||||
# Cookie settings. Should not be necessary to change these.
|
||||
COOKIE_PATH="/"
|
||||
COOKIE_DOMAIN=
|
||||
@@ -64,6 +83,12 @@ MAILGUN_SECRET=
|
||||
MANDRILL_SECRET=
|
||||
SPARKPOST_SECRET=
|
||||
|
||||
# Firefly III can send you the following messages
|
||||
SEND_REGISTRATION_MAIL=true
|
||||
SEND_ERROR_MESSAGE=false
|
||||
|
||||
# These messages contain (sensitive) transaction information:
|
||||
SEND_REPORT_JOURNALS=true
|
||||
|
||||
# Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places.
|
||||
MAPBOX_API_KEY=
|
||||
@@ -80,9 +105,56 @@ ANALYTICS_ID=
|
||||
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
||||
USE_ENCRYPTION=false
|
||||
|
||||
# Firefly III has two options for user authentication. "eloquent" is the default,
|
||||
# and "adldap" for LDAP servers.
|
||||
# For full instructions on these settings please visit:
|
||||
# https://firefly-iii.readthedocs.io/en/latest/installation/authentication.html
|
||||
LOGIN_PROVIDER=eloquent
|
||||
|
||||
# LDAP connection configuration
|
||||
# or FreeIPA or ActiveDirectory
|
||||
ADLDAP_CONNECTION_SCHEME=OpenLDAP
|
||||
ADLDAP_AUTO_CONNECT=true
|
||||
|
||||
# LDAP connection settings
|
||||
ADLDAP_CONTROLLERS=
|
||||
ADLDAP_PORT=389
|
||||
ADLDAP_TIMEOUT=5
|
||||
ADLDAP_BASEDN=""
|
||||
ADLDAP_FOLLOW_REFFERALS=false
|
||||
ADLDAP_USE_SSL=false
|
||||
ADLDAP_USE_TLS=false
|
||||
|
||||
ADLDAP_ADMIN_USERNAME=
|
||||
ADLDAP_ADMIN_PASSWORD=
|
||||
|
||||
ADLDAP_ACCOUNT_PREFIX=
|
||||
ADLDAP_ACCOUNT_SUFFIX=
|
||||
ADLDAP_ADMIN_ACCOUNT_PREFIX=
|
||||
ADLDAP_ADMIN_ACCOUNT_SUFFIX=
|
||||
|
||||
# LDAP authentication settings.
|
||||
ADLDAP_PASSWORD_SYNC=false
|
||||
ADLDAP_LOGIN_FALLBACK=false
|
||||
|
||||
ADLDAP_DISCOVER_FIELD=distinguishedname
|
||||
ADLDAP_AUTH_FIELD=distinguishedname
|
||||
|
||||
# Will allow SSO if your server provides an AUTH_USER field.
|
||||
WINDOWS_SSO_DISCOVER=samaccountname
|
||||
WINDOWS_SSO_KEY=AUTH_USER
|
||||
|
||||
# field to sync as local username.
|
||||
ADLDAP_SYNC_FIELD=userprincipalname
|
||||
|
||||
# You can disable the X-Frame-Options header if it interfears with tools like
|
||||
# Organizr. This is at your own risk.
|
||||
DISABLE_FRAME_HEADER=false
|
||||
|
||||
# Leave the following configuration vars as is.
|
||||
# Unless you like to tinker and know what you're doing.
|
||||
APP_NAME=FireflyIII
|
||||
ADLDAP_CONNECTION=default
|
||||
BROADCAST_DRIVER=log
|
||||
QUEUE_DRIVER=sync
|
||||
REDIS_HOST=127.0.0.1
|
||||
@@ -97,7 +169,6 @@ DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
IS_DOCKER=false
|
||||
IS_SANDSTORM=false
|
||||
BUNQ_USE_SANDBOX=true
|
||||
IS_HEROKU=false
|
||||
MAILGUN_DOMAIN=
|
||||
MAILGUN_SECRET=
|
||||
BUNQ_USE_SANDBOX=true
|
||||
FFIII_LAYOUT=v1
|
||||
|
||||
5
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
5
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@@ -12,6 +12,9 @@ I am running Firefly III version x.x.x
|
||||
**Steps to reproduce**
|
||||
What do you need to do to trigger this bug?
|
||||
|
||||
**Expected behavior**
|
||||
What do you expect to see after those steps?
|
||||
|
||||
**Extra info**
|
||||
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).
|
||||
|
||||
@@ -19,4 +22,4 @@ Please add extra info here, such as OS, browser, and the output from the /debug
|
||||
Earn bonus points by:
|
||||
|
||||
- Post a stacktrace from your log files
|
||||
- Add a screenshot
|
||||
- Add a screenshot
|
||||
|
||||
9
.locales
Normal file
9
.locales
Normal file
@@ -0,0 +1,9 @@
|
||||
en_US
|
||||
de_DE
|
||||
fr_FR
|
||||
it_IT
|
||||
nl_NL
|
||||
pl_PL
|
||||
pt_BR
|
||||
ru_RU
|
||||
tr_TR
|
||||
@@ -1,4 +1,167 @@
|
||||
# 4.7.5.2
|
||||
# 4.7.9
|
||||
- [Issue 1622](https://github.com/firefly-iii/firefly-iii/issues/1622) Can now unlink a transaction from a bill.
|
||||
- [Issue 1848](https://github.com/firefly-iii/firefly-iii/issues/1848) Added support for the Swiss Franc.
|
||||
- [Issue 1828](https://github.com/firefly-iii/firefly-iii/issues/1828) Focus on fields for easy access.
|
||||
- [Issue 1859](https://github.com/firefly-iii/firefly-iii/issues/1859) Warning when seeding database.
|
||||
- Completely rewritten API. Check out the documentation [here](https://api-docs.firefly-iii.org/).
|
||||
- Currencies can now be enabled and disabled, making for cleaner views.
|
||||
- You can disable the `X-Frame-Options` header if this is necessary.
|
||||
- New fancy favicons.
|
||||
- Updated and improved docker build.
|
||||
- Docker build no longer builds its own cURL.
|
||||
- [Issue 1607](https://github.com/firefly-iii/firefly-iii/issues/1607) [issue 1857](https://github.com/firefly-iii/firefly-iii/issues/1857) [issue 1895](https://github.com/firefly-iii/firefly-iii/issues/1895) Improved bunq import and added support for auto-savings.
|
||||
- [Issue 1766](https://github.com/firefly-iii/firefly-iii/issues/1766) Extra commands so cache dir is owned by www user.
|
||||
- [Issue 1811](https://github.com/firefly-iii/firefly-iii/issues/1811) 404 when generating report without options.
|
||||
- [Issue 1835](https://github.com/firefly-iii/firefly-iii/issues/1835) Strange debug popup removed.
|
||||
- [Issue 1840](https://github.com/firefly-iii/firefly-iii/issues/1840) Error when exporting data.
|
||||
- [Issue 1857](https://github.com/firefly-iii/firefly-iii/issues/1857) Bunq import words again (see above).
|
||||
- [Issue 1858](https://github.com/firefly-iii/firefly-iii/issues/1858) SQL errors when importing CSV.
|
||||
- [Issue 1861](https://github.com/firefly-iii/firefly-iii/issues/1861) Period navigator was broken.
|
||||
- [Issue 1864](https://github.com/firefly-iii/firefly-iii/issues/1864) First description was empty on split transactions.
|
||||
- [Issue 1865](https://github.com/firefly-iii/firefly-iii/issues/1865) Bad math when showing categories.
|
||||
- [Issue 1868](https://github.com/firefly-iii/firefly-iii/issues/1868) Fixes to FinTS import.
|
||||
- [Issue 1872](https://github.com/firefly-iii/firefly-iii/issues/1872) Some images had 404's.
|
||||
- [Issue 1877](https://github.com/firefly-iii/firefly-iii/issues/1877) Several encryption / decryption issues.
|
||||
- [Issue 1878](https://github.com/firefly-iii/firefly-iii/issues/1878) Wrong nav links
|
||||
- [Issue 1884](https://github.com/firefly-iii/firefly-iii/issues/1884) Budget API improvements (see above)
|
||||
- [Issue 1888](https://github.com/firefly-iii/firefly-iii/issues/1888) Transaction API improvements (see above)
|
||||
- [Issue 1890](https://github.com/firefly-iii/firefly-iii/issues/1890) Fixes in Bills API
|
||||
- [Issue 1891](https://github.com/firefly-iii/firefly-iii/issues/1891) Typo fixed.
|
||||
- [Issue 1893](https://github.com/firefly-iii/firefly-iii/issues/1893) Update piggies from recurring transactions.
|
||||
- [Issue 1898](https://github.com/firefly-iii/firefly-iii/issues/1898) Bug in tag report.
|
||||
- [Issue 1901](https://github.com/firefly-iii/firefly-iii/issues/1901) Redirect when cloning transactions.
|
||||
- [Issue 1909](https://github.com/firefly-iii/firefly-iii/issues/1909) Date range fixes.
|
||||
- [Issue 1916](https://github.com/firefly-iii/firefly-iii/issues/1916) Date range fixes.
|
||||
|
||||
# 4.7.8
|
||||
|
||||
- [Issue 1005](https://github.com/firefly-iii/firefly-iii/issues/1005) You can now configure Firefly III to use LDAP.
|
||||
- [Issue 1071](https://github.com/firefly-iii/firefly-iii/issues/1071) You can execute transaction rules using the command line (so you can cronjob it)
|
||||
- [Issue 1108](https://github.com/firefly-iii/firefly-iii/issues/1108) You can now reorder budgets.
|
||||
- [Issue 1159](https://github.com/firefly-iii/firefly-iii/issues/1159) The ability to import transactions from FinTS-enabled banks.
|
||||
- [Issue 1727](https://github.com/firefly-iii/firefly-iii/issues/1727) You can now use SFTP as storage for uploads and exports.
|
||||
- [Issue 1733](https://github.com/firefly-iii/firefly-iii/issues/1733) You can configure Firefly III not to send emails with transaction information in them.
|
||||
- [Issue 1040](https://github.com/firefly-iii/firefly-iii/issues/1040) Fixed various things that would not scale properly in the past.
|
||||
- [Issue 1771](https://github.com/firefly-iii/firefly-iii/issues/1771) A link to the transaction that fits the bill.
|
||||
- [Issue 1800](https://github.com/firefly-iii/firefly-iii/issues/1800) Icon updated to match others.
|
||||
- MySQL database connection now forces the InnoDB to be used.
|
||||
- [Issue 1583](https://github.com/firefly-iii/firefly-iii/issues/1583) Some times recurring transactions would not fire.
|
||||
- [Issue 1607](https://github.com/firefly-iii/firefly-iii/issues/1607) Problems with the bunq API, finally solved?! (I feel like a clickbait YouTube video now)
|
||||
- [Issue 1698](https://github.com/firefly-iii/firefly-iii/issues/1698) Certificate problems in the Docker container
|
||||
- [Issue 1751](https://github.com/firefly-iii/firefly-iii/issues/1751) Bug in autocomplete
|
||||
- [Issue 1760](https://github.com/firefly-iii/firefly-iii/issues/1760) Tag report bad math
|
||||
- [Issue 1765](https://github.com/firefly-iii/firefly-iii/issues/1765) API inconsistencies for piggy banks.
|
||||
- [Issue 1774](https://github.com/firefly-iii/firefly-iii/issues/1774) Integer exception in SQLite databases
|
||||
- [Issue 1775](https://github.com/firefly-iii/firefly-iii/issues/1775) Heroku now supports all locales
|
||||
- [Issue 1778](https://github.com/firefly-iii/firefly-iii/issues/1778) More autocomplete problems fixed
|
||||
- [Issue 1747](https://github.com/firefly-iii/firefly-iii/issues/1747) Rules now stop at the right moment.
|
||||
- [Issue 1781](https://github.com/firefly-iii/firefly-iii/issues/1781) Problems when creating new rules.
|
||||
- [Issue 1784](https://github.com/firefly-iii/firefly-iii/issues/1784) Can now create a liability with an empty balance.
|
||||
- [Issue 1785](https://github.com/firefly-iii/firefly-iii/issues/1785) Redirect error
|
||||
- [Issue 1790](https://github.com/firefly-iii/firefly-iii/issues/1790) Show attachments for bills.
|
||||
- [Issue 1792](https://github.com/firefly-iii/firefly-iii/issues/1792) Mention excluded accounts.
|
||||
- [Issue 1798](https://github.com/firefly-iii/firefly-iii/issues/1798) Could not recreate deleted piggy banks
|
||||
- [Issue 1805](https://github.com/firefly-iii/firefly-iii/issues/1805) Fixes when handling foreign currencies
|
||||
- [Issue 1807](https://github.com/firefly-iii/firefly-iii/issues/1807) Also decrypt deleted records.
|
||||
- [Issue 1812](https://github.com/firefly-iii/firefly-iii/issues/1812) Fix in transactions API
|
||||
- [Issue 1815](https://github.com/firefly-iii/firefly-iii/issues/1815) Opening balance account name can now be translated.
|
||||
- [Issue 1830](https://github.com/firefly-iii/firefly-iii/issues/1830) Multi-user in a single browser could leak autocomplete data.
|
||||
|
||||
# 4.7.7
|
||||
- [Issue 954](https://github.com/firefly-iii/firefly-iii/issues/954) Some additional view chart ranges
|
||||
- [Issue 1710](https://github.com/firefly-iii/firefly-iii/issues/1710) Added a new currency ([hamuz](https://github.com/hamuz))
|
||||
- Transactions will now store (in the database) how they were created.
|
||||
- [Issue 907](https://github.com/firefly-iii/firefly-iii/issues/907) Better and more options on the transaction list.
|
||||
- [Issue 1450](https://github.com/firefly-iii/firefly-iii/issues/1450) Add a rule to change the type of a transaction automagically
|
||||
- [Issue 1701](https://github.com/firefly-iii/firefly-iii/issues/1701) Fix reference to PHP executable ([hertzg](https://github.com/hertzg))
|
||||
- Budget limits have currency information, for future expansion.
|
||||
- Some charts and pages can handle multiple currencies better.
|
||||
- New GA code for those who use it.
|
||||
- The credit card liability type has been removed.
|
||||
- [Issue 896](https://github.com/firefly-iii/firefly-iii/issues/896) Better redirection when coming from deleted objects.
|
||||
- [Issue 1519](https://github.com/firefly-iii/firefly-iii/issues/1519) Fix autocomplete tags
|
||||
- [Issue 1607](https://github.com/firefly-iii/firefly-iii/issues/1607) Some fixes for the bunq api calls
|
||||
- [Issue 1650](https://github.com/firefly-iii/firefly-iii/issues/1650) Add a negated amount column for CSV imports ([hamuz](https://github.com/hamuz))
|
||||
- [Issue 1658](https://github.com/firefly-iii/firefly-iii/issues/1658) Make font heavy again.
|
||||
- [Issue 1660](https://github.com/firefly-iii/firefly-iii/issues/1660) Add a negated amount column for CSV imports ([hamuz](https://github.com/hamuz))
|
||||
- [Issue 1667](https://github.com/firefly-iii/firefly-iii/issues/1667) Fix pie charts
|
||||
- [Issue 1668](https://github.com/firefly-iii/firefly-iii/issues/1668) YNAB iso_code fix
|
||||
- [Issue 1670](https://github.com/firefly-iii/firefly-iii/issues/1670) Fix piggy bank API error
|
||||
- [Issue 1671](https://github.com/firefly-iii/firefly-iii/issues/1671) More options for liability accounts.
|
||||
- [Issue 1673](https://github.com/firefly-iii/firefly-iii/issues/1673) Fix reconciliation issues.
|
||||
- [Issue 1675](https://github.com/firefly-iii/firefly-iii/issues/1675) Wrong sum in tag report.
|
||||
- [Issue 1679](https://github.com/firefly-iii/firefly-iii/issues/1679) Change type of a transaction wouldn't trigger rules.
|
||||
- [Issue 1682](https://github.com/firefly-iii/firefly-iii/issues/1682) Add liability accounts to transaction conversion
|
||||
- [Issue 1683](https://github.com/firefly-iii/firefly-iii/issues/1683) See matching transaction showed transfers twice.
|
||||
- [Issue 1685](https://github.com/firefly-iii/firefly-iii/issues/1685) fix autocomplete for rules
|
||||
- [Issue 1690](https://github.com/firefly-iii/firefly-iii/issues/1690) Missing highlighted button in intro popup
|
||||
- [Issue 1691](https://github.com/firefly-iii/firefly-iii/issues/1691) No mention of liabilities in demo text
|
||||
- [Issue 1695](https://github.com/firefly-iii/firefly-iii/issues/1695) Small fixes in bills pages.
|
||||
- [Issue 1708](https://github.com/firefly-iii/firefly-iii/issues/1708) Fix by [mathieupost](https://github.com/mathieupost) for bunq
|
||||
- [Issue 1709](https://github.com/firefly-iii/firefly-iii/issues/1709) Fix oauth buttons
|
||||
- [Issue 1712](https://github.com/firefly-iii/firefly-iii/issues/1712) Double slash fix by [hamuz](https://github.com/hamuz)
|
||||
- [Issue 1719](https://github.com/firefly-iii/firefly-iii/issues/1719) Add missing accounts to API
|
||||
- [Issue 1720](https://github.com/firefly-iii/firefly-iii/issues/1720) Fix validation for transaction type.
|
||||
- [Issue 1723](https://github.com/firefly-iii/firefly-iii/issues/1723) API broken for currency exchange rates.
|
||||
- [Issue 1728](https://github.com/firefly-iii/firefly-iii/issues/1728) Fix problem with transaction factory.
|
||||
- [Issue 1729](https://github.com/firefly-iii/firefly-iii/issues/1729) Fix bulk transaction editor
|
||||
- [Issue 1731](https://github.com/firefly-iii/firefly-iii/issues/1731) API failure for budget limits.
|
||||
- Secure headers now allow Mapbox and the 2FA QR code.
|
||||
|
||||
# 4.7.6.2
|
||||
- Docker file builds again.
|
||||
- Fix CSS of OAuth2 authorization view.
|
||||
|
||||
# 4.7.6.1
|
||||
- An issue where I switched variables from the Docker `.env` file to the normal `.env` file and vice versa -- breaking both.
|
||||
- [Issue 1649](https://github.com/firefly-iii/firefly-iii/issues/1649) 2FA QR code would not show up due to very strict security policy headers
|
||||
- Docker build gave a cURL error whenever it runs PHP commands.
|
||||
|
||||
# 4.7.6
|
||||
- [Issue 145](https://github.com/firefly-iii/firefly-iii/issues/145) You can now download transactions from YNAB.
|
||||
- [Issue 306](https://github.com/firefly-iii/firefly-iii/issues/306) You can now add liabilities to Firefly III.
|
||||
- [Issue 740](https://github.com/firefly-iii/firefly-iii/issues/740) Various charts are now currency aware.
|
||||
- [Issue 833](https://github.com/firefly-iii/firefly-iii/issues/833) Bills can use non-default currencies.
|
||||
- [Issue 1578](https://github.com/firefly-iii/firefly-iii/issues/1578) Firefly III will notify you if the cron job hasn't fired.
|
||||
- [Issue 1623](https://github.com/firefly-iii/firefly-iii/issues/1623) New transactions will link back from the success message.
|
||||
- [Issue 1624](https://github.com/firefly-iii/firefly-iii/issues/1624) transactions will link to the object.
|
||||
- You can call the cron job over the web now (see docs).
|
||||
- You don't need to call the cron job every minute any more.
|
||||
- Various charts are now red/green to signify income and expenses.
|
||||
- Option to add or remove accounts from the net worth calculations.
|
||||
- This will be the last release on PHP 7.1. Future versions will require PHP 7.2.
|
||||
- [Issue 1460](https://github.com/firefly-iii/firefly-iii/issues/1460) Downloading transactions from bunq should go more smoothly.
|
||||
- [Issue 1464](https://github.com/firefly-iii/firefly-iii/issues/1464) Fixed the docker file to work on Raspberry Pi's.
|
||||
- [Issue 1540](https://github.com/firefly-iii/firefly-iii/issues/1540) The Docker file now has a working cron job for recurring transactions.
|
||||
- [Issue 1564](https://github.com/firefly-iii/firefly-iii/issues/1564) Fix double transfers when importing from bunq.
|
||||
- [Issue 1575](https://github.com/firefly-iii/firefly-iii/issues/1575) Some views would give a XSRF token warning
|
||||
- [Issue 1576](https://github.com/firefly-iii/firefly-iii/issues/1576) Fix assigning budgets
|
||||
- [Issue 1580](https://github.com/firefly-iii/firefly-iii/issues/1580) Missing string for translation
|
||||
- [Issue 1581](https://github.com/firefly-iii/firefly-iii/issues/1581) Expand help text
|
||||
- [Issue 1584](https://github.com/firefly-iii/firefly-iii/issues/1584) Link to administration is back.
|
||||
- [Issue 1586](https://github.com/firefly-iii/firefly-iii/issues/1586) Date fields in import were mislabeled.
|
||||
- [Issue 1593](https://github.com/firefly-iii/firefly-iii/issues/1593) Link types are translatable.
|
||||
- [Issue 1594](https://github.com/firefly-iii/firefly-iii/issues/1594) Very long breadcrumbs are weird.
|
||||
- [Issue 1598](https://github.com/firefly-iii/firefly-iii/issues/1598) Fix budget calculations.
|
||||
- [Issue 1597](https://github.com/firefly-iii/firefly-iii/issues/1597) Piggy banks are always inactive.
|
||||
- [Issue 1605](https://github.com/firefly-iii/firefly-iii/issues/1605) System will ignore foreign currency setting if user doesn't indicate the amount.
|
||||
- [Issue 1608](https://github.com/firefly-iii/firefly-iii/issues/1608) Spelling error in command line import.
|
||||
- [Issue 1609](https://github.com/firefly-iii/firefly-iii/issues/1609) Link to budgets page was absolute.
|
||||
- [Issue 1615](https://github.com/firefly-iii/firefly-iii/issues/1615) Fix currency bug in transactions.
|
||||
- [Issue 1616](https://github.com/firefly-iii/firefly-iii/issues/1616) Fix null pointer exception in pie charts.
|
||||
- [Issue 1617](https://github.com/firefly-iii/firefly-iii/issues/1617) Fix for complex tag names in URL's.
|
||||
- [Issue 1620](https://github.com/firefly-iii/firefly-iii/issues/1620) Fixed index reference in API.
|
||||
- [Issue 1639](https://github.com/firefly-iii/firefly-iii/issues/1639) Firefly III trusts the Heroku load balancer, fixing deployment on Heroku.
|
||||
- [Issue 1642](https://github.com/firefly-iii/firefly-iii/issues/1642) Fix issue with split journals.
|
||||
- [Issue 1643](https://github.com/firefly-iii/firefly-iii/issues/1643) Fix reconciliation issue.
|
||||
- Users can no longer give income a budget.
|
||||
- Fix bug in Spectre import.
|
||||
- Heroku would not make you owner.
|
||||
- Add `.htaccess` files to all public directories.
|
||||
- New secure headers will make Firefly III slightly more secure.
|
||||
- The rule "tester" will now also take the "strict"-checkbox into account.
|
||||
|
||||
# 4.7.5.3
|
||||
- [Issue 1527](https://github.com/firefly-iii/firefly-iii/issues/1527), fixed views for transactions without a budget.
|
||||
- [Issue 1553](https://github.com/firefly-iii/firefly-iii/issues/1553), report could not handle transactions before the first one in the system.
|
||||
- [Issue 1549](https://github.com/firefly-iii/firefly-iii/issues/1549) update a budget will also update any rules that refer to that budget.
|
||||
|
||||
@@ -37,15 +37,15 @@ HOME=/etc/mysql /usr/bin/mysql_install_db --force
|
||||
# Spawn mysqld, php
|
||||
HOME=/etc/mysql /usr/sbin/mysqld &
|
||||
|
||||
/usr/sbin/php-fpm7.1 --nodaemonize --fpm-config /etc/php/7.1/fpm/php-fpm.conf &
|
||||
/usr/sbin/php-fpm7.2 --nodaemonize --fpm-config /etc/php/7.2/fpm/php-fpm.conf &
|
||||
|
||||
# Wait until mysql and php have bound their sockets, indicating readiness
|
||||
while [ ! -e /var/run/mysqld/mysqld.sock ] ; do
|
||||
echo "waiting for mysql to be available at /var/run/mysqld/mysqld.sock"
|
||||
sleep .5
|
||||
done
|
||||
while [ ! -e /var/run/php7.1-fpm.sock ] ; do
|
||||
echo "waiting for php7.1-fpm to be available at /var/run/php7.1-fpm.sock"
|
||||
while [ ! -e /var/run/php7.2-fpm.sock ] ; do
|
||||
echo "waiting for php7.2-fpm to be available at /var/run/php7.2-fpm.sock"
|
||||
sleep .5
|
||||
done
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,8 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
|
||||
manifest = (
|
||||
appTitle = (defaultText = "Firefly III"),
|
||||
appVersion = 15,
|
||||
appMarketingVersion = (defaultText = "4.7.5.2"),
|
||||
appVersion = 19,
|
||||
appMarketingVersion = (defaultText = "4.7.9"),
|
||||
|
||||
actions = [
|
||||
# Define your "new document" handlers here.
|
||||
|
||||
@@ -53,7 +53,7 @@ http {
|
||||
}
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_pass unix:/var/run/php7.1-fpm.sock;
|
||||
fastcgi_pass unix:/var/run/php7.2-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -38,37 +38,37 @@ echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sou
|
||||
|
||||
# install packages.
|
||||
apt-get update
|
||||
apt-get install -y nginx php7.1-fpm php7.1-mysql php7.1-gd php7.1-cli php7.1-curl git php7.1-dev php7.1-zip php7.1-intl php7.1-dom php7.1-mbstring php7.1-bcmath mysql-server
|
||||
apt-get install -y nginx php7.2-fpm php7.2-mysql php7.2-gd php7.2-cli php7.2-curl git php7.2-dev php7.2-zip php7.2-intl php7.2-dom php7.2-mbstring php7.2-bcmath mysql-server
|
||||
service nginx stop
|
||||
service php7.1-fpm stop
|
||||
service php7.2-fpm stop
|
||||
service mysql stop
|
||||
systemctl disable nginx
|
||||
systemctl disable php7.1-fpm
|
||||
systemctl disable php7.2-fpm
|
||||
systemctl disable mysql
|
||||
|
||||
# make php.ini display errors:
|
||||
sed -i 's/display_errors = Off/display_errors = On/g' /etc/php/7.1/fpm/php.ini
|
||||
sed -i 's/display_errors = Off/display_errors = On/g' /etc/php/7.2/fpm/php.ini
|
||||
|
||||
# patch /etc/php/7.1/fpm/pool.d/www.conf to not change uid/gid to www-data
|
||||
# patch /etc/php/7.2/fpm/pool.d/www.conf to not change uid/gid to www-data
|
||||
sed --in-place='' \
|
||||
--expression='s/^listen.owner = www-data/;listen.owner = www-data/' \
|
||||
--expression='s/^listen.group = www-data/;listen.group = www-data/' \
|
||||
/etc/php/7.1/fpm/pool.d/www.conf
|
||||
# patch /etc/php/7.1/fpm/php-fpm.conf to not have a pidfile
|
||||
/etc/php/7.2/fpm/pool.d/www.conf
|
||||
# patch /etc/php/7.2/fpm/php-fpm.conf to not have a pidfile
|
||||
sed --in-place='' \
|
||||
--expression='s/^pid =/;pid =/' \
|
||||
/etc/php/7.1/fpm/php-fpm.conf
|
||||
/etc/php/7.2/fpm/php-fpm.conf
|
||||
|
||||
# move sock file to better dir:
|
||||
sed --in-place='' \
|
||||
--expression='s/^listen = \/run\/php\/php7.1-fpm.sock/listen = \/var\/run\/php7.1-fpm.sock/' \
|
||||
/etc/php/7.1/fpm/pool.d/www.conf
|
||||
--expression='s/^listen = \/run\/php\/php7.2-fpm.sock/listen = \/var\/run\/php7.2-fpm.sock/' \
|
||||
/etc/php/7.2/fpm/pool.d/www.conf
|
||||
|
||||
# patch /etc/php/7.1/fpm/pool.d/www.conf to no clear environment variables
|
||||
# patch /etc/php/7.2/fpm/pool.d/www.conf to no clear environment variables
|
||||
# so we can pass in SANDSTORM=1 to apps
|
||||
sed --in-place='' \
|
||||
--expression='s/^;clear_env = no/clear_env=no/' \
|
||||
/etc/php/7.1/fpm/pool.d/www.conf
|
||||
/etc/php/7.2/fpm/pool.d/www.conf
|
||||
# patch mysql conf to not change uid, and to use /var/tmp over /tmp
|
||||
# for secure-file-priv see https://github.com/sandstorm-io/vagrant-spk/issues/195
|
||||
sed --in-place='' \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
language: php
|
||||
php:
|
||||
- 7.1.18
|
||||
- 7.2
|
||||
|
||||
cache:
|
||||
directories:
|
||||
|
||||
96
Dockerfile
96
Dockerfile
@@ -1,12 +1,12 @@
|
||||
# use PHP 7.1 and Apache as a base.
|
||||
FROM php:7.1-apache
|
||||
FROM php:7.2-apache
|
||||
|
||||
# set working dir
|
||||
ENV FIREFLY_PATH /var/www/firefly-iii
|
||||
ENV CURL_VERSION 7.60.0
|
||||
ENV OPENSSL_VERSION 1.1.1-pre6
|
||||
WORKDIR $FIREFLY_PATH
|
||||
ADD . $FIREFLY_PATH
|
||||
# If building on a RPi, use --build-arg cores=3 to use all cores when compiling
|
||||
# to speed up the image build
|
||||
ARG CORES
|
||||
ENV CORES ${CORES:-1}
|
||||
|
||||
ENV FIREFLY_PATH=/var/www/firefly-iii/ CURL_VERSION=7.60.0 OPENSSL_VERSION=1.1.1-pre6 COMPOSER_ALLOW_SUPERUSER=1
|
||||
LABEL version="1.2" maintainer="thegrumpydictator@gmail.com"
|
||||
|
||||
# install packages
|
||||
RUN apt-get update -y && \
|
||||
@@ -16,61 +16,60 @@ RUN apt-get update -y && \
|
||||
wget \
|
||||
libpng-dev \
|
||||
libicu-dev \
|
||||
libldap2-dev \
|
||||
libedit-dev \
|
||||
libtidy-dev \
|
||||
libxml2-dev \
|
||||
unzip \
|
||||
libsqlite3-dev \
|
||||
nano \
|
||||
curl \
|
||||
openssl \
|
||||
libpq-dev \
|
||||
libbz2-dev \
|
||||
gettext-base \
|
||||
cron \
|
||||
rsyslog \
|
||||
supervisor \
|
||||
locales && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Setup the Composer installer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Install latest curl
|
||||
RUN cd /tmp && \
|
||||
wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz && \
|
||||
tar -xvf openssl-${OPENSSL_VERSION}.tar.gz && \
|
||||
cd openssl-${OPENSSL_VERSION} && \
|
||||
./config && \
|
||||
make && \
|
||||
make install
|
||||
|
||||
RUN cd /tmp && \
|
||||
wget https://curl.haxx.se/download/curl-${CURL_VERSION}.tar.gz && \
|
||||
tar -xvf curl-${CURL_VERSION}.tar.gz && \
|
||||
cd curl-${CURL_VERSION} && \
|
||||
./configure --with-ssl && \
|
||||
make && \
|
||||
make install
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/ && \
|
||||
docker-php-ext-install ldap
|
||||
|
||||
|
||||
# Create the log file to be able to run tail
|
||||
RUN touch /var/log/cron.log
|
||||
# Make sure that libcurl is using the newer curl libaries
|
||||
#RUN echo "/usr/local/lib" >> /etc/ld.so.conf.d/00-curl.conf && ldconfig
|
||||
|
||||
# Setup cron job
|
||||
RUN (crontab -l ; echo "* * * * * root $FIREFLY_PATH/artisan schedule:run >> /var/log/cron.log") | crontab
|
||||
# Mimic the Debian/Ubuntu config file structure for supervisor
|
||||
COPY .deploy/docker/supervisord.conf /etc/supervisor/supervisord.conf
|
||||
RUN mkdir -p /etc/supervisor/conf.d /var/log/supervisor
|
||||
|
||||
# Install PHP exentions.
|
||||
RUN docker-php-ext-install -j$(nproc) curl gd intl json readline tidy zip bcmath xml mbstring pdo_sqlite pdo_mysql bz2 pdo_pgsql
|
||||
# copy Firefly III supervisor conf file.
|
||||
COPY ./.deploy/docker/firefly-iii.conf /etc/supervisor/conf.d/firefly-iii.conf
|
||||
|
||||
# Generate locales supported by Firefly III
|
||||
RUN echo "en_US.UTF-8 UTF-8\nde_DE.UTF-8 UTF-8\nfr_FR.UTF-8 UTF-8\nit_IT.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npl_PL.UTF-8 UTF-8\npt_BR.UTF-8 UTF-8\nru_RU.UTF-8 UTF-8\ntr_TR.UTF-8 UTF-8\n\n" > /etc/locale.gen && locale-gen
|
||||
# copy cron job supervisor conf file.
|
||||
COPY ./.deploy/docker/cronjob.conf /etc/supervisor/conf.d/cronjob.conf
|
||||
|
||||
# copy ca certs to correct location
|
||||
COPY ./.deploy/docker/cacert.pem /usr/local/ssl/cert.pem
|
||||
|
||||
# test crons added via crontab
|
||||
RUN echo "0 3 * * * /usr/local/bin/php /var/www/firefly-iii/artisan firefly:cron" | crontab -
|
||||
#RUN (crontab -l ; echo "*/1 * * * * free >> /var/www/firefly-iii/public/cron.html") 2>&1 | crontab -
|
||||
|
||||
# Install PHP exentions, install composer, update languages.
|
||||
RUN docker-php-ext-install -j$(nproc) gd intl tidy zip curl bcmath pdo_mysql bz2 pdo_pgsql && \
|
||||
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \
|
||||
echo "en_US.UTF-8 UTF-8\nde_DE.UTF-8 UTF-8\nfr_FR.UTF-8 UTF-8\nit_IT.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npl_PL.UTF-8 UTF-8\npt_BR.UTF-8 UTF-8\nru_RU.UTF-8 UTF-8\ntr_TR.UTF-8 UTF-8\n\n" > /etc/locale.gen && locale-gen
|
||||
|
||||
# copy Apache config to correct spot.
|
||||
COPY ./.deploy/docker/apache2.conf /etc/apache2/apache2.conf
|
||||
|
||||
# Enable apache mod rewrite..
|
||||
RUN a2enmod rewrite
|
||||
# Enable apache mod rewrite and mod ssl..
|
||||
RUN a2enmod rewrite && a2enmod ssl
|
||||
|
||||
# Enable apache mod ssl..
|
||||
RUN a2enmod ssl
|
||||
|
||||
# Create volumes for several directories:
|
||||
# Create volumes
|
||||
VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload
|
||||
|
||||
# Enable default site (Firefly III)
|
||||
@@ -79,15 +78,18 @@ COPY ./.deploy/docker/apache-firefly.conf /etc/apache2/sites-available/000-defau
|
||||
# Make sure we own Firefly III directory
|
||||
RUN chown -R www-data:www-data /var/www && chmod -R 775 $FIREFLY_PATH/storage
|
||||
|
||||
# Copy in Firefly Source
|
||||
WORKDIR $FIREFLY_PATH
|
||||
ADD . $FIREFLY_PATH
|
||||
|
||||
# Fix the link to curl:
|
||||
#RUN rm -rf /usr/local/lib/libcurl.so.4 && ln -s /usr/lib/x86_64-linux-gnu/libcurl.so.4.4.0 /usr/local/lib/libcurl.so.4
|
||||
|
||||
# Run composer
|
||||
RUN composer install --prefer-dist --no-dev --no-scripts --no-suggest
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
# Run the command on container startup
|
||||
CMD cron
|
||||
|
||||
# Run entrypoint thing
|
||||
ENTRYPOINT [".deploy/docker/entrypoint.sh"]
|
||||
|
||||
|
||||
3
app.json
3
app.json
@@ -51,6 +51,9 @@
|
||||
"buildpacks": [
|
||||
{
|
||||
"url": "heroku/php"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/heroku/heroku-buildpack-locale"
|
||||
}
|
||||
],
|
||||
"env": {
|
||||
|
||||
@@ -75,7 +75,12 @@ class AboutController extends Controller
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item(auth()->user(), new UserTransformer($this->parameters), 'users');
|
||||
|
||||
/** @var UserTransformer $transformer */
|
||||
$transformer = app(UserTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item(auth()->user(), $transformer, 'users');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
@@ -24,15 +24,21 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\AccountRequest;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
@@ -46,8 +52,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
*/
|
||||
class AccountController extends Controller
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface The currency repository */
|
||||
private $currencyRepository;
|
||||
use AccountFilter, TransactionFilter;
|
||||
/** @var AccountRepositoryInterface The account repository */
|
||||
private $repository;
|
||||
|
||||
@@ -65,9 +70,6 @@ class AccountController extends Controller
|
||||
$this->repository = app(AccountRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
|
||||
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
||||
$this->currencyRepository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
@@ -105,7 +107,7 @@ class AccountController extends Controller
|
||||
$this->parameters->set('type', $type);
|
||||
|
||||
// types to get, page size:
|
||||
$types = $this->mapTypes($this->parameters->get('type'));
|
||||
$types = $this->mapAccountTypes($this->parameters->get('type'));
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of accounts. Count it and split it.
|
||||
@@ -119,12 +121,58 @@ class AccountController extends Controller
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($accounts, new AccountTransformer($this->parameters), 'accounts');
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($accounts, $transformer, 'accounts');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Account $account
|
||||
*
|
||||
* @return JsonResponse]
|
||||
*/
|
||||
public function piggyBanks(Request $request, Account $account): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of budgets. Count it and split it.
|
||||
$collection = $this->repository->getPiggyBanks($account);
|
||||
$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.accounts.piggy_banks', [$account->id]) . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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.
|
||||
*
|
||||
@@ -136,14 +184,13 @@ class AccountController extends Controller
|
||||
public function show(Request $request, Account $account): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($account, new AccountTransformer($this->parameters), 'accounts');
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($account, $transformer, 'accounts');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -157,18 +204,74 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function store(AccountRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
// if currency ID is 0, find the currency by the code:
|
||||
if (0 === $data['currency_id']) {
|
||||
$currency = $this->currencyRepository->findByCodeNull($data['currency_code']);
|
||||
$data['currency_id'] = null === $currency ? 0 : $currency->id;
|
||||
}
|
||||
$data = $request->getAll();
|
||||
$account = $this->repository->store($data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($account, new AccountTransformer($this->parameters), 'accounts');
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($account, $transformer, 'accounts');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Account $account
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function transactions(Request $request, Account $account): 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 = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($admin);
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
if ($this->repository->isAsset($account)) {
|
||||
$collector->setAccounts(new Collection([$account]));
|
||||
}
|
||||
if (!$this->repository->isAsset($account)) {
|
||||
$collector->setOpposingAccounts(new Collection([$account]));
|
||||
}
|
||||
|
||||
if (\in_array(TransactionType::TRANSFER, $types, true)) {
|
||||
$collector->removeFilter(InternalTransferFilter::class);
|
||||
}
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedTransactions();
|
||||
$paginator->setPath(route('api.v1.accounts.transactions', [$account->id]) . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::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');
|
||||
}
|
||||
@@ -183,60 +286,18 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function update(AccountRequest $request, Account $account): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
// if currency ID is 0, find the currency by the code:
|
||||
if (0 === $data['currency_id']) {
|
||||
$currency = $this->currencyRepository->findByCodeNull($data['currency_code']);
|
||||
$data['currency_id'] = null === $currency ? 0 : $currency->id;
|
||||
}
|
||||
// set correct type:
|
||||
$data = $request->getAll();
|
||||
$data['type'] = config('firefly.shortNamesByFullName.' . $account->accountType->type);
|
||||
$this->repository->update($account, $data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($account, new AccountTransformer($this->parameters), 'accounts');
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($account, $transformer, 'accounts');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* All the available types.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mapTypes(string $type): array
|
||||
{
|
||||
$types = [
|
||||
'all' => [AccountType::DEFAULT, AccountType::CASH, AccountType::ASSET, AccountType::EXPENSE, AccountType::REVENUE,
|
||||
AccountType::INITIAL_BALANCE, AccountType::BENEFICIARY, AccountType::IMPORT, AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,],
|
||||
'asset' => [AccountType::DEFAULT, AccountType::ASSET,],
|
||||
'cash' => [AccountType::CASH,],
|
||||
'expense' => [AccountType::EXPENSE, AccountType::BENEFICIARY,],
|
||||
'revenue' => [AccountType::REVENUE,],
|
||||
'special' => [AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,],
|
||||
'hidden' => [AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION, AccountType::LOAN,],
|
||||
AccountType::DEFAULT => [AccountType::DEFAULT],
|
||||
AccountType::CASH => [AccountType::CASH],
|
||||
AccountType::ASSET => [AccountType::ASSET],
|
||||
AccountType::EXPENSE => [AccountType::EXPENSE],
|
||||
AccountType::REVENUE => [AccountType::REVENUE],
|
||||
AccountType::INITIAL_BALANCE => [AccountType::INITIAL_BALANCE],
|
||||
AccountType::BENEFICIARY => [AccountType::BENEFICIARY],
|
||||
AccountType::IMPORT => [AccountType::IMPORT],
|
||||
AccountType::RECONCILIATION => [AccountType::RECONCILIATION],
|
||||
AccountType::LOAN => [AccountType::LOAN],
|
||||
];
|
||||
$return = $types['all'];
|
||||
if (isset($types[$type])) {
|
||||
$return = $types[$type];
|
||||
}
|
||||
|
||||
return $return; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +144,12 @@ class AttachmentController extends Controller
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($attachments, new AttachmentTransformer($this->parameters), 'attachments');
|
||||
|
||||
/** @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');
|
||||
@@ -161,14 +166,14 @@ class AttachmentController extends Controller
|
||||
public function show(Request $request, Attachment $attachment): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($attachment, new AttachmentTransformer($this->parameters), 'attachments');
|
||||
|
||||
/** @var AttachmentTransformer $transformer */
|
||||
$transformer = app(AttachmentTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($attachment, $transformer, 'attachments');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -188,7 +193,12 @@ class AttachmentController extends Controller
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($attachment, new AttachmentTransformer($this->parameters), 'attachments');
|
||||
|
||||
/** @var AttachmentTransformer $transformer */
|
||||
$transformer = app(AttachmentTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($attachment, $transformer, 'attachments');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -209,7 +219,11 @@ class AttachmentController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($attachment, new AttachmentTransformer($this->parameters), 'attachments');
|
||||
/** @var AttachmentTransformer $transformer */
|
||||
$transformer = app(AttachmentTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($attachment, $transformer, 'attachments');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@ namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\AvailableBudgetRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Factory\TransactionCurrencyFactory;
|
||||
use FireflyIII\Models\AvailableBudget;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Transformers\AvailableBudgetTransformer;
|
||||
@@ -111,7 +113,12 @@ class AvailableBudgetController extends Controller
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($availableBudgets, new AvailableBudgetTransformer($this->parameters), 'available_budgets');
|
||||
|
||||
/** @var AvailableBudgetTransformer $transformer */
|
||||
$transformer = app(AvailableBudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($availableBudgets, $transformer, 'available_budgets');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
@@ -127,16 +134,15 @@ class AvailableBudgetController extends Controller
|
||||
*/
|
||||
public function show(Request $request, AvailableBudget $availableBudget): JsonResponse
|
||||
{
|
||||
|
||||
$manager = new Manager;
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($availableBudget, new AvailableBudgetTransformer($this->parameters), 'available_budgets');
|
||||
|
||||
/** @var AvailableBudgetTransformer $transformer */
|
||||
$transformer = app(AvailableBudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($availableBudget, $transformer, 'available_budgets');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -151,21 +157,29 @@ class AvailableBudgetController extends Controller
|
||||
*/
|
||||
public function store(AvailableBudgetRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$currency = $this->currencyRepository->findNull($data['transaction_currency_id']);
|
||||
$data = $request->getAll();
|
||||
/** @var TransactionCurrencyFactory $factory */
|
||||
$factory = app(TransactionCurrencyFactory::class);
|
||||
$currency = $factory->find($data['currency_id'], $data['currency_code']);
|
||||
|
||||
if (null === $currency) {
|
||||
throw new FireflyException('Could not find the indicated currency.');
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
}
|
||||
$availableBudget = $this->repository->setAvailableBudget($currency, $data['start_date'], $data['end_date'], $data['amount']);
|
||||
$availableBudget = $this->repository->setAvailableBudget($currency, $data['start'], $data['end'], $data['amount']);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($availableBudget, new AvailableBudgetTransformer($this->parameters), 'available_budgets');
|
||||
/** @var AvailableBudgetTransformer $transformer */
|
||||
$transformer = app(AvailableBudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($availableBudget, $transformer, 'available_budgets');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
@@ -177,12 +191,32 @@ class AvailableBudgetController extends Controller
|
||||
public function update(AvailableBudgetRequest $request, AvailableBudget $availableBudget): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
|
||||
/** @var TransactionCurrencyFactory $factory */
|
||||
$factory = app(TransactionCurrencyFactory::class);
|
||||
/** @var TransactionCurrency $currency */
|
||||
$currency = $factory->find($data['currency_id'] ?? null, $data['currency_code'] ?? null);
|
||||
|
||||
if (null === $currency) {
|
||||
// use default currency:
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
}
|
||||
$currency->enabled = true;
|
||||
$currency->save();
|
||||
unset($data['currency_code']);
|
||||
$data['currency_id'] = $currency->id;
|
||||
|
||||
|
||||
$this->repository->updateAvailableBudget($availableBudget, $data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($availableBudget, new AvailableBudgetTransformer($this->parameters), 'available_budgets');
|
||||
/** @var AvailableBudgetTransformer $transformer */
|
||||
$transformer = app(AvailableBudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($availableBudget, $transformer, 'available_budgets');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -26,12 +26,18 @@ namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\BillRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\BillTransformer;
|
||||
use FireflyIII\Transformers\RuleTransformer;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
@@ -44,6 +50,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
*/
|
||||
class BillController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var BillRepositoryInterface The bill repository */
|
||||
private $repository;
|
||||
|
||||
@@ -67,6 +74,43 @@ class BillController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function attachments(Request $request, Bill $bill): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$collection = $this->repository->getAttachments($bill);
|
||||
|
||||
$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.bills.attachments', [$bill->id]) . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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.
|
||||
*
|
||||
@@ -99,12 +143,56 @@ class BillController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new FractalCollection($bills, new BillTransformer($this->parameters), 'bills');
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($bills, $transformer, 'bills');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function rules(Request $request, Bill $bill): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of budgets. Count it and split it.
|
||||
$collection = $this->repository->getRulesForBill($bill);
|
||||
$count = $collection->count();
|
||||
$rules = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.bills.rules', [$bill->id]) . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var RuleTransformer $transformer */
|
||||
$transformer = app(RuleTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
|
||||
$resource = new FractalCollection($rules, $transformer, 'rules');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified bill.
|
||||
@@ -117,14 +205,14 @@ class BillController extends Controller
|
||||
public function show(Request $request, Bill $bill): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($bill, new BillTransformer($this->parameters), 'bills');
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($bill, $transformer, 'bills');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -145,7 +233,11 @@ class BillController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($bill, new BillTransformer($this->parameters), 'bills');
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($bill, $transformer, 'bills');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -153,6 +245,53 @@ class BillController extends Controller
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function transactions(Request $request, Bill $bill): 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 = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($admin);
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setAllAssetAccounts();
|
||||
$collector->setBills(new Collection([$bill]));
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedTransactions();
|
||||
$paginator->setPath(route('api.v1.bills.transactions', [$bill->id]) . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a bill.
|
||||
@@ -170,7 +309,11 @@ class BillController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($bill, new BillTransformer($this->parameters), 'bills');
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($bill, $transformer, 'bills');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -23,11 +23,16 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
|
||||
use FireflyIII\Api\V1\Requests\BudgetRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||
use FireflyIII\Transformers\BudgetTransformer;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -45,6 +50,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
*/
|
||||
class BudgetController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var BudgetRepositoryInterface The budget repository */
|
||||
private $repository;
|
||||
|
||||
@@ -68,6 +74,39 @@ class BudgetController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function budgetLimits(Request $request, Budget $budget): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$this->parameters->set('budget_id', $budget->id);
|
||||
$collection = $this->repository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end'));
|
||||
$count = $collection->count();
|
||||
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.budgets.budget_limits', [$budget->id]) . $this->buildParams());
|
||||
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var BudgetLimitTransformer $transformer */
|
||||
$transformer = app(BudgetLimitTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
|
||||
$resource = new FractalCollection($budgetLimits, $transformer, 'budget_limits');
|
||||
$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.
|
||||
*
|
||||
@@ -109,13 +148,17 @@ class BudgetController extends Controller
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($budgets, new BudgetTransformer($this->parameters), 'budgets');
|
||||
|
||||
/** @var BudgetTransformer $transformer */
|
||||
$transformer = app(BudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($budgets, $transformer, 'budgets');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show a budget.
|
||||
*
|
||||
@@ -127,14 +170,14 @@ class BudgetController extends Controller
|
||||
public function show(Request $request, Budget $budget): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($budget, new BudgetTransformer($this->parameters), 'budgets');
|
||||
/** @var BudgetTransformer $transformer */
|
||||
$transformer = app(BudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($budget, $transformer, 'budgets');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -155,13 +198,92 @@ class BudgetController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($budget, new BudgetTransformer($this->parameters), 'budgets');
|
||||
/** @var BudgetTransformer $transformer */
|
||||
$transformer = app(BudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($budget, $transformer, 'budgets');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
throw new FireflyException('Could not store new budget.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param BudgetLimitRequest $request
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function storeBudgetLimit(BudgetLimitRequest $request, Budget $budget): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$data['budget'] = $budget;
|
||||
$budgetLimit = $this->repository->storeBudgetLimit($data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var BudgetLimitTransformer $transformer */
|
||||
$transformer = app(BudgetLimitTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($budgetLimit, $transformer, 'budget_limits');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function transactions(Request $request, Budget $budget): 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 = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($admin);
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setAllAssetAccounts();
|
||||
$collector->setBudget($budget);
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
|
||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedTransactions();
|
||||
$paginator->setPath(route('api.v1.budgets.transactions', [$budget->id]) . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a budget.
|
||||
@@ -179,7 +301,11 @@ class BudgetController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($budget, new BudgetTransformer($this->parameters), 'budgets');
|
||||
/** @var BudgetTransformer $transformer */
|
||||
$transformer = app(BudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($budget, $transformer, 'budgets');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -26,15 +26,17 @@ namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
@@ -49,6 +51,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
*/
|
||||
class BudgetLimitController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var BudgetRepositoryInterface The budget repository */
|
||||
private $repository;
|
||||
|
||||
@@ -114,7 +117,12 @@ class BudgetLimitController extends Controller
|
||||
$paginator->setPath(route('api.v1.budget_limits.index') . $this->buildParams());
|
||||
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($budgetLimits, new BudgetLimitTransformer($this->parameters), 'budget_limits');
|
||||
|
||||
/** @var BudgetLimitTransformer $transformer */
|
||||
$transformer = app(BudgetLimitTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($budgetLimits, $transformer, 'budget_limits');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
@@ -131,14 +139,14 @@ class BudgetLimitController extends Controller
|
||||
public function show(Request $request, BudgetLimit $budgetLimit): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($budgetLimit, new BudgetLimitTransformer($this->parameters), 'budget_limits');
|
||||
|
||||
/** @var BudgetLimitTransformer $transformer */
|
||||
$transformer = app(BudgetLimitTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($budgetLimit, $transformer, 'budget_limits');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -164,7 +172,55 @@ class BudgetLimitController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($budgetLimit, new BudgetLimitTransformer($this->parameters), 'budget_limits');
|
||||
/** @var BudgetLimitTransformer $transformer */
|
||||
$transformer = app(BudgetLimitTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($budgetLimit, $transformer, 'budget_limits');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param BudgetLimit $budgetLimit
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function transactions(Request $request, BudgetLimit $budgetLimit): 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 = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($admin);
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setAllAssetAccounts();
|
||||
$collector->setBudget($budgetLimit->budget);
|
||||
$collector->setRange($budgetLimit->start_date, $budgetLimit->end_date);
|
||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedTransactions();
|
||||
$paginator->setPath(route('api.v1.budget_limits.transactions', [$budgetLimit->id]) . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::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');
|
||||
}
|
||||
@@ -179,18 +235,18 @@ class BudgetLimitController extends Controller
|
||||
*/
|
||||
public function update(BudgetLimitRequest $request, BudgetLimit $budgetLimit): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$budget = $this->repository->findNull($data['budget_id']);
|
||||
if (null === $budget) {
|
||||
$budget = $budgetLimit->budget;
|
||||
}
|
||||
$data['budget'] = $budget;
|
||||
$data = $request->getAll();
|
||||
$data['budget'] = $budgetLimit->budget;
|
||||
$budgetLimit = $this->repository->updateBudgetLimit($budgetLimit, $data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($budgetLimit, new BudgetLimitTransformer($this->parameters), 'budget_limits');
|
||||
/** @var BudgetLimitTransformer $transformer */
|
||||
$transformer = app(BudgetLimitTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($budgetLimit, $transformer, 'budget_limits');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -25,9 +25,14 @@ namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\CategoryRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\CategoryTransformer;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -45,6 +50,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
*/
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var CategoryRepositoryInterface The category repository */
|
||||
private $repository;
|
||||
|
||||
@@ -109,7 +115,13 @@ class CategoryController extends Controller
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($categories, new CategoryTransformer($this->parameters), 'categories');
|
||||
|
||||
/** @var CategoryTransformer $transformer */
|
||||
$transformer = app(CategoryTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
|
||||
$resource = new FractalCollection($categories, $transformer, 'categories');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
@@ -127,14 +139,14 @@ class CategoryController extends Controller
|
||||
public function show(Request $request, Category $category): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($category, new CategoryTransformer($this->parameters), 'categories');
|
||||
/** @var CategoryTransformer $transformer */
|
||||
$transformer = app(CategoryTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($category, $transformer, 'categories');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -155,13 +167,68 @@ class CategoryController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($category, new CategoryTransformer($this->parameters), 'categories');
|
||||
/** @var CategoryTransformer $transformer */
|
||||
$transformer = app(CategoryTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($category, $transformer, 'categories');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
throw new FireflyException('Could not store new category.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @param Category $category
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function transactions(Request $request, Category $category): 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 = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($admin);
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setAllAssetAccounts();
|
||||
$collector->setCategory($category);
|
||||
|
||||
if (\in_array(TransactionType::TRANSFER, $types, true)) {
|
||||
$collector->removeFilter(InternalTransferFilter::class);
|
||||
}
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedTransactions();
|
||||
$paginator->setPath(route('api.v1.categories.transactions', [$category->id]) . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the category.
|
||||
@@ -179,7 +246,11 @@ class CategoryController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($category, new CategoryTransformer($this->parameters), 'categories');
|
||||
/** @var CategoryTransformer $transformer */
|
||||
$transformer = app(CategoryTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($category, $transformer, 'categories');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -23,12 +23,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\ConfigurationRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Configuration;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Class ConfigurationController.
|
||||
@@ -54,6 +54,7 @@ class ConfigurationController extends Controller
|
||||
$admin = auth()->user();
|
||||
|
||||
if (!$this->repository->hasRole($admin, 'owner')) {
|
||||
/** @noinspection ExceptionsAnnotatingAndHandlingInspection */
|
||||
throw new FireflyException('No access to method.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
@@ -77,31 +78,17 @@ class ConfigurationController extends Controller
|
||||
/**
|
||||
* Update the configuration.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param ConfigurationRequest $request
|
||||
* @param string $name
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
public function update(Request $request): JsonResponse
|
||||
public function update(ConfigurationRequest $request, string $name): JsonResponse
|
||||
{
|
||||
$name = $request->get('name');
|
||||
$value = $request->get('value');
|
||||
$valid = ['is_demo_site', 'permission_update_check', 'single_user_mode'];
|
||||
if (!\in_array($name, $valid, true)) {
|
||||
throw new FireflyException('You cannot edit this configuration value.');
|
||||
}
|
||||
$configValue = '';
|
||||
switch ($name) {
|
||||
case 'is_demo_site':
|
||||
case 'single_user_mode':
|
||||
$configValue = 'true' === $value;
|
||||
break;
|
||||
case 'permission_update_check':
|
||||
$configValue = (int)$value >= -1 && (int)$value <= 1 ? (int)$value : -1;
|
||||
break;
|
||||
}
|
||||
app('fireflyconfig')->set($name, $configValue);
|
||||
$data = $request->getAll();
|
||||
app('fireflyconfig')->set($name, $data['value']);
|
||||
$configData = $this->getConfigData();
|
||||
|
||||
return response()->json(['data' => $configData], 200)->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
@@ -100,7 +100,7 @@ class Controller extends BaseController
|
||||
// some date fields:
|
||||
$dates = ['start', 'end', 'date'];
|
||||
foreach ($dates as $field) {
|
||||
$date = request()->get($field);
|
||||
$date = request()->query->get($field);
|
||||
$obj = null;
|
||||
if (null !== $date) {
|
||||
try {
|
||||
|
||||
@@ -26,14 +26,41 @@ namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\CurrencyRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AvailableBudget;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Models\RecurrenceTransaction;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleTrigger;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\AvailableBudgetTransformer;
|
||||
use FireflyIII\Transformers\BillTransformer;
|
||||
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||
use FireflyIII\Transformers\CurrencyExchangeRateTransformer;
|
||||
use FireflyIII\Transformers\CurrencyTransformer;
|
||||
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||
use FireflyIII\Transformers\RuleTransformer;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
@@ -47,6 +74,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
*/
|
||||
class CurrencyController extends Controller
|
||||
{
|
||||
use AccountFilter, TransactionFilter;
|
||||
/** @var CurrencyRepositoryInterface The currency repository */
|
||||
private $repository;
|
||||
/** @var UserRepositoryInterface The user repository */
|
||||
@@ -73,6 +101,241 @@ class CurrencyController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a list of accounts.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function accounts(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// read type from URI
|
||||
$type = $request->get('type') ?? 'all';
|
||||
$this->parameters->set('type', $type);
|
||||
|
||||
// types to get, page size:
|
||||
$types = $this->mapAccountTypes($this->parameters->get('type'));
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of accounts. Count it and split it.
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
$unfiltered = $accountRepository->getAccountsByType($types);
|
||||
|
||||
// filter list on currency preference:
|
||||
$collection = $unfiltered->filter(
|
||||
function (Account $account) use ($currency, $accountRepository) {
|
||||
$currencyId = (int)$accountRepository->getMetaValue($account, 'currency_id');
|
||||
|
||||
return $currencyId === $currency->id;
|
||||
}
|
||||
);
|
||||
|
||||
$count = $collection->count();
|
||||
$accounts = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.currencies.accounts', [$currency->code]) . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
|
||||
$resource = new FractalCollection($accounts, $transformer, 'accounts');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function availableBudgets(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of available budgets. Count it and split it.
|
||||
/** @var BudgetRepositoryInterface $repository */
|
||||
$repository = app(BudgetRepositoryInterface::class);
|
||||
$repository->setUser($admin);
|
||||
$unfiltered = $repository->getAvailableBudgets();
|
||||
|
||||
// filter list.
|
||||
$collection = $unfiltered->filter(
|
||||
function (AvailableBudget $availableBudget) use ($currency) {
|
||||
return $availableBudget->transaction_currency_id === $currency->id;
|
||||
}
|
||||
);
|
||||
|
||||
$count = $collection->count();
|
||||
$availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.currencies.available_budgets', [$currency->code]) . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var AvailableBudgetTransformer $transformer */
|
||||
$transformer = app(AvailableBudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($availableBudgets, $transformer, 'available_budgets');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* List all bills
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function bills(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
/** @var BillRepositoryInterface $repository */
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$paginator = $repository->getPaginator($pageSize);
|
||||
/** @var Collection $bills */
|
||||
$unfiltered = $paginator->getCollection();
|
||||
|
||||
// filter and paginate list:
|
||||
$collection = $unfiltered->filter(
|
||||
function (Bill $bill) use ($currency) {
|
||||
return $bill->transaction_currency_id === $currency->id;
|
||||
}
|
||||
);
|
||||
$count = $collection->count();
|
||||
$bills = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.currencies.bills', [$currency->code]) . $this->buildParams());
|
||||
|
||||
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($bills, $transformer, 'bills');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* List all budget limits
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function budgetLimits(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
/** @var BudgetRepositoryInterface $repository */
|
||||
$repository = app(BudgetRepositoryInterface::class);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$unfiltered = $repository->getAllBudgetLimits($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
|
||||
// TODO replace this
|
||||
// filter budget limits on currency ID
|
||||
$collection = $unfiltered->filter(
|
||||
function (BudgetLimit $budgetLimit) use ($currency) {
|
||||
return $budgetLimit->transaction_currency_id === $currency->id;
|
||||
}
|
||||
);
|
||||
|
||||
$count = $collection->count();
|
||||
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.currencies.budget_limits', [$currency->code]) . $this->buildParams());
|
||||
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var BudgetLimitTransformer $transformer */
|
||||
$transformer = app(BudgetLimitTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($budgetLimits, $transformer, 'budget_limits');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of known exchange rates
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function cer(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$collection = $this->repository->getExchangeRates($currency);
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
|
||||
$count = $collection->count();
|
||||
$exchangeRates = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
$paginator = new LengthAwarePaginator($exchangeRates, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.currencies.cer', [$currency->code]) . $this->buildParams());
|
||||
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var CurrencyExchangeRateTransformer $transformer */
|
||||
$transformer = app(CurrencyExchangeRateTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($exchangeRates, $transformer, 'currency_exchange_rates');
|
||||
$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.
|
||||
*
|
||||
@@ -90,7 +353,7 @@ class CurrencyController extends Controller
|
||||
// access denied:
|
||||
throw new FireflyException('No access to method, user is not owner.'); // @codeCoverageIgnore
|
||||
}
|
||||
if (!$this->repository->canDeleteCurrency($currency)) {
|
||||
if ($this->repository->currencyInUse($currency)) {
|
||||
throw new FireflyException('No access to method, currency is in use.'); // @codeCoverageIgnore
|
||||
}
|
||||
$this->repository->destroy($currency);
|
||||
@@ -98,6 +361,66 @@ class CurrencyController extends Controller
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable a currency.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function disable(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
// must be unused.
|
||||
if ($this->repository->currencyInUse($currency)) {
|
||||
return response()->json([], 409);
|
||||
}
|
||||
$this->repository->disable($currency);
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
||||
|
||||
/** @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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable a currency.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function enable(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$this->repository->enable($currency);
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
||||
|
||||
/** @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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
@@ -108,7 +431,7 @@ class CurrencyController extends Controller
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$collection = $this->repository->get();
|
||||
$collection = $this->repository->getAll();
|
||||
$count = $collection->count();
|
||||
// slice them:
|
||||
$currencies = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
@@ -122,12 +445,156 @@ class CurrencyController extends Controller
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
||||
|
||||
$resource = new FractalCollection($currencies, new CurrencyTransformer($this->parameters), 'currencies');
|
||||
/** @var CurrencyTransformer $transformer */
|
||||
$transformer = app(CurrencyTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($currencies, $transformer, 'currencies');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the currency a default currency.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function makeDefault(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$this->repository->enable($currency);
|
||||
|
||||
app('preferences')->set('currencyPreference', $currency->code);
|
||||
app('preferences')->mark();
|
||||
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List all recurring transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse]
|
||||
*/
|
||||
public function recurrences(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of budgets. Count it and split it.
|
||||
/** @var RecurringRepositoryInterface $repository */
|
||||
$repository = app(RecurringRepositoryInterface::class);
|
||||
$unfiltered = $repository->getAll();
|
||||
|
||||
// filter selection
|
||||
$collection = $unfiltered->filter(
|
||||
function (Recurrence $recurrence) use ($currency) {
|
||||
/** @var RecurrenceTransaction $transaction */
|
||||
foreach ($recurrence->recurrenceTransactions as $transaction) {
|
||||
if ($transaction->transaction_currency_id === $currency->id || $transaction->foreign_currency_id === $currency->id) {
|
||||
return $recurrence;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
$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.currencies.recurrences', [$currency->code]) . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($piggyBanks, $transformer, 'recurrences');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse]
|
||||
*/
|
||||
public function rules(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of budgets. Count it and split it.
|
||||
/** @var RuleRepositoryInterface $repository */
|
||||
$repository = app(RuleRepositoryInterface::class);
|
||||
$unfiltered = $repository->getAll();
|
||||
|
||||
$collection = $unfiltered->filter(
|
||||
function (Rule $rule) use ($currency) {
|
||||
/** @var RuleTrigger $trigger */
|
||||
foreach ($rule->ruleTriggers as $trigger) {
|
||||
if ('currency_is' === $trigger->trigger_type && $currency->name === $trigger->trigger_value) {
|
||||
return $rule;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
);
|
||||
|
||||
$count = $collection->count();
|
||||
$rules = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.rules.index') . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var RuleTransformer $transformer */
|
||||
$transformer = app(RuleTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($rules, $transformer, 'rules');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a currency.
|
||||
@@ -140,16 +607,16 @@ class CurrencyController extends Controller
|
||||
public function show(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
||||
|
||||
$resource = new Item($currency, new CurrencyTransformer($this->parameters), 'currencies');
|
||||
/** @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');
|
||||
}
|
||||
@@ -177,7 +644,11 @@ class CurrencyController extends Controller
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
||||
|
||||
$resource = new Item($currency, new CurrencyTransformer($this->parameters), 'currencies');
|
||||
/** @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');
|
||||
}
|
||||
@@ -185,6 +656,57 @@ class CurrencyController extends Controller
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function transactions(Request $request, TransactionCurrency $currency): 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 = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($admin);
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setAllAssetAccounts();
|
||||
$collector->setCurrency($currency);
|
||||
|
||||
if (\in_array(TransactionType::TRANSFER, $types, true)) {
|
||||
$collector->removeFilter(InternalTransferFilter::class);
|
||||
}
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedTransactions();
|
||||
$paginator->setPath(route('api.v1.currencies.transactions', [$currency->code]) . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a currency.
|
||||
@@ -211,7 +733,11 @@ class CurrencyController extends Controller
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
||||
|
||||
$resource = new Item($currency, new CurrencyTransformer($this->parameters), 'currencies');
|
||||
/** @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');
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ class CurrencyExchangeRateController extends Controller
|
||||
$this->parameters->set('from', $fromCurrency->code);
|
||||
$this->parameters->set('to', $toCurrency->code);
|
||||
$this->parameters->set('date', $dateObj->format('Y-m-d'));
|
||||
$this->parameters->set('amount', $request->get('amount'));
|
||||
|
||||
$rate = $this->repository->getExchangeRate($fromCurrency, $toCurrency, $dateObj);
|
||||
if (null === $rate) {
|
||||
@@ -103,8 +104,10 @@ class CurrencyExchangeRateController extends Controller
|
||||
$service->setUser($admin);
|
||||
$rate = $service->getRate($fromCurrency, $toCurrency, $dateObj);
|
||||
}
|
||||
|
||||
$resource = new Item($rate, new CurrencyExchangeRateTransformer($this->parameters), 'currency_exchange_rates');
|
||||
/** @var CurrencyExchangeRateTransformer $transformer */
|
||||
$transformer = app(CurrencyExchangeRateTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($rate, $transformer, 'currency_exchange_rates');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
184
app/Api/V1/Controllers/ImportController.php
Normal file
184
app/Api/V1/Controllers/ImportController.php
Normal file
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
/**
|
||||
* ImportController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\ImportJobTransformer;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class ImportController
|
||||
*/
|
||||
class ImportController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var ImportJobRepositoryInterface Import job repository. */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* LinkTypeController constructor.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function listAll(Request $request): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$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());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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 Request $request
|
||||
* @param ImportJob $importJob
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(Request $request, ImportJob $importJob): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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 ImportJob $importJob
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
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 = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$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();
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($admin);
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setAllAssetAccounts();
|
||||
$collector->setTag($tag);
|
||||
|
||||
if (\in_array(TransactionType::TRANSFER, $types, true)) {
|
||||
$collector->removeFilter(InternalTransferFilter::class);
|
||||
}
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedTransactions();
|
||||
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
}
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::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');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,10 +25,15 @@ namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\LinkTypeRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
use FireflyIII\Models\LinkType;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\LinkTypeTransformer;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -46,6 +51,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
*/
|
||||
class LinkTypeController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var LinkTypeRepositoryInterface The link type repository */
|
||||
private $repository;
|
||||
|
||||
@@ -114,7 +120,12 @@ class LinkTypeController extends Controller
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($linkTypes, new LinkTypeTransformer($this->parameters), 'link_types');
|
||||
|
||||
/** @var LinkTypeTransformer $transformer */
|
||||
$transformer = app(LinkTypeTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($linkTypes, $transformer, 'link_types');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
@@ -132,14 +143,13 @@ class LinkTypeController extends Controller
|
||||
public function show(Request $request, LinkType $linkType): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($linkType, new LinkTypeTransformer($this->parameters), 'link_types');
|
||||
/** @var LinkTypeTransformer $transformer */
|
||||
$transformer = app(LinkTypeTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($linkType, $transformer, 'link_types');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
@@ -168,12 +178,69 @@ class LinkTypeController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($linkType, new LinkTypeTransformer($this->parameters), 'link_types');
|
||||
/** @var LinkTypeTransformer $transformer */
|
||||
$transformer = app(LinkTypeTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($linkType, $transformer, 'link_types');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the resource.
|
||||
*
|
||||
* @param LinkType $linkType
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function transactions(Request $request, LinkType $linkType): 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 = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// whatever is returned by the query, it must be part of these journals:
|
||||
$journalIds = $this->repository->getJournalIds($linkType);
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($admin);
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setAllAssetAccounts();
|
||||
$collector->setJournalIds($journalIds);
|
||||
|
||||
if (\in_array(TransactionType::TRANSFER, $types, true)) {
|
||||
$collector->removeFilter(InternalTransferFilter::class);
|
||||
}
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedTransactions();
|
||||
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::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');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update object.
|
||||
*
|
||||
@@ -202,7 +269,11 @@ class LinkTypeController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($linkType, new LinkTypeTransformer($this->parameters), 'link_types');
|
||||
/** @var LinkTypeTransformer $transformer */
|
||||
$transformer = app(LinkTypeTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($linkType, $transformer, 'link_types');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ use FireflyIII\Api\V1\Requests\PiggyBankRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Transformers\PiggyBankEventTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -110,7 +111,47 @@ class PiggyBankController extends Controller
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($piggyBanks, new PiggyBankTransformer($this->parameters), 'piggy_banks');
|
||||
|
||||
/** @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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function piggyBankEvents(Request $request, PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$collection = $this->repository->getEvents($piggyBank);
|
||||
$count = $collection->count();
|
||||
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.piggy_banks.events', [$piggyBank->id]) . $this->buildParams());
|
||||
|
||||
/** @var PiggyBankEventTransformer $transformer */
|
||||
$transformer = app(PiggyBankEventTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($events, $transformer, 'piggy_bank_events');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
@@ -128,14 +169,14 @@ class PiggyBankController extends Controller
|
||||
public function show(Request $request, PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($piggyBank, new PiggyBankTransformer($this->parameters), 'piggy_banks');
|
||||
/** @var PiggyBankTransformer $transformer */
|
||||
$transformer = app(PiggyBankTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($piggyBank, $transformer, 'piggy_banks');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
@@ -157,11 +198,15 @@ class PiggyBankController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($piggyBank, new PiggyBankTransformer($this->parameters), 'piggy_banks');
|
||||
/** @var PiggyBankTransformer $transformer */
|
||||
$transformer = app(PiggyBankTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($piggyBank, $transformer, 'piggy_banks');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
throw new FireflyException('Could not store new piggy bank.'); // @codeCoverageIgnore
|
||||
throw new FireflyException('Could not store new piggy bank.');
|
||||
|
||||
}
|
||||
|
||||
@@ -180,7 +225,11 @@ class PiggyBankController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($piggyBank, new PiggyBankTransformer($this->parameters), 'piggy_banks');
|
||||
/** @var PiggyBankTransformer $transformer */
|
||||
$transformer = app(PiggyBankTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($piggyBank, $transformer, 'piggy_banks');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -71,35 +71,18 @@ class PreferenceController extends Controller
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($preferences, new PreferenceTransformer($this->parameters), 'preferences');
|
||||
|
||||
/** @var PreferenceTransformer $transformer */
|
||||
$transformer = app(PreferenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($preferences, $transformer, 'preferences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Preference $preference
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(Request $request, Preference $preference): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($preference, new PreferenceTransformer($this->parameters), 'preferences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a preference.
|
||||
*
|
||||
@@ -137,7 +120,11 @@ class PreferenceController extends Controller
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($result, new PreferenceTransformer($this->parameters), 'preferences');
|
||||
/** @var PreferenceTransformer $transformer */
|
||||
$transformer = app(PreferenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($result, $transformer, 'preferences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -24,9 +24,16 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\RecurrenceRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\Cronjobs\RecurringCronjob;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -36,12 +43,14 @@ use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RecurrenceController
|
||||
*/
|
||||
class RecurrenceController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var RecurringRepositoryInterface The recurring transaction repository */
|
||||
private $repository;
|
||||
|
||||
@@ -106,7 +115,12 @@ class RecurrenceController extends Controller
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($piggyBanks, new RecurrenceTransformer($this->parameters), 'recurrences');
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($piggyBanks, $transformer, 'recurrences');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
@@ -124,14 +138,14 @@ class RecurrenceController extends Controller
|
||||
public function show(Request $request, Recurrence $recurrence): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($recurrence, new RecurrenceTransformer($this->parameters), 'recurrences');
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($recurrence, $transformer, 'recurrences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
@@ -151,11 +165,94 @@ class RecurrenceController extends Controller
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($recurrence, new RecurrenceTransformer($this->parameters), 'recurrences');
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($recurrence, $transformer, 'recurrences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show transactions for this recurrence.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Recurrence $recurrence
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function transactions(Request $request, Recurrence $recurrence): 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 = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// whatever is returned by the query, it must be part of these journals:
|
||||
$journalIds = $this->repository->getJournalIds($recurrence);
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($admin);
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setAllAssetAccounts();
|
||||
$collector->setJournalIds($journalIds);
|
||||
|
||||
if (\in_array(TransactionType::TRANSFER, $types, true)) {
|
||||
$collector->removeFilter(InternalTransferFilter::class);
|
||||
}
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedTransactions();
|
||||
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::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');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function trigger(): JsonResponse
|
||||
{
|
||||
/** @var RecurringCronjob $recurring */
|
||||
$recurring = app(RecurringCronjob::class);
|
||||
try {
|
||||
$result = $recurring->fire();
|
||||
} catch (FireflyException $e) {
|
||||
Log::error($e->getMessage());
|
||||
throw new FireflyException('Could not fire recurring cron job.');
|
||||
}
|
||||
if (false === $result) {
|
||||
return response()->json([], 204);
|
||||
}
|
||||
if (true === $result) {
|
||||
return response()->json([], 200);
|
||||
}
|
||||
|
||||
return response()->json([], 418); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
* Update single recurrence.
|
||||
*
|
||||
@@ -171,8 +268,11 @@ class RecurrenceController extends Controller
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($category, new RecurrenceTransformer($this->parameters), 'recurrences');
|
||||
$resource = new Item($category, $transformer, 'recurrences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -23,25 +23,36 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Requests\RuleRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Jobs\ExecuteRuleOnExistingTransactions;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\TransactionRules\TransactionMatcher;
|
||||
use FireflyIII\Transformers\RuleTransformer;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RuleController
|
||||
*/
|
||||
class RuleController extends Controller
|
||||
{
|
||||
/** @var AccountRepositoryInterface Account repository */
|
||||
private $accountRepository;
|
||||
/** @var RuleRepositoryInterface The rule repository */
|
||||
private $ruleRepository;
|
||||
|
||||
@@ -59,6 +70,9 @@ class RuleController extends Controller
|
||||
$this->ruleRepository = app(RuleRepositoryInterface::class);
|
||||
$this->ruleRepository->setUser($user);
|
||||
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
$this->accountRepository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
@@ -101,11 +115,16 @@ class RuleController extends Controller
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.piggy_banks.index') . $this->buildParams());
|
||||
$paginator->setPath(route('api.v1.rules.index') . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($rules, new RuleTransformer($this->parameters), 'rules');
|
||||
|
||||
/** @var RuleTransformer $transformer */
|
||||
$transformer = app(RuleTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($rules, $transformer, 'rules');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
@@ -123,14 +142,14 @@ class RuleController extends Controller
|
||||
public function show(Request $request, Rule $rule): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($rule, new RuleTransformer($this->parameters), 'rules');
|
||||
/** @var RuleTransformer $transformer */
|
||||
$transformer = app(RuleTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($rule, $transformer, 'rules');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
@@ -150,11 +169,127 @@ class RuleController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($rule, new RuleTransformer($this->parameters), 'rules');
|
||||
/** @var RuleTransformer $transformer */
|
||||
$transformer = app(RuleTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($rule, $transformer, 'rules');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function testRule(Request $request, Rule $rule): JsonResponse
|
||||
{
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$page = 0 === (int)$request->query('page') ? 1 : (int)$request->query('page');
|
||||
$startDate = null === $request->query('start_date') ? null : Carbon::createFromFormat('Y-m-d', $request->query('start_date'));
|
||||
$endDate = null === $request->query('end_date') ? null : Carbon::createFromFormat('Y-m-d', $request->query('end_date'));
|
||||
$searchLimit = 0 === (int)$request->query('search_limit') ? (int)config('firefly.test-triggers.limit') : (int)$request->query('search_limit');
|
||||
$triggerLimit = 0 === (int)$request->query('triggered_limit') ? (int)config('firefly.test-triggers.range') : (int)$request->query('triggered_limit');
|
||||
$accountList = '' === (string)$request->query('accounts') ? [] : explode(',', $request->query('accounts'));
|
||||
$accounts = new Collection;
|
||||
|
||||
foreach ($accountList as $accountId) {
|
||||
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
|
||||
$account = $this->accountRepository->findNull((int)$accountId);
|
||||
if (null !== $account && AccountType::ASSET === $account->accountType->type) {
|
||||
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
|
||||
$accounts->push($account);
|
||||
}
|
||||
if (null === $account) {
|
||||
Log::debug(sprintf('No asset account with id "%s"', $accountId));
|
||||
}
|
||||
}
|
||||
|
||||
/** @var Rule $rule */
|
||||
Log::debug(sprintf('Now testing rule #%d, "%s"', $rule->id, $rule->title));
|
||||
/** @var TransactionMatcher $matcher */
|
||||
$matcher = app(TransactionMatcher::class);
|
||||
// set all parameters:
|
||||
$matcher->setRule($rule);
|
||||
$matcher->setStartDate($startDate);
|
||||
$matcher->setEndDate($endDate);
|
||||
$matcher->setSearchLimit($searchLimit);
|
||||
$matcher->setTriggeredLimit($triggerLimit);
|
||||
$matcher->setAccounts($accounts);
|
||||
|
||||
$matchingTransactions = $matcher->findTransactionsByRule();
|
||||
$matchingTransactions = $matchingTransactions->unique('id');
|
||||
|
||||
// make paginator out of results.
|
||||
$count = $matchingTransactions->count();
|
||||
$transactions = $matchingTransactions->slice(($page - 1) * $pageSize, $pageSize);
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($transactions, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.rules.test', [$rule->id]) . $this->buildParams());
|
||||
|
||||
// resulting list is presented as JSON thing.
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($matchingTransactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given rule group on a set of existing transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function triggerRule(Request $request, Rule $rule): JsonResponse
|
||||
{
|
||||
// Get parameters specified by the user
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$startDate = new Carbon($request->get('start_date'));
|
||||
$endDate = new Carbon($request->get('end_date'));
|
||||
$accountList = '' === (string)$request->query('accounts') ? [] : explode(',', $request->query('accounts'));
|
||||
$accounts = new Collection;
|
||||
|
||||
foreach ($accountList as $accountId) {
|
||||
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
|
||||
$account = $this->accountRepository->findNull((int)$accountId);
|
||||
if (null !== $account && $this->accountRepository->isAsset($account)) {
|
||||
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
|
||||
$accounts->push($account);
|
||||
}
|
||||
if (null === $account) {
|
||||
Log::debug(sprintf('No asset account with id "%s"', $accountId));
|
||||
}
|
||||
}
|
||||
|
||||
// Create a job to do the work asynchronously
|
||||
$job = new ExecuteRuleOnExistingTransactions($rule);
|
||||
|
||||
// Apply parameters to the job
|
||||
$job->setUser($user);
|
||||
$job->setAccounts($accounts);
|
||||
$job->setStartDate($startDate);
|
||||
$job->setEndDate($endDate);
|
||||
|
||||
// Dispatch a new job to execute it in a queue
|
||||
$this->dispatch($job);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a rule.
|
||||
*
|
||||
@@ -170,7 +305,11 @@ class RuleController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($rule, new RuleTransformer($this->parameters), 'rules');
|
||||
/** @var RuleTransformer $transformer */
|
||||
$transformer = app(RuleTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($rule, $transformer, 'rules');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -23,19 +23,30 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Requests\RuleGroupRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Jobs\ExecuteRuleOnExistingTransactions;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
use FireflyIII\TransactionRules\TransactionMatcher;
|
||||
use FireflyIII\Transformers\RuleGroupTransformer;
|
||||
use FireflyIII\Transformers\RuleTransformer;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Log;
|
||||
|
||||
|
||||
/**
|
||||
@@ -43,6 +54,8 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
*/
|
||||
class RuleGroupController extends Controller
|
||||
{
|
||||
/** @var AccountRepositoryInterface Account repository */
|
||||
private $accountRepository;
|
||||
/** @var RuleGroupRepositoryInterface The rule group repository */
|
||||
private $ruleGroupRepository;
|
||||
|
||||
@@ -60,6 +73,9 @@ class RuleGroupController extends Controller
|
||||
$this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
|
||||
$this->ruleGroupRepository->setUser($user);
|
||||
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
$this->accountRepository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
@@ -95,7 +111,7 @@ class RuleGroupController extends Controller
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of budgets. Count it and split it.
|
||||
// get list of rule groups. Count it and split it.
|
||||
$collection = $this->ruleGroupRepository->get();
|
||||
$count = $collection->count();
|
||||
$ruleGroups = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
@@ -106,12 +122,55 @@ class RuleGroupController extends Controller
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($ruleGroups, new RuleGroupTransformer($this->parameters), 'rule_groups');
|
||||
|
||||
/** @var RuleGroupTransformer $transformer */
|
||||
$transformer = app(RuleGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($ruleGroups, $transformer, 'rule_groups');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param RuleGroup $group
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function rules(Request $request, RuleGroup $group): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of budgets. Count it and split it.
|
||||
$collection = $this->ruleGroupRepository->getRules($group);
|
||||
$count = $collection->count();
|
||||
$rules = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.rule_groups.rules', [$group->id]) . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var RuleTransformer $transformer */
|
||||
$transformer = app(RuleTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($rules, $transformer, 'rules');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
@@ -123,14 +182,14 @@ class RuleGroupController extends Controller
|
||||
public function show(Request $request, RuleGroup $ruleGroup): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($ruleGroup, new RuleGroupTransformer($this->parameters), 'rule_groups');
|
||||
/** @var RuleGroupTransformer $transformer */
|
||||
$transformer = app(RuleGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($ruleGroup, $transformer, 'rule_groups');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
@@ -150,14 +209,146 @@ class RuleGroupController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($ruleGroup, new RuleGroupTransformer($this->parameters), 'rule_groups');
|
||||
/** @var RuleGroupTransformer $transformer */
|
||||
$transformer = app(RuleGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($ruleGroup, $transformer, 'rule_groups');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param RuleGroup $group
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function testGroup(Request $request, RuleGroup $group): JsonResponse
|
||||
{
|
||||
Log::debug('Now in testGroup()');
|
||||
/** @var Collection $rules */
|
||||
$rules = $this->ruleGroupRepository->getActiveRules($group);
|
||||
if (0 === $rules->count()) {
|
||||
throw new FireflyException('No rules in this rule group.');
|
||||
}
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$page = 0 === (int)$request->query('page') ? 1 : (int)$request->query('page');
|
||||
$startDate = null === $request->query('start_date') ? null : Carbon::createFromFormat('Y-m-d', $request->query('start_date'));
|
||||
$endDate = null === $request->query('end_date') ? null : Carbon::createFromFormat('Y-m-d', $request->query('end_date'));
|
||||
$searchLimit = 0 === (int)$request->query('search_limit') ? (int)config('firefly.test-triggers.limit') : (int)$request->query('search_limit');
|
||||
$triggerLimit = 0 === (int)$request->query('triggered_limit') ? (int)config('firefly.test-triggers.range') : (int)$request->query('triggered_limit');
|
||||
$accountList = '' === (string)$request->query('accounts') ? [] : explode(',', $request->query('accounts'));
|
||||
$accounts = new Collection;
|
||||
|
||||
foreach ($accountList as $accountId) {
|
||||
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
|
||||
$account = $this->accountRepository->findNull((int)$accountId);
|
||||
if (null !== $account && AccountType::ASSET === $account->accountType->type) {
|
||||
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
|
||||
$accounts->push($account);
|
||||
}
|
||||
if (null === $account) {
|
||||
Log::debug(sprintf('No asset account with id "%s"', $accountId));
|
||||
}
|
||||
}
|
||||
|
||||
$matchingTransactions = new Collection;
|
||||
Log::debug(sprintf('Going to test %d rules', $rules->count()));
|
||||
/** @var Rule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
Log::debug(sprintf('Now testing rule #%d, "%s"', $rule->id, $rule->title));
|
||||
/** @var TransactionMatcher $matcher */
|
||||
$matcher = app(TransactionMatcher::class);
|
||||
// set all parameters:
|
||||
$matcher->setRule($rule);
|
||||
$matcher->setStartDate($startDate);
|
||||
$matcher->setEndDate($endDate);
|
||||
$matcher->setSearchLimit($searchLimit);
|
||||
$matcher->setTriggeredLimit($triggerLimit);
|
||||
$matcher->setAccounts($accounts);
|
||||
|
||||
$result = $matcher->findTransactionsByRule();
|
||||
$matchingTransactions = $result->merge($matchingTransactions);
|
||||
}
|
||||
$matchingTransactions = $matchingTransactions->unique('id');
|
||||
|
||||
// make paginator out of results.
|
||||
$count = $matchingTransactions->count();
|
||||
$transactions = $matchingTransactions->slice(($page - 1) * $pageSize, $pageSize);
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($transactions, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.rule_groups.test', [$group->id]) . $this->buildParams());
|
||||
|
||||
// resulting list is presented as JSON thing.
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($matchingTransactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given rule group on a set of existing transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param RuleGroup $group
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function triggerGroup(Request $request, RuleGroup $group): JsonResponse
|
||||
{
|
||||
// Get parameters specified by the user
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$startDate = new Carbon($request->get('start_date'));
|
||||
$endDate = new Carbon($request->get('end_date'));
|
||||
$accountList = '' === (string)$request->query('accounts') ? [] : explode(',', $request->query('accounts'));
|
||||
$accounts = new Collection;
|
||||
|
||||
foreach ($accountList as $accountId) {
|
||||
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
|
||||
$account = $this->accountRepository->findNull((int)$accountId);
|
||||
if (null !== $account && AccountType::ASSET === $account->accountType->type) {
|
||||
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
|
||||
$accounts->push($account);
|
||||
}
|
||||
if (null === $account) {
|
||||
Log::debug(sprintf('No asset account with id "%s"', $accountId));
|
||||
}
|
||||
}
|
||||
|
||||
/** @var Collection $rules */
|
||||
$rules = $this->ruleGroupRepository->getActiveRules($group);
|
||||
foreach ($rules as $rule) {
|
||||
// Create a job to do the work asynchronously
|
||||
$job = new ExecuteRuleOnExistingTransactions($rule);
|
||||
|
||||
// Apply parameters to the job
|
||||
$job->setUser($user);
|
||||
$job->setAccounts($accounts);
|
||||
$job->setStartDate($startDate);
|
||||
$job->setEndDate($endDate);
|
||||
|
||||
// Dispatch a new job to execute it in a queue
|
||||
$this->dispatch($job);
|
||||
}
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a rule group.
|
||||
* TODO update order of rule group
|
||||
*
|
||||
* @param RuleGroupRequest $request
|
||||
* @param RuleGroup $ruleGroup
|
||||
@@ -171,7 +362,11 @@ class RuleGroupController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($ruleGroup, new RuleGroupTransformer($this->parameters), 'rule_groups');
|
||||
/** @var RuleGroupTransformer $transformer */
|
||||
$transformer = app(RuleGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($ruleGroup, $transformer, 'rule_groups');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
248
app/Api/V1/Controllers/TagController.php
Normal file
248
app/Api/V1/Controllers/TagController.php
Normal file
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
/**
|
||||
* TagController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\TagRequest;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\TagTransformer;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class TagController
|
||||
*/
|
||||
class TagController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
|
||||
/** @var TagRepositoryInterface The tag repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* RuleController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
$this->repository = app(TagRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the resource.
|
||||
*
|
||||
* @param Tag $tag
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function delete(Tag $tag): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($tag);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse]
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of budgets. Count it and split it.
|
||||
$collection = $this->repository->get();
|
||||
$count = $collection->count();
|
||||
$rules = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.tags.index') . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var TagTransformer $transformer */
|
||||
$transformer = app(TagTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($rules, $transformer, 'tags');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Tag $tag
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(Request $request, Tag $tag): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var TagTransformer $transformer */
|
||||
$transformer = app(TagTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($tag, $transformer, 'tags');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Store new object.
|
||||
*
|
||||
* @param TagRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(TagRequest $request): JsonResponse
|
||||
{
|
||||
$rule = $this->repository->store($request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var TagTransformer $transformer */
|
||||
$transformer = app(TagTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($rule, $transformer, 'tags');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Tag $tag
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function transactions(Request $request, Tag $tag): 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 = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($admin);
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setAllAssetAccounts();
|
||||
$collector->setTag($tag);
|
||||
|
||||
if (\in_array(TransactionType::TRANSFER, $types, true)) {
|
||||
$collector->removeFilter(InternalTransferFilter::class);
|
||||
}
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedTransactions();
|
||||
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a rule.
|
||||
*
|
||||
* @param TagRequest $request
|
||||
* @param Tag $tag
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(TagRequest $request, Tag $tag): JsonResponse
|
||||
{
|
||||
$rule = $this->repository->update($tag, $request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
/** @var TagTransformer $transformer */
|
||||
$transformer = app(TagTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($rule, $transformer, 'tags');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
}
|
||||
@@ -25,14 +25,19 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\TransactionRequest;
|
||||
use FireflyIII\Events\StoredTransactionJournal;
|
||||
use FireflyIII\Events\UpdatedTransactionJournal;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
use FireflyIII\Helpers\Filter\NegativeAmountFilter;
|
||||
use FireflyIII\Helpers\Filter\PositiveAmountFilter;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankEventTransformer;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -49,6 +54,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
*/
|
||||
class TransactionController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
|
||||
/** @var JournalRepositoryInterface The journal repository */
|
||||
private $repository;
|
||||
@@ -73,6 +79,30 @@ class TransactionController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Transaction $transaction
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function attachments(Request $request, Transaction $transaction): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$attachments = $this->repository->getAttachmentsByTr($transaction);
|
||||
|
||||
/** @var AttachmentTransformer $transformer */
|
||||
$transformer = app(AttachmentTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($attachments, $transformer, 'attachments');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
@@ -101,15 +131,15 @@ class TransactionController extends Controller
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$this->parameters->set('type', $type);
|
||||
|
||||
$types = $this->mapTypes($this->parameters->get('type'));
|
||||
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($admin);
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setAllAssetAccounts();
|
||||
@@ -123,39 +153,60 @@ class TransactionController extends Controller
|
||||
}
|
||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedJournals();
|
||||
$paginator = $collector->getPaginatedTransactions();
|
||||
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::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');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Transaction $transaction
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function piggyBankEvents(Request $request, Transaction $transaction): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$events = $this->repository->getPiggyBankEventsByTr($transaction);
|
||||
|
||||
/** @var PiggyBankEventTransformer $transformer */
|
||||
$transformer = app(PiggyBankEventTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($events, $transformer, 'piggy_bank_events');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a single transaction.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Transaction $transaction
|
||||
* @param string $include
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(Request $request, Transaction $transaction, string $include = null): JsonResponse
|
||||
public function show(Request $request, Transaction $transaction): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $include ?? '';
|
||||
$include = $request->get('include') ?? $include;
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
// collect transactions using the journal collector
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser(auth()->user());
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
// filter on specific journals.
|
||||
@@ -167,11 +218,14 @@ class TransactionController extends Controller
|
||||
$collector->addFilter(PositiveAmountFilter::class);
|
||||
}
|
||||
if (!($transactionType === TransactionType::WITHDRAWAL)) {
|
||||
$collector->addFilter(NegativeAmountFilter::class);
|
||||
$collector->addFilter(NegativeAmountFilter::class); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$transactions = $collector->getJournals();
|
||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
||||
$transactions = $collector->getTransactions();
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -192,16 +246,14 @@ class TransactionController extends Controller
|
||||
$data['user'] = auth()->user()->id;
|
||||
$journal = $repository->store($data);
|
||||
|
||||
event(new StoredTransactionJournal($journal, 0));
|
||||
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
// collect transactions using the journal collector
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser(auth()->user());
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
// filter on specific journals.
|
||||
@@ -216,8 +268,13 @@ class TransactionController extends Controller
|
||||
$collector->addFilter(NegativeAmountFilter::class);
|
||||
}
|
||||
|
||||
$transactions = $collector->getJournals();
|
||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
||||
$transactions = $collector->getTransactions();
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -241,13 +298,11 @@ class TransactionController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
event(new UpdatedTransactionJournal($journal));
|
||||
|
||||
// needs a lot of extra data to match the journal collector. Or just expand that one.
|
||||
// collect transactions using the journal collector
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser(auth()->user());
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
// filter on specific journals.
|
||||
@@ -262,46 +317,15 @@ class TransactionController extends Controller
|
||||
$collector->addFilter(NegativeAmountFilter::class);
|
||||
}
|
||||
|
||||
$transactions = $collector->getJournals();
|
||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
||||
$transactions = $collector->getTransactions();
|
||||
|
||||
/** @var TransactionTransformer $transformer */
|
||||
$transformer = app(TransactionTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* All the types you can request.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mapTypes(string $type): array
|
||||
{
|
||||
$types = [
|
||||
'all' => [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE,
|
||||
TransactionType::RECONCILIATION,],
|
||||
'withdrawal' => [TransactionType::WITHDRAWAL,],
|
||||
'withdrawals' => [TransactionType::WITHDRAWAL,],
|
||||
'expense' => [TransactionType::WITHDRAWAL,],
|
||||
'income' => [TransactionType::DEPOSIT,],
|
||||
'deposit' => [TransactionType::DEPOSIT,],
|
||||
'deposits' => [TransactionType::DEPOSIT,],
|
||||
'transfer' => [TransactionType::TRANSFER,],
|
||||
'transfers' => [TransactionType::TRANSFER,],
|
||||
'opening_balance' => [TransactionType::OPENING_BALANCE,],
|
||||
'reconciliation' => [TransactionType::RECONCILIATION,],
|
||||
'reconciliations' => [TransactionType::RECONCILIATION,],
|
||||
'special' => [TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,],
|
||||
'specials' => [TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,],
|
||||
'default' => [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER,],
|
||||
];
|
||||
$return = $types['default'];
|
||||
if (isset($types[$type])) {
|
||||
$return = $types[$type];
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* JournalLinkController.php
|
||||
* TransactionLinkController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
@@ -23,12 +23,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\JournalLinkRequest;
|
||||
use FireflyIII\Api\V1\Requests\TransactionLinkRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionJournalLink;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\JournalLinkTransformer;
|
||||
use FireflyIII\Transformers\TransactionLinkTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -40,12 +42,12 @@ use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class JournalLinkController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
* Class TransactionLinkController
|
||||
*/
|
||||
class JournalLinkController extends Controller
|
||||
class TransactionLinkController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
|
||||
/** @var JournalRepositoryInterface The journal repository */
|
||||
private $journalRepository;
|
||||
/** @var LinkTypeRepositoryInterface The link type repository */
|
||||
@@ -105,21 +107,25 @@ class JournalLinkController extends Controller
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
$linkType = $this->repository->findByName($name);
|
||||
|
||||
// get list of accounts. Count it and split it.
|
||||
// get list of transaction links. Count it and split it.
|
||||
$collection = $this->repository->getJournalLinks($linkType);
|
||||
$count = $collection->count();
|
||||
$journalLinks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($journalLinks, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.journal_links.index') . $this->buildParams());
|
||||
$paginator->setPath(route('api.v1.transaction_links.index') . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($journalLinks, new JournalLinkTransformer($this->parameters), 'journal_links');
|
||||
|
||||
/** @var TransactionLinkTransformer $transformer */
|
||||
$transformer = app(TransactionLinkTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($journalLinks, $transformer, 'transaction_links');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
@@ -137,14 +143,14 @@ class JournalLinkController extends Controller
|
||||
public function show(Request $request, TransactionJournalLink $journalLink): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'journal_links');
|
||||
|
||||
/** @var TransactionLinkTransformer $transformer */
|
||||
$transformer = app(TransactionLinkTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($journalLink, $transformer, 'transaction_links');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
@@ -153,19 +159,14 @@ class JournalLinkController extends Controller
|
||||
/**
|
||||
* Store new object.
|
||||
*
|
||||
* @param JournalLinkRequest $request
|
||||
* @param TransactionLinkRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function store(JournalLinkRequest $request): JsonResponse
|
||||
public function store(TransactionLinkRequest $request): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$data = $request->getAll();
|
||||
$inward = $this->journalRepository->findNull($data['inward_id'] ?? 0);
|
||||
$outward = $this->journalRepository->findNull($data['outward_id'] ?? 0);
|
||||
@@ -176,7 +177,11 @@ class JournalLinkController extends Controller
|
||||
|
||||
$journalLink = $this->repository->storeLink($data, $inward, $outward);
|
||||
|
||||
$resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'journal_links');
|
||||
/** @var TransactionLinkTransformer $transformer */
|
||||
$transformer = app(TransactionLinkTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($journalLink, $transformer, 'transaction_links');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
@@ -185,21 +190,15 @@ class JournalLinkController extends Controller
|
||||
/**
|
||||
* Update object.
|
||||
*
|
||||
* @param JournalLinkRequest $request
|
||||
* @param TransactionLinkRequest $request
|
||||
* @param TransactionJournalLink $journalLink
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function update(JournalLinkRequest $request, TransactionJournalLink $journalLink): JsonResponse
|
||||
public function update(TransactionLinkRequest $request, TransactionJournalLink $journalLink): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
|
||||
$manager = new Manager;
|
||||
$data = $request->getAll();
|
||||
$data['inward'] = $this->journalRepository->findNull($data['inward_id'] ?? 0);
|
||||
$data['outward'] = $this->journalRepository->findNull($data['outward_id'] ?? 0);
|
||||
@@ -209,7 +208,11 @@ class JournalLinkController extends Controller
|
||||
$data['direction'] = 'inward';
|
||||
$journalLink = $this->repository->updateLink($journalLink, $data);
|
||||
|
||||
$resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'journal_links');
|
||||
/** @var TransactionLinkTransformer $transformer */
|
||||
$transformer = app(TransactionLinkTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($journalLink, $transformer, 'transaction_links');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
@@ -78,7 +78,7 @@ class UserController extends Controller
|
||||
{
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
if ($this->repository->hasRole($admin, 'owner')) {
|
||||
if ($admin->id !== $user->id && $this->repository->hasRole($admin, 'owner')) {
|
||||
$this->repository->destroy($user);
|
||||
|
||||
return response()->json([], 204);
|
||||
@@ -113,7 +113,11 @@ class UserController extends Controller
|
||||
$paginator->setPath(route('api.v1.users.index') . $this->buildParams());
|
||||
|
||||
// make resource
|
||||
$resource = new FractalCollection($users, new UserTransformer($this->parameters), 'users');
|
||||
/** @var UserTransformer $transformer */
|
||||
$transformer = app(UserTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($users, $transformer, 'users');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
@@ -134,12 +138,12 @@ class UserController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
// make resource
|
||||
$resource = new Item($user, new UserTransformer($this->parameters), 'users');
|
||||
/** @var UserTransformer $transformer */
|
||||
$transformer = app(UserTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($user, $transformer, 'users');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -161,12 +165,13 @@ class UserController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
// make resource
|
||||
$resource = new Item($user, new UserTransformer($this->parameters), 'users');
|
||||
|
||||
/** @var UserTransformer $transformer */
|
||||
$transformer = app(UserTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($user, $transformer, 'users');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -189,12 +194,12 @@ class UserController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
// make resource
|
||||
$resource = new Item($user, new UserTransformer($this->parameters), 'users');
|
||||
/** @var UserTransformer $transformer */
|
||||
$transformer = app(UserTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($user, $transformer, 'users');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
|
||||
/**
|
||||
* Class AccountRequest
|
||||
*/
|
||||
@@ -47,9 +50,19 @@ class AccountRequest extends Request
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$active = true;
|
||||
$includeNetWorth = true;
|
||||
if (null !== $this->get('active')) {
|
||||
$active = $this->boolean('active');
|
||||
}
|
||||
if (null !== $this->get('include_net_worth')) {
|
||||
$includeNetWorth = $this->boolean('include_net_worth');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'name' => $this->string('name'),
|
||||
'active' => $this->boolean('active'),
|
||||
'active' => $active,
|
||||
'include_net_worth' => $includeNetWorth,
|
||||
'accountType' => $this->string('type'),
|
||||
'account_type_id' => null,
|
||||
'currency_id' => $this->integer('currency_id'),
|
||||
@@ -61,11 +74,20 @@ class AccountRequest extends Request
|
||||
'accountRole' => $this->string('account_role'),
|
||||
'openingBalance' => $this->string('opening_balance'),
|
||||
'openingBalanceDate' => $this->date('opening_balance_date'),
|
||||
'ccType' => $this->string('cc_type'),
|
||||
'ccMonthlyPaymentDate' => $this->string('cc_monthly_payment_date'),
|
||||
'ccType' => $this->string('credit_card_type'),
|
||||
'ccMonthlyPaymentDate' => $this->string('monthly_payment_date'),
|
||||
'notes' => $this->string('notes'),
|
||||
'interest' => $this->string('interest'),
|
||||
'interest_period' => $this->string('interest_period'),
|
||||
];
|
||||
|
||||
if ('liability' === $data['accountType']) {
|
||||
$data['openingBalance'] = bcmul($this->string('liability_amount'), '-1');
|
||||
$data['openingBalanceDate'] = $this->date('liability_start_date');
|
||||
$data['accountType'] = $this->string('liability_type');
|
||||
$data['account_type_id'] = null;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -80,21 +102,27 @@ class AccountRequest extends Request
|
||||
$types = implode(',', array_keys(config('firefly.subTitlesByIdentifier')));
|
||||
$ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes')));
|
||||
$rules = [
|
||||
'name' => 'required|min:1|uniqueAccountForUser',
|
||||
'opening_balance' => 'numeric|required_with:opening_balance_date|nullable',
|
||||
'opening_balance_date' => 'date|required_with:opening_balance|nullable',
|
||||
'iban' => 'iban|nullable',
|
||||
'bic' => 'bic|nullable',
|
||||
'virtual_balance' => 'numeric|nullable',
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id|required_without:currency_code',
|
||||
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:currency_id',
|
||||
'account_number' => 'between:1,255|nullable|uniqueAccountNumberForUser',
|
||||
'account_role' => 'in:' . $accountRoles . '|required_if:type,asset',
|
||||
'active' => 'required|boolean',
|
||||
'cc_type' => 'in:' . $ccPaymentTypes . '|required_if:account_role,ccAsset',
|
||||
'cc_monthly_payment_date' => 'date' . '|required_if:account_role,ccAsset|required_if:cc_type,monthlyFull',
|
||||
'type' => 'required|in:' . $types,
|
||||
'notes' => 'min:0|max:65536',
|
||||
'name' => 'required|min:1|uniqueAccountForUser',
|
||||
'type' => 'required|in:' . $types,
|
||||
'iban' => 'iban|nullable',
|
||||
'bic' => 'bic|nullable',
|
||||
'account_number' => 'between:1,255|nullable|uniqueAccountNumberForUser',
|
||||
'opening_balance' => 'numeric|required_with:opening_balance_date|nullable',
|
||||
'opening_balance_date' => 'date|required_with:opening_balance|nullable',
|
||||
'virtual_balance' => 'numeric|nullable',
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
'active' => [new IsBoolean],
|
||||
'include_net_worth' => [new IsBoolean],
|
||||
'account_role' => 'in:' . $accountRoles . '|required_if:type,asset',
|
||||
'credit_card_type' => 'in:' . $ccPaymentTypes . '|required_if:account_role,ccAsset',
|
||||
'monthly_payment_date' => 'date' . '|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull',
|
||||
'liability_type' => 'required_if:type,liability|in:loan,debt,mortgage',
|
||||
'liability_amount' => 'required_if:type,liability|min:0|numeric',
|
||||
'liability_start_date' => 'required_if:type,liability|date',
|
||||
'interest' => 'required_if:type,liability|between:0,100|numeric',
|
||||
'interest_period' => 'required_if:type,liability|in:daily,monthly,yearly',
|
||||
'notes' => 'min:0|max:65536',
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Rules\IsValidAttachmentModel;
|
||||
|
||||
@@ -69,9 +70,10 @@ class AttachmentRequest extends Request
|
||||
{
|
||||
$models = implode(
|
||||
',', [
|
||||
Bill::class,
|
||||
ImportJob::class,
|
||||
TransactionJournal::class,
|
||||
str_replace('FireflyIII\\Models\\', '', Bill::class),
|
||||
str_replace('FireflyIII\\Models\\', '', ImportJob::class),
|
||||
str_replace('FireflyIII\\Models\\', '', TransactionJournal::class),
|
||||
str_replace('FireflyIII\\Models\\', '', Transaction::class),
|
||||
]
|
||||
);
|
||||
$model = $this->string('model');
|
||||
|
||||
@@ -47,10 +47,11 @@ class AvailableBudgetRequest extends Request
|
||||
public function getAll(): array
|
||||
{
|
||||
return [
|
||||
'transaction_currency_id' => $this->integer('transaction_currency_id'),
|
||||
'amount' => $this->string('amount'),
|
||||
'start_date' => $this->date('start_date'),
|
||||
'end_date' => $this->date('end_date'),
|
||||
'currency_id' => $this->integer('currency_id'),
|
||||
'currency_code' => $this->string('currency_code'),
|
||||
'amount' => $this->string('amount'),
|
||||
'start' => $this->date('start'),
|
||||
'end' => $this->date('end'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -62,10 +63,11 @@ class AvailableBudgetRequest extends Request
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'transaction_currency_id' => 'required|numeric|exists:transaction_currencies,id',
|
||||
'amount' => 'required|numeric|more:0',
|
||||
'start_date' => 'required|date|before:end_date',
|
||||
'end_date' => 'required|date|after:start_date',
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
'amount' => 'required|numeric|more:0',
|
||||
'start' => 'required|date|before:end',
|
||||
'end' => 'required|date|after:start',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
@@ -50,6 +51,11 @@ class BillRequest extends Request
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$active = true;
|
||||
if(null !== $this->get('active')) {
|
||||
$active = $this->boolean('active');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'name' => $this->string('name'),
|
||||
'amount_min' => $this->string('amount_min'),
|
||||
@@ -59,8 +65,7 @@ class BillRequest extends Request
|
||||
'date' => $this->date('date'),
|
||||
'repeat_freq' => $this->string('repeat_freq'),
|
||||
'skip' => $this->integer('skip'),
|
||||
'automatch' => $this->boolean('automatch'),
|
||||
'active' => $this->boolean('active'),
|
||||
'active' => $active,
|
||||
'notes' => $this->string('notes'),
|
||||
];
|
||||
|
||||
@@ -78,13 +83,13 @@ class BillRequest extends Request
|
||||
'name' => 'required|between:1,255|uniqueObjectForUser:bills,name',
|
||||
'amount_min' => 'required|numeric|more:0',
|
||||
'amount_max' => 'required|numeric|more:0',
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id|required_without:currency_code',
|
||||
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:currency_id',
|
||||
'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',
|
||||
'skip' => 'required|between:0,31',
|
||||
'automatch' => 'required|boolean',
|
||||
'active' => 'required|boolean',
|
||||
'skip' => 'between:0,31',
|
||||
'automatch' => [new IsBoolean],
|
||||
'active' => [new IsBoolean],
|
||||
'notes' => 'between:1,65536',
|
||||
];
|
||||
switch ($this->method()) {
|
||||
|
||||
@@ -48,10 +48,12 @@ class BudgetLimitRequest extends Request
|
||||
public function getAll(): array
|
||||
{
|
||||
return [
|
||||
'budget_id' => $this->integer('budget_id'),
|
||||
'start_date' => $this->date('start_date'),
|
||||
'end_date' => $this->date('end_date'),
|
||||
'amount' => $this->string('amount'),
|
||||
'budget_id' => $this->integer('budget_id'),
|
||||
'start' => $this->date('start'),
|
||||
'end' => $this->date('end'),
|
||||
'amount' => $this->string('amount'),
|
||||
'currency_id' => $this->integer('currency_id'),
|
||||
'currency_code' => $this->string('currency_code'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -63,10 +65,12 @@ class BudgetLimitRequest extends Request
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'budget_id' => 'required|exists:budgets,id|belongsToUser:budgets,id',
|
||||
'start_date' => 'required|before:end_date|date',
|
||||
'end_date' => 'required|after:start_date|date',
|
||||
'amount' => 'required|more:0',
|
||||
'budget_id' => 'required|exists:budgets,id|belongsToUser:budgets,id',
|
||||
'start' => 'required|before:end|date',
|
||||
'end' => 'required|after:start|date',
|
||||
'amount' => 'required|more:0',
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
@@ -76,6 +80,12 @@ class BudgetLimitRequest extends Request
|
||||
$rules['budget_id'] = 'required|exists:budgets,id|belongsToUser:budgets,id';
|
||||
break;
|
||||
}
|
||||
// if request has a budget already, drop the rule.
|
||||
$budget = $this->route()->parameter('budget');
|
||||
if (null !== $budget) {
|
||||
unset($rules['budget_id']);
|
||||
}
|
||||
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
|
||||
/**
|
||||
* Class BudgetRequest
|
||||
@@ -48,9 +49,14 @@ class BudgetRequest extends Request
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$active = true;
|
||||
if (null !== $this->get('active')) {
|
||||
$active = $this->boolean('active');
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
'active' => $this->boolean('active'),
|
||||
'active' => $active,
|
||||
'order' => 0,
|
||||
];
|
||||
}
|
||||
@@ -64,7 +70,7 @@ class BudgetRequest extends Request
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name',
|
||||
'active' => 'required|boolean',
|
||||
'active' => [new IsBoolean],
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
|
||||
/**
|
||||
* Class CategoryRequest
|
||||
@@ -49,8 +50,7 @@ class CategoryRequest extends Request
|
||||
public function getAll(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
'active' => $this->boolean('active'),
|
||||
'name' => $this->string('name')
|
||||
];
|
||||
}
|
||||
|
||||
@@ -62,8 +62,7 @@ class CategoryRequest extends Request
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required|between:1,100|uniqueObjectForUser:categories,name',
|
||||
'active' => 'required|boolean',
|
||||
'name' => 'required|between:1,100|uniqueObjectForUser:categories,name'
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* JournalLinkRequest.php
|
||||
* ConfigurationRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
@@ -23,13 +24,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class JournalLinkRequest
|
||||
* Class ConfigurationRequest
|
||||
*/
|
||||
class JournalLinkRequest extends Request
|
||||
class ConfigurationRequest extends Request
|
||||
{
|
||||
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
@@ -48,28 +50,34 @@ class JournalLinkRequest extends Request
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
return [
|
||||
'link_type_id' => $this->integer('link_type_id'),
|
||||
'inward_id' => $this->integer('inward_id'),
|
||||
'outward_id' => $this->integer('outward_id'),
|
||||
'notes' => $this->string('notes'),
|
||||
];
|
||||
$name = $this->route()->parameter('configName');
|
||||
switch ($name) {
|
||||
case 'is_demo_site':
|
||||
case 'single_user_mode':
|
||||
return ['value' => $this->boolean('value')];
|
||||
case 'permission_update_check':
|
||||
return ['value' => $this->integer('value')];
|
||||
}
|
||||
|
||||
return ['value' => $this->string('value')]; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'link_type_id' => 'required|exists:link_types,id',
|
||||
'inward_id' => 'required|belongsToUser:transaction_journals,id',
|
||||
'outward_id' => 'required|belongsToUser:transaction_journals,id',
|
||||
'notes' => 'between:0,65000',
|
||||
];
|
||||
}
|
||||
$name = $this->route()->parameter('configName');
|
||||
switch ($name) {
|
||||
case 'is_demo_site':
|
||||
case 'single_user_mode':
|
||||
return ['value' => ['required', new IsBoolean]];
|
||||
case 'permission_update_check':
|
||||
return ['value' => 'required|numeric|between:-1,1'];
|
||||
}
|
||||
|
||||
return ['value' => 'required']; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
|
||||
|
||||
/**
|
||||
* Class CurrencyRequest
|
||||
@@ -47,12 +49,22 @@ class CurrencyRequest extends Request
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$enabled = true;
|
||||
$default = false;
|
||||
if (null !== $this->get('enabled')) {
|
||||
$enabled = $this->boolean('enabled');
|
||||
}
|
||||
if (null !== $this->get('default')) {
|
||||
$default = $this->boolean('default');
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
'code' => $this->string('code'),
|
||||
'symbol' => $this->string('symbol'),
|
||||
'decimal_places' => $this->integer('decimal_places'),
|
||||
'default' => $this->boolean('default'),
|
||||
'default' => $default,
|
||||
'enabled' => $enabled,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -67,8 +79,10 @@ class CurrencyRequest extends Request
|
||||
'name' => 'required|between:1,255|unique:transaction_currencies,name',
|
||||
'code' => 'required|between:3,3|unique:transaction_currencies,code',
|
||||
'symbol' => 'required|between:1,5|unique:transaction_currencies,symbol',
|
||||
'decimal_places' => 'required|between:0,20|numeric|min:0|max:20',
|
||||
'default' => 'boolean',
|
||||
'decimal_places' => 'between:0,20|numeric|min:0|max:20',
|
||||
'enabled' => [new IsBoolean()],
|
||||
'default' => [new IsBoolean()],
|
||||
|
||||
];
|
||||
|
||||
switch ($this->method()) {
|
||||
@@ -76,7 +90,7 @@ class CurrencyRequest extends Request
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
$currency = $this->route()->parameter('currency');
|
||||
$currency = $this->route()->parameter('currency_code');
|
||||
$rules['name'] = 'required|between:1,255|unique:transaction_currencies,name,' . $currency->id;
|
||||
$rules['code'] = 'required|between:1,255|unique:transaction_currencies,code,' . $currency->id;
|
||||
$rules['symbol'] = 'required|between:1,255|unique:transaction_currencies,symbol,' . $currency->id;
|
||||
|
||||
@@ -50,14 +50,17 @@ class PiggyBankRequest extends Request
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$current = $this->string('current_amount');
|
||||
$current = '' === $current ? '0' : $current;
|
||||
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
'account_id' => $this->integer('account_id'),
|
||||
'targetamount' => $this->string('target_amount'),
|
||||
'current_amount' => $this->string('current_amount'),
|
||||
'start_date' => $this->date('start_date'),
|
||||
'target_date' => $this->date('target_date'),
|
||||
'note' => $this->string('notes'),
|
||||
'current_amount' => $current,
|
||||
'startdate' => $this->date('start_date'),
|
||||
'targetdate' => $this->date('target_date'),
|
||||
'notes' => $this->string('notes'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -74,7 +77,7 @@ class PiggyBankRequest extends Request
|
||||
'target_amount' => 'required|numeric|more:0',
|
||||
'current_amount' => 'numeric|more:0|lte:target_amount',
|
||||
'start_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable|after:start_date',
|
||||
'notes' => 'max:65000',
|
||||
];
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Validation\RecurrenceValidation;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Validation\Validator;
|
||||
@@ -54,6 +55,14 @@ class RecurrenceRequest extends Request
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$active = true;
|
||||
$applyRules = true;
|
||||
if (null !== $this->get('active')) {
|
||||
$active = $this->boolean('active');
|
||||
}
|
||||
if (null !== $this->get('apply_rules')) {
|
||||
$applyRules = $this->boolean('apply_rules');
|
||||
}
|
||||
$return = [
|
||||
'recurrence' => [
|
||||
'type' => $this->string('type'),
|
||||
@@ -62,8 +71,8 @@ class RecurrenceRequest extends Request
|
||||
'first_date' => $this->date('first_date'),
|
||||
'repeat_until' => $this->date('repeat_until'),
|
||||
'repetitions' => $this->integer('nr_of_repetitions'),
|
||||
'apply_rules' => $this->boolean('apply_rules'),
|
||||
'active' => $this->boolean('active'),
|
||||
'apply_rules' => $applyRules,
|
||||
'active' => $active,
|
||||
],
|
||||
'meta' => [
|
||||
'piggy_bank_id' => $this->integer('piggy_bank_id'),
|
||||
@@ -84,26 +93,28 @@ class RecurrenceRequest extends Request
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$today = Carbon::create()->addDay();
|
||||
$today = Carbon::now()->addDay();
|
||||
|
||||
return [
|
||||
'type' => 'required|in:withdrawal,transfer,deposit',
|
||||
'title' => 'required|between:1,255|uniqueObjectForUser:recurrences,title',
|
||||
'description' => 'between:1,65000',
|
||||
'first_date' => sprintf('required|date|after:%s', $today->format('Y-m-d')),
|
||||
'apply_rules' => [new IsBoolean],
|
||||
'active' => [new IsBoolean],
|
||||
'repeat_until' => sprintf('date|after:%s', $today->format('Y-m-d')),
|
||||
'nr_of_repetitions' => 'numeric|between:1,31',
|
||||
'apply_rules' => 'required|boolean',
|
||||
'active' => 'required|boolean',
|
||||
'tags' => 'between:1,64000',
|
||||
'piggy_bank_id' => 'numeric',
|
||||
'repetitions.*.type' => 'required|in:daily,weekly,ndom,monthly,yearly',
|
||||
'repetitions.*.moment' => 'between:0,10',
|
||||
'repetitions.*.skip' => 'required|numeric|between:0,31',
|
||||
'repetitions.*.weekend' => 'required|numeric|min:1|max:4',
|
||||
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|required_without:transactions.*.currency_code',
|
||||
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:transactions.*.currency_id',
|
||||
'transactions.*.description' => 'required|between:1,255',
|
||||
'transactions.*.amount' => 'required|numeric|more:0',
|
||||
'transactions.*.foreign_amount' => 'numeric|more: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',
|
||||
'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser],
|
||||
@@ -112,8 +123,8 @@ class RecurrenceRequest extends Request
|
||||
'transactions.*.source_name' => 'between:1,255|nullable',
|
||||
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser],
|
||||
'transactions.*.destination_name' => 'between:1,255|nullable',
|
||||
'transactions.*.amount' => 'required|numeric|more:0',
|
||||
'transactions.*.description' => 'required|between:1,255',
|
||||
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
|
||||
|
||||
/**
|
||||
@@ -50,10 +51,16 @@ class RuleGroupRequest extends Request
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$active = true;
|
||||
|
||||
if (null !== $this->get('active')) {
|
||||
$active = $this->boolean('active');
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => $this->string('title'),
|
||||
'description' => $this->string('description'),
|
||||
'active' => $this->boolean('active'),
|
||||
'active' => $active,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -67,7 +74,7 @@ class RuleGroupRequest extends Request
|
||||
$rules = [
|
||||
'title' => 'required|between:1,100|uniqueObjectForUser:rule_groups,title',
|
||||
'description' => 'between:1,5000|nullable',
|
||||
'active' => 'required|boolean',
|
||||
'active' => [new IsBoolean],
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
|
||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
|
||||
@@ -49,34 +50,32 @@ class RuleRequest extends Request
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$strict = true;
|
||||
$active = true;
|
||||
$stopProcessing = false;
|
||||
if (null !== $this->get('active')) {
|
||||
$active = $this->boolean('active');
|
||||
}
|
||||
if (null !== $this->get('strict')) {
|
||||
$strict = $this->boolean('strict');
|
||||
}
|
||||
if (null !== $this->get('stop_processing')) {
|
||||
$stopProcessing = $this->boolean('stop_processing');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'title' => $this->string('title'),
|
||||
'description' => $this->string('description'),
|
||||
'rule_group_id' => $this->integer('rule_group_id'),
|
||||
'rule_group_title' => $this->string('rule_group_title'),
|
||||
'trigger' => $this->string('trigger'),
|
||||
'strict' => $this->boolean('strict'),
|
||||
'stop-processing' => $this->boolean('stop_processing'),
|
||||
'active' => $this->boolean('active'),
|
||||
'rule-triggers' => [],
|
||||
'rule-actions' => [],
|
||||
'strict' => $strict,
|
||||
'stop_processing' => $stopProcessing,
|
||||
'active' => $active,
|
||||
'triggers' => $this->getRuleTriggers(),
|
||||
'actions' => $this->getRuleActions(),
|
||||
];
|
||||
|
||||
foreach ($this->get('rule-triggers') as $trigger) {
|
||||
$data['rule-triggers'][] = [
|
||||
'name' => $trigger['name'],
|
||||
'value' => $trigger['value'],
|
||||
'stop-processing' => 1 === (int)($trigger['stop-processing'] ?? 0),
|
||||
];
|
||||
}
|
||||
foreach ($this->get('rule-actions') as $action) {
|
||||
$data['rule-actions'][] = [
|
||||
'name' => $action['name'],
|
||||
'value' => $action['value'],
|
||||
'stop-processing' => 1 === (int)($action['stop-processing'] ?? 0),
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -90,24 +89,26 @@ class RuleRequest extends Request
|
||||
$validTriggers = array_keys(config('firefly.rule-triggers'));
|
||||
$validActions = array_keys(config('firefly.rule-actions'));
|
||||
|
||||
// some actions require text:
|
||||
$contextActions = implode(',', config('firefly.rule-actions-text'));
|
||||
|
||||
$rules = [
|
||||
'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',
|
||||
'rule_group_title' => 'nullable|between:1,255|required_without:rule_group_id|belongsToUser:rule_groups,title',
|
||||
'trigger' => 'required|in:store-journal,update-journal',
|
||||
'rule-triggers.*.name' => 'required|in:' . implode(',', $validTriggers),
|
||||
'rule-triggers.*.stop-processing' => 'boolean',
|
||||
'rule-triggers.*.value' => 'required|min:1|ruleTriggerValue', //
|
||||
'rule-actions.*.name' => 'required|in:' . implode(',', $validActions),
|
||||
'rule-actions.*.value' => 'required_if:rule-action.*.type,' . $contextActions . '|ruleActionValue',
|
||||
'rule-actions.*.stop-processing' => 'boolean',
|
||||
'strict' => 'required|boolean',
|
||||
'stop_processing' => 'required|boolean',
|
||||
'active' => 'required|boolean',
|
||||
// some triggers and actions require text:
|
||||
$contextTriggers = implode(',', config('firefly.context-rule-triggers'));
|
||||
$contextActions = implode(',', config('firefly.context-rule-actions'));
|
||||
$rules = [
|
||||
'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',
|
||||
'rule_group_title' => 'nullable|between:1,255|required_without:rule_group_id|belongsToUser:rule_groups,title',
|
||||
'trigger' => 'required|in:store-journal,update-journal',
|
||||
'triggers.*.type' => 'required|in:' . implode(',', $validTriggers),
|
||||
'triggers.*.value' => 'required_if:actions.*.type,' . $contextTriggers . '|min:1|ruleTriggerValue',
|
||||
'triggers.*.stop_processing' => [new IsBoolean],
|
||||
'triggers.*.active' => [new IsBoolean],
|
||||
'actions.*.type' => 'required|in:' . implode(',', $validActions),
|
||||
'actions.*.value' => 'required_if:actions.*.type,' . $contextActions . '|ruleActionValue',
|
||||
'actions.*.stop_processing' => [new IsBoolean],
|
||||
'actions.*.active' => [new IsBoolean],
|
||||
'strict' => [new IsBoolean],
|
||||
'stop_processing' => [new IsBoolean],
|
||||
'active' => [new IsBoolean],
|
||||
];
|
||||
|
||||
return $rules;
|
||||
@@ -137,10 +138,10 @@ class RuleRequest extends Request
|
||||
*/
|
||||
protected function atLeastOneAction(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$repetitions = $data['rule-actions'] ?? [];
|
||||
// need at least one transaction
|
||||
if (0 === \count($repetitions)) {
|
||||
$data = $validator->getData();
|
||||
$actions = $data['actions'] ?? [];
|
||||
// need at least one trigger
|
||||
if (0 === \count($actions)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
|
||||
}
|
||||
}
|
||||
@@ -152,11 +153,53 @@ class RuleRequest extends Request
|
||||
*/
|
||||
protected function atLeastOneTrigger(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$repetitions = $data['rule-triggers'] ?? [];
|
||||
// need at least one transaction
|
||||
if (0 === \count($repetitions)) {
|
||||
$data = $validator->getData();
|
||||
$triggers = $data['triggers'] ?? [];
|
||||
// need at least one trugger
|
||||
if (0 === \count($triggers)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getRuleActions(): array
|
||||
{
|
||||
$actions = $this->get('actions');
|
||||
$return = [];
|
||||
if (\is_array($actions)) {
|
||||
foreach ($actions as $action) {
|
||||
$return[] = [
|
||||
'type' => $action['type'],
|
||||
'value' => $action['value'],
|
||||
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
|
||||
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getRuleTriggers(): array
|
||||
{
|
||||
$triggers = $this->get('triggers');
|
||||
$return = [];
|
||||
if (\is_array($triggers)) {
|
||||
foreach ($triggers as $trigger) {
|
||||
$return[] = [
|
||||
'type' => $trigger['type'],
|
||||
'value' => $trigger['value'],
|
||||
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'false')),
|
||||
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
||||
93
app/Api/V1/Requests/TagRequest.php
Normal file
93
app/Api/V1/Requests/TagRequest.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* TagRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Models\Tag;
|
||||
|
||||
/**
|
||||
* Class TagRequest
|
||||
*/
|
||||
class TagRequest 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
|
||||
{
|
||||
$data = [
|
||||
'tag' => $this->string('tag'),
|
||||
'date' => $this->date('date'),
|
||||
'description' => $this->string('description'),
|
||||
'latitude' => '' === $this->string('latitude') ? null : $this->string('latitude'),
|
||||
'longitude' => '' === $this->string('longitude') ? null : $this->string('longitude'),
|
||||
'zoom_level' => $this->integer('zoom_level'),
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'tag' => 'required|min:1|uniqueObjectForUser:tags,tag',
|
||||
'description' => 'min:1|nullable',
|
||||
'date' => 'date|nullable',
|
||||
'latitude' => 'numeric|min:-90|max:90|nullable|required_with:longitude',
|
||||
'longitude' => 'numeric|min:-90|max:90|nullable|required_with:latitude',
|
||||
'zoom_level' => 'numeric|min:0|max:80|nullable',
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
/** @var Tag $tag */
|
||||
$tag = $this->route()->parameter('tagOrId');
|
||||
$rules['tag'] = 'required|min:1|uniqueObjectForUser:tags,tag,' . $tag->id;
|
||||
break;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
135
app/Api/V1/Requests/TransactionLinkRequest.php
Normal file
135
app/Api/V1/Requests/TransactionLinkRequest.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
/**
|
||||
* TransactionLinkRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class TransactionLinkRequest
|
||||
*/
|
||||
class TransactionLinkRequest 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 [
|
||||
'link_type_id' => $this->integer('link_type_id'),
|
||||
'link_type_name' => $this->string('link_type_name'),
|
||||
'inward_id' => $this->integer('inward_id'),
|
||||
'outward_id' => $this->integer('outward_id'),
|
||||
'notes' => $this->string('notes'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'link_type_id' => 'exists:link_types,id|required_without:link_type_name',
|
||||
'link_type_name' => 'exists:link_types,name|required_without:link_type_id',
|
||||
'inward_id' => 'required|belongsToUser:transaction_journals,id|different:outward_id',
|
||||
'outward_id' => 'required|belongsToUser:transaction_journals,id|different:inward_id',
|
||||
'notes' => 'between:0,65000',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
$this->validateExistingLink($validator);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Validator $validator
|
||||
*/
|
||||
private function validateExistingLink(Validator $validator): void
|
||||
{
|
||||
/** @var LinkTypeRepositoryInterface $repository */
|
||||
$repository = app(LinkTypeRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
|
||||
/** @var JournalRepositoryInterface $journalRepos */
|
||||
$journalRepos = app(JournalRepositoryInterface::class);
|
||||
$journalRepos->setUser(auth()->user());
|
||||
|
||||
$data = $validator->getData();
|
||||
$inwardId = (int)($data['inward_id'] ?? 0);
|
||||
$outwardId = (int)($data['outward_id'] ?? 0);
|
||||
$inward = $journalRepos->findNull($inwardId);
|
||||
$outward = $journalRepos->findNull($outwardId);
|
||||
|
||||
if (null === $inward) {
|
||||
$validator->errors()->add('inward_id', 'Invalid inward ID.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (null === $outward) {
|
||||
$validator->errors()->add('outward_id', 'Invalid outward ID.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($repository->findLink($inward, $outward)) {
|
||||
// only if not updating:
|
||||
$link = $this->route()->parameter('journalLink');
|
||||
if (null === $link) {
|
||||
$validator->errors()->add('outward_id', 'Already have a link between inward and outward.');
|
||||
$validator->errors()->add('inward_id', 'Already have a link between inward and outward.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
@@ -65,6 +66,15 @@ class TransactionRequest extends Request
|
||||
'bill_id' => $this->integer('bill_id'),
|
||||
'bill_name' => $this->string('bill_name'),
|
||||
'tags' => explode(',', $this->string('tags')),
|
||||
'notes' => $this->string('notes'),
|
||||
'sepa-cc' => $this->string('sepa_cc'),
|
||||
'sepa-ct-op' => $this->string('sepa_ct_op'),
|
||||
'sepa-ct-id' => $this->string('sepa_ct_id'),
|
||||
'sepa-db' => $this->string('sepa_db'),
|
||||
'sepa-country' => $this->string('sepa_country'),
|
||||
'sepa-ep' => $this->string('sepa_ep'),
|
||||
'sepa-ci' => $this->string('sepa_ci'),
|
||||
'sepa-batch-id' => $this->string('sepa_batch_id'),
|
||||
'interest_date' => $this->date('interest_date'),
|
||||
'book_date' => $this->date('book_date'),
|
||||
'process_date' => $this->date('process_date'),
|
||||
@@ -72,7 +82,9 @@ class TransactionRequest extends Request
|
||||
'payment_date' => $this->date('payment_date'),
|
||||
'invoice_date' => $this->date('invoice_date'),
|
||||
'internal_reference' => $this->string('internal_reference'),
|
||||
'notes' => $this->string('notes'),
|
||||
'bunq_payment_id' => $this->string('bunq_payment_id'),
|
||||
'external_id' => $this->string('external_id'),
|
||||
'original-source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')),
|
||||
'transactions' => $this->getTransactionData(),
|
||||
];
|
||||
|
||||
@@ -89,9 +101,9 @@ class TransactionRequest extends Request
|
||||
{
|
||||
$rules = [
|
||||
// basic fields for journal:
|
||||
'type' => 'required|in:withdrawal,deposit,transfer',
|
||||
'date' => 'required|date',
|
||||
'type' => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation',
|
||||
'description' => 'between:1,255',
|
||||
'date' => 'required|date',
|
||||
'piggy_bank_id' => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser],
|
||||
'piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser],
|
||||
'bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser],
|
||||
@@ -99,6 +111,19 @@ class TransactionRequest extends Request
|
||||
'tags' => 'between:1,255',
|
||||
|
||||
// then, custom fields for journal
|
||||
'notes' => 'min:1,max:50000|nullable',
|
||||
|
||||
// SEPA fields:
|
||||
'sepa_cc' => 'min:1,max:255|nullable',
|
||||
'sepa_ct_op' => 'min:1,max:255|nullable',
|
||||
'sepa_ct_id' => 'min:1,max:255|nullable',
|
||||
'sepa_db' => 'min:1,max:255|nullable',
|
||||
'sepa_country' => 'min:1,max:255|nullable',
|
||||
'sepa_ep' => 'min:1,max:255|nullable',
|
||||
'sepa_ci' => 'min:1,max:255|nullable',
|
||||
'sepa_batch_id' => 'min:1,max:255|nullable',
|
||||
|
||||
// dates
|
||||
'interest_date' => 'date|nullable',
|
||||
'book_date' => 'date|nullable',
|
||||
'process_date' => 'date|nullable',
|
||||
@@ -106,13 +131,14 @@ class TransactionRequest extends Request
|
||||
'payment_date' => 'date|nullable',
|
||||
'invoice_date' => 'date|nullable',
|
||||
'internal_reference' => 'min:1,max:255|nullable',
|
||||
'notes' => 'min:1,max:50000|nullable',
|
||||
'bunq_payment_id' => 'min:1,max:255|nullable',
|
||||
'external_id' => 'min:1,max:255|nullable',
|
||||
|
||||
// transaction rules (in array for splits):
|
||||
'transactions.*.description' => 'nullable|between:1,255',
|
||||
'transactions.*.amount' => 'required|numeric|more:0',
|
||||
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|required_without:transactions.*.currency_code',
|
||||
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:transactions.*.currency_id',
|
||||
'transactions.*.description' => 'nullable|between:1,255',
|
||||
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
'transactions.*.foreign_amount' => 'numeric|more:0',
|
||||
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
@@ -120,8 +146,7 @@ class TransactionRequest extends Request
|
||||
'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser],
|
||||
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser],
|
||||
'transactions.*.category_name' => 'between:1,255|nullable',
|
||||
'transactions.*.reconciled' => 'boolean|nullable',
|
||||
// basic rules will be expanded later.
|
||||
'transactions.*.reconciled' => [new IsBoolean],
|
||||
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser],
|
||||
'transactions.*.source_name' => 'between:1,255|nullable',
|
||||
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser],
|
||||
@@ -171,8 +196,8 @@ class TransactionRequest extends Request
|
||||
$return = [];
|
||||
foreach ($this->get('transactions') as $index => $transaction) {
|
||||
$return[] = [
|
||||
'description' => $transaction['description'] ?? null,
|
||||
'amount' => $transaction['amount'],
|
||||
'description' => $transaction['description'] ?? null,
|
||||
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
|
||||
'currency_code' => $transaction['currency_code'] ?? null,
|
||||
'foreign_amount' => $transaction['foreign_amount'] ?? null,
|
||||
@@ -186,7 +211,7 @@ class TransactionRequest extends Request
|
||||
'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,
|
||||
'reconciled' => $transaction['reconciled'] ?? false,
|
||||
'reconciled' => $this->convertBoolean((string)($transaction['reconciled'] ?? 'false')),
|
||||
'identifier' => $index,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\User;
|
||||
|
||||
|
||||
@@ -64,10 +65,15 @@ class UserRequest extends Request
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$blocked = false;
|
||||
if (null === $this->get('blocked')) {
|
||||
$blocked = $this->boolean('blocked');
|
||||
}
|
||||
$data = [
|
||||
'email' => $this->string('email'),
|
||||
'blocked' => $this->boolean('blocked'),
|
||||
'blocked' => $blocked,
|
||||
'blocked_code' => $this->string('blocked_code'),
|
||||
'role' => $this->string('role'),
|
||||
];
|
||||
|
||||
return $data;
|
||||
@@ -82,8 +88,9 @@ class UserRequest extends Request
|
||||
{
|
||||
$rules = [
|
||||
'email' => 'required|email|unique:users,email,',
|
||||
'blocked' => 'required|boolean',
|
||||
'blocked' => [new IsBoolean],
|
||||
'blocked_code' => 'in:email_changed',
|
||||
'role' => 'in:owner,demo',
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
|
||||
393
app/Console/Commands/ApplyRules.php
Normal file
393
app/Console/Commands/ApplyRules.php
Normal file
@@ -0,0 +1,393 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
use FireflyIII\TransactionRules\Processor;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class ApplyRules
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ApplyRules extends Command
|
||||
{
|
||||
use VerifiesAccessToken;
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'This command will apply your rules and rule groups on a selection of your transactions.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature
|
||||
= 'firefly:apply-rules
|
||||
{--user=1 : The user ID that the import should import for.}
|
||||
{--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.}
|
||||
{--rules= : A comma-separated list of rules to apply. Take the ID\'s of these rules from the Firefly III interface. Using this option overrules the option that selects rule groups.}
|
||||
{--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 Carbon */
|
||||
private $endDate;
|
||||
/** @var Collection */
|
||||
private $results;
|
||||
/** @var Collection */
|
||||
private $ruleGroups;
|
||||
/** @var Collection */
|
||||
private $rules;
|
||||
/** @var Carbon */
|
||||
private $startDate;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->accounts = new Collection;
|
||||
$this->rules = new Collection;
|
||||
$this->ruleGroups = new Collection;
|
||||
$this->results = new Collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
if (!$this->verifyAccessToken()) {
|
||||
$this->error('Invalid access token.');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$result = $this->verifyInput();
|
||||
if (false === $result) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// get transactions from asset accounts.
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($this->getUser());
|
||||
$collector->setAccounts($this->accounts);
|
||||
$collector->setRange($this->startDate, $this->endDate);
|
||||
$transactions = $collector->getTransactions();
|
||||
$count = $transactions->count();
|
||||
|
||||
// first run all rule groups:
|
||||
/** @var RuleGroupRepositoryInterface $ruleGroupRepos */
|
||||
$ruleGroupRepos = app(RuleGroupRepositoryInterface::class);
|
||||
$ruleGroupRepos->setUser($this->getUser());
|
||||
|
||||
/** @var RuleGroup $ruleGroup */
|
||||
foreach ($this->ruleGroups as $ruleGroup) {
|
||||
$this->line(sprintf('Going to apply rule group "%s" to %d transaction(s).', $ruleGroup->title, $count));
|
||||
$rules = $ruleGroupRepos->getActiveStoreRules($ruleGroup);
|
||||
$this->applyRuleSelection($rules, $transactions, true);
|
||||
}
|
||||
|
||||
// then run all rules (rule groups should be empty).
|
||||
if ($this->rules->count() > 0) {
|
||||
|
||||
$this->line(sprintf('Will apply %d rule(s) to %d transaction(s)', $this->rules->count(), $transactions->count()));
|
||||
$this->applyRuleSelection($this->rules, $transactions, false);
|
||||
}
|
||||
|
||||
// filter results:
|
||||
$this->results = $this->results->unique(
|
||||
function (Transaction $transaction) {
|
||||
return (int)$transaction->journal_id;
|
||||
}
|
||||
);
|
||||
|
||||
$this->line('');
|
||||
if (0 === $this->results->count()) {
|
||||
$this->line('The rules were fired but did not influence any transactions.');
|
||||
}
|
||||
if ($this->results->count() > 0) {
|
||||
$this->line(sprintf('The rule(s) was/were fired, and influenced %d transaction(s).', $this->results->count()));
|
||||
foreach ($this->results as $result) {
|
||||
$this->line(
|
||||
vsprintf(
|
||||
'Transaction #%d: "%s" (%s %s)',
|
||||
[
|
||||
$result->journal_id,
|
||||
$result->description,
|
||||
$result->transaction_currency_code,
|
||||
round($result->transaction_amount, $result->transaction_currency_dp),
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $rules
|
||||
* @param Collection $transactions
|
||||
* @param bool $breakProcessing
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
private function applyRuleSelection(Collection $rules, Collection $transactions, bool $breakProcessing): void
|
||||
{
|
||||
$bar = $this->output->createProgressBar($rules->count() * $transactions->count());
|
||||
foreach ($rules as $rule) {
|
||||
/** @var Processor $processor */
|
||||
$processor = app(Processor::class);
|
||||
$processor->make($rule, true);
|
||||
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
/** @var Rule $rule */
|
||||
$bar->advance();
|
||||
$result = $processor->handleTransaction($transaction);
|
||||
if (true === $result) {
|
||||
$this->results->push($transaction);
|
||||
}
|
||||
}
|
||||
if (true === $rule->stop_processing && true === $breakProcessing) {
|
||||
$this->line('');
|
||||
$this->line(sprintf('Rule #%d ("%s") says to stop processing.', $rule->id, $rule->title));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->line('');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function grabAllRules(): void
|
||||
{
|
||||
if (true === $this->option('all_rules')) {
|
||||
/** @var RuleRepositoryInterface $ruleRepos */
|
||||
$ruleRepos = app(RuleRepositoryInterface::class);
|
||||
$ruleRepos->setUser($this->getUser());
|
||||
$this->rules = $ruleRepos->getAll();
|
||||
|
||||
// reset rule groups.
|
||||
$this->ruleGroups = new Collection;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function parseDates(): void
|
||||
{
|
||||
// parse start date.
|
||||
$startDate = Carbon::create()->startOfMonth();
|
||||
$startString = $this->option('start_date');
|
||||
if (null === $startString) {
|
||||
/** @var JournalRepositoryInterface $repository */
|
||||
$repository = app(JournalRepositoryInterface::class);
|
||||
$repository->setUser($this->getUser());
|
||||
$first = $repository->firstNull();
|
||||
if (null !== $first) {
|
||||
$startDate = $first->date;
|
||||
}
|
||||
}
|
||||
if (null !== $startString && '' !== $startString) {
|
||||
$startDate = Carbon::createFromFormat('Y-m-d', $startString);
|
||||
}
|
||||
|
||||
// parse end date
|
||||
$endDate = Carbon::now();
|
||||
$endString = $this->option('end_date');
|
||||
if (null !== $endString && '' !== $endString) {
|
||||
$endDate = Carbon::createFromFormat('Y-m-d', $endString);
|
||||
}
|
||||
|
||||
if ($startDate > $endDate) {
|
||||
[$endDate, $startDate] = [$startDate, $endDate];
|
||||
}
|
||||
|
||||
$this->startDate = $startDate;
|
||||
$this->endDate = $endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
private function verifyInput(): bool
|
||||
{
|
||||
// verify account.
|
||||
$result = $this->verifyInputAccounts();
|
||||
if (false === $result) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
// verify rule groups.
|
||||
$result = $this->verifyRuleGroups();
|
||||
if (false === $result) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
// verify rules.
|
||||
$result = $this->verifyRules();
|
||||
if (false === $result) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$this->grabAllRules();
|
||||
$this->parseDates();
|
||||
|
||||
//$this->line('Number of rules found: ' . $this->rules->count());
|
||||
$this->line('Start date is ' . $this->startDate->format('Y-m-d'));
|
||||
$this->line('End date is ' . $this->endDate->format('Y-m-d'));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
private function verifyInputAccounts(): bool
|
||||
{
|
||||
$accountString = $this->option('accounts');
|
||||
if (null === $accountString || '' === $accountString) {
|
||||
$this->error('Please use the --accounts to indicate the accounts to apply rules to.');
|
||||
|
||||
return false;
|
||||
}
|
||||
$finalList = new Collection;
|
||||
$accountList = explode(',', $accountString);
|
||||
|
||||
if (0 === \count($accountList)) {
|
||||
$this->error('Please use the --accounts to indicate the accounts to apply rules to.');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
$accountRepository->setUser($this->getUser());
|
||||
|
||||
foreach ($accountList as $accountId) {
|
||||
$accountId = (int)$accountId;
|
||||
$account = $accountRepository->findNull($accountId);
|
||||
if (null !== $account
|
||||
&& \in_array(
|
||||
$account->accountType->type, [AccountType::DEFAULT, AccountType::DEBT, AccountType::ASSET, AccountType::LOAN, AccountType::MORTGAGE], true
|
||||
)) {
|
||||
$finalList->push($account);
|
||||
}
|
||||
}
|
||||
|
||||
if (0 === $finalList->count()) {
|
||||
$this->error('Please make sure all accounts in --accounts are asset accounts or liabilities.');
|
||||
|
||||
return false;
|
||||
}
|
||||
$this->accounts = $finalList;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
private function verifyRuleGroups(): bool
|
||||
{
|
||||
$ruleGroupString = $this->option('rule_groups');
|
||||
if (null === $ruleGroupString || '' === $ruleGroupString) {
|
||||
// can be empty.
|
||||
return true;
|
||||
}
|
||||
$ruleGroupList = explode(',', $ruleGroupString);
|
||||
|
||||
if (0 === \count($ruleGroupList)) {
|
||||
// can be empty.
|
||||
|
||||
return true;
|
||||
}
|
||||
/** @var RuleGroupRepositoryInterface $ruleGroupRepos */
|
||||
$ruleGroupRepos = app(RuleGroupRepositoryInterface::class);
|
||||
$ruleGroupRepos->setUser($this->getUser());
|
||||
|
||||
foreach ($ruleGroupList as $ruleGroupId) {
|
||||
$ruleGroupId = (int)$ruleGroupId;
|
||||
$ruleGroup = $ruleGroupRepos->find($ruleGroupId);
|
||||
$this->ruleGroups->push($ruleGroup);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
private function verifyRules(): bool
|
||||
{
|
||||
$ruleString = $this->option('rules');
|
||||
if (null === $ruleString || '' === $ruleString) {
|
||||
// can be empty.
|
||||
return true;
|
||||
}
|
||||
$finalList = new Collection;
|
||||
$ruleList = explode(',', $ruleString);
|
||||
|
||||
if (0 === \count($ruleList)) {
|
||||
// can be empty.
|
||||
|
||||
return true;
|
||||
}
|
||||
/** @var RuleRepositoryInterface $ruleRepos */
|
||||
$ruleRepos = app(RuleRepositoryInterface::class);
|
||||
$ruleRepos->setUser($this->getUser());
|
||||
|
||||
foreach ($ruleList as $ruleId) {
|
||||
$ruleId = (int)$ruleId;
|
||||
$rule = $ruleRepos->find($ruleId);
|
||||
if (null !== $rule) {
|
||||
$finalList->push($rule);
|
||||
}
|
||||
}
|
||||
if ($finalList->count() > 0) {
|
||||
// reset rule groups.
|
||||
$this->ruleGroups = new Collection;
|
||||
$this->rules = $finalList;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -33,12 +33,14 @@ use FireflyIII\Repositories\ExportJob\ExportJobRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use Illuminate\Console\Command;
|
||||
use Storage;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/**
|
||||
* Class CreateExport.
|
||||
*
|
||||
* Generates export from the command line.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class CreateExport extends Command
|
||||
{
|
||||
@@ -134,10 +136,14 @@ class CreateExport extends Command
|
||||
$processor->createZipFile();
|
||||
$disk = Storage::disk('export');
|
||||
$fileName = sprintf('export-%s.zip', date('Y-m-d_H-i-s'));
|
||||
$disk->move($job->key . '.zip', $fileName);
|
||||
$localPath = storage_path('export') . '/' . $job->key . '.zip';
|
||||
|
||||
$this->line('The export has finished! You can find the ZIP file in this location:');
|
||||
$this->line(storage_path(sprintf('export/%s', $fileName)));
|
||||
// "move" from local to export disk
|
||||
$disk->put($fileName, file_get_contents($localPath));
|
||||
unlink($localPath);
|
||||
|
||||
$this->line('The export has finished! You can find the ZIP file in export disk with file name:');
|
||||
$this->line($fileName);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ use Log;
|
||||
|
||||
/**
|
||||
* Class CreateImport.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class CreateImport extends Command
|
||||
{
|
||||
@@ -150,7 +152,7 @@ class CreateImport extends Command
|
||||
|
||||
|
||||
if (true === $this->option('start')) {
|
||||
$this->infoLine('The has started. The process is not visible. Please wait.');
|
||||
$this->infoLine('The import routine has started. The process is not visible. Please wait.');
|
||||
Log::debug('Go for import!');
|
||||
|
||||
// run it!
|
||||
|
||||
67
app/Console/Commands/Cron.php
Normal file
67
app/Console/Commands/Cron.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Support\Cronjobs\RecurringCronjob;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class Cron
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Cron extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Runs all Firefly III cron-job related commands. Configure a cron job according to the official Firefly III documentation.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly:cron';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$recurring = new RecurringCronjob;
|
||||
try {
|
||||
$result = $recurring->fire();
|
||||
} catch (FireflyException $e) {
|
||||
$this->error($e->getMessage());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -31,6 +31,8 @@ use Log;
|
||||
|
||||
/**
|
||||
* Class DecryptAttachment.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class DecryptAttachment extends Command
|
||||
{
|
||||
|
||||
@@ -29,6 +29,8 @@ use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class EncryptFile.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class EncryptFile extends Command
|
||||
{
|
||||
@@ -37,7 +39,7 @@ class EncryptFile extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Encrypts a file and places it in the storage/upload directory.';
|
||||
protected $description = 'Encrypts a file and places it in the upload disk.';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
|
||||
@@ -35,6 +35,8 @@ use Log;
|
||||
|
||||
/**
|
||||
* Class Import.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Import extends Command
|
||||
{
|
||||
@@ -64,7 +66,7 @@ class Import extends Command
|
||||
Log::debug('Start start-import command');
|
||||
$jobKey = (string)$this->argument('key');
|
||||
/** @var ImportJob $job */
|
||||
$job = ImportJob::where('key', $jobKey)->first();
|
||||
$job = ImportJob::where('key', $jobKey)->first();
|
||||
if (null === $job) {
|
||||
$this->errorLine(sprintf('No job found with key "%s"', $jobKey));
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ use Storage;
|
||||
|
||||
/**
|
||||
* Class ScanAttachments.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ScanAttachments extends Command
|
||||
{
|
||||
@@ -82,6 +84,7 @@ class ScanAttachments extends Command
|
||||
$attachment->save();
|
||||
$this->line(sprintf('Fixed attachment #%d', $attachment->id));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\Rule;
|
||||
@@ -63,6 +64,8 @@ use UnexpectedValueException;
|
||||
* Upgrade user database.
|
||||
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class UpgradeDatabase extends Command
|
||||
{
|
||||
@@ -94,6 +97,8 @@ class UpgradeDatabase extends Command
|
||||
$this->migrateNotes();
|
||||
$this->migrateAttachmentData();
|
||||
$this->migrateBillsToRules();
|
||||
$this->budgetLimitCurrency();
|
||||
$this->removeCCLiabilities();
|
||||
|
||||
$this->info('Firefly III database is up to date.');
|
||||
|
||||
@@ -434,6 +439,31 @@ class UpgradeDatabase extends Command
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function budgetLimitCurrency(): void
|
||||
{
|
||||
$budgetLimits = BudgetLimit::get();
|
||||
/** @var BudgetLimit $budgetLimit */
|
||||
foreach ($budgetLimits as $budgetLimit) {
|
||||
if (null === $budgetLimit->transaction_currency_id) {
|
||||
$budget = $budgetLimit->budget;
|
||||
if (null !== $budget) {
|
||||
$user = $budget->user;
|
||||
if (null !== $user) {
|
||||
$currency = \Amount::getDefaultCurrencyByUser($user);
|
||||
$budgetLimit->transaction_currency_id = $currency->id;
|
||||
$budgetLimit->save();
|
||||
$this->line(
|
||||
sprintf('Budget limit #%d (part of budget "%s") now has a currency setting (%s).', $budgetLimit->id, $budget->name, $currency->name)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function createNewTypes(): void
|
||||
{
|
||||
// create transaction type "Reconciliation".
|
||||
@@ -506,6 +536,28 @@ class UpgradeDatabase extends Command
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function removeCCLiabilities(): void
|
||||
{
|
||||
$ccType = AccountType::where('type', AccountType::CREDITCARD)->first();
|
||||
$debtType =AccountType::where('type', AccountType::DEBT)->first();
|
||||
if(null === $ccType || null === $debtType) {
|
||||
return;
|
||||
}
|
||||
/** @var Collection $accounts */
|
||||
$accounts = Account::where('account_type_id', $ccType->id)->get();
|
||||
foreach($accounts as $account) {
|
||||
$account->account_type_id = $debtType->id;
|
||||
$account->save();
|
||||
$this->line(sprintf('Converted credit card liability account "%s" (#%d) to generic debt liability.', $account->name, $account->id));
|
||||
}
|
||||
if($accounts->count() > 0) {
|
||||
$this->info('Credit card liability types are no longer supported and have been converted to generic debts. See: http://bit.ly/FF3-credit-cards');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method makes sure that the transaction journal uses the currency given in the transaction.
|
||||
*
|
||||
|
||||
@@ -27,6 +27,8 @@ use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class UpgradeFireflyInstructions.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class UpgradeFireflyInstructions extends Command
|
||||
{
|
||||
@@ -54,6 +56,7 @@ class UpgradeFireflyInstructions extends Command
|
||||
if ('install' === (string)$this->argument('task')) {
|
||||
$this->installInstructions();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class UseEncryption.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class UseEncryption extends Command
|
||||
{
|
||||
@@ -62,6 +63,7 @@ class UseEncryption extends Command
|
||||
$this->handleObjects('Category', 'name', 'encrypted');
|
||||
$this->handleObjects('PiggyBank', 'name', 'encrypted');
|
||||
$this->handleObjects('TransactionJournal', 'description', 'encrypted');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -77,7 +79,7 @@ class UseEncryption extends Command
|
||||
$fqn = sprintf('FireflyIII\Models\%s', $class);
|
||||
$encrypt = true === config('firefly.encryption') ? 0 : 1;
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$set = $fqn::where($indicator, $encrypt)->get();
|
||||
$set = $fqn::where($indicator, $encrypt)->withTrashed()->get();
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$newName = $entry->$field;
|
||||
|
||||
@@ -23,16 +23,37 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Trait VerifiesAccessToken.
|
||||
*
|
||||
* Verifies user access token for sensitive commands.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
trait VerifiesAccessToken
|
||||
{
|
||||
/**
|
||||
* @return User
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function getUser(): User
|
||||
{
|
||||
$userId = (int)$this->option('user');
|
||||
/** @var UserRepositoryInterface $repository */
|
||||
$repository = app(UserRepositoryInterface::class);
|
||||
$user = $repository->findNull($userId);
|
||||
if (null === $user) {
|
||||
throw new FireflyException('User is unexpectedly NULL');
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract method to make sure trait knows about method "option".
|
||||
*
|
||||
|
||||
@@ -28,12 +28,15 @@ namespace FireflyIII\Console\Commands;
|
||||
use Crypt;
|
||||
use DB;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\LinkType;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
@@ -41,6 +44,7 @@ use FireflyIII\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Schema;
|
||||
use stdClass;
|
||||
@@ -50,6 +54,7 @@ use stdClass;
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class VerifyDatabase extends Command
|
||||
{
|
||||
@@ -94,6 +99,7 @@ class VerifyDatabase extends Command
|
||||
$this->fixDoubleAmounts();
|
||||
$this->fixBadMeta();
|
||||
$this->removeBills();
|
||||
$this->enableCurrencies();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -149,6 +155,45 @@ class VerifyDatabase extends Command
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will make sure that all currencies in use are actually enabled.
|
||||
*/
|
||||
private function enableCurrencies(): void
|
||||
{
|
||||
$found = [];
|
||||
// get all meta entries
|
||||
/** @var Collection $meta */
|
||||
$meta = AccountMeta::where('name', 'currency_id')->groupBy('data')->get(['data']);
|
||||
foreach ($meta as $entry) {
|
||||
$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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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 = array_unique($found);
|
||||
TransactionCurrency::whereIn('id', $found)->update(['enabled' => true]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix the situation where the matching transactions of a journal somehow have non-matching categories or budgets.
|
||||
*
|
||||
|
||||
@@ -24,13 +24,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Jobs\CreateRecurringTransactions;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* File to make sure commands work.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
@@ -52,6 +52,21 @@ class Kernel extends ConsoleKernel
|
||||
*/
|
||||
protected function schedule(Schedule $schedule): void
|
||||
{
|
||||
$schedule->job(new CreateRecurringTransactions(new Carbon))->daily();
|
||||
$schedule->call(
|
||||
function () {
|
||||
Log::error('Firefly III no longer users the Laravel scheduler to do cron jobs! Please read the instructions at https://firefly-iii.readthedocs.io/en/latest/');
|
||||
echo "\n";
|
||||
echo '------------';
|
||||
echo "\n";
|
||||
echo wordwrap('Firefly III no longer users the Laravel scheduler to do cron jobs! Please read the instructions here:');
|
||||
echo "\n";
|
||||
echo 'https://firefly-iii.readthedocs.io/en/latest/';
|
||||
echo "\n\n";
|
||||
echo 'Disable this cron job!';
|
||||
echo "\n";
|
||||
echo '------------';
|
||||
echo "\n";
|
||||
}
|
||||
)->everyMinute();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ use Log;
|
||||
|
||||
/**
|
||||
* Class AdminRequestedTestMessage.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AdminRequestedTestMessage extends Event
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Events;
|
||||
|
||||
/**
|
||||
* Class Event.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
abstract class Event
|
||||
{
|
||||
|
||||
@@ -29,6 +29,7 @@ use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class RegisteredUser.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class RegisteredUser extends Event
|
||||
{
|
||||
|
||||
@@ -29,6 +29,7 @@ use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class RequestedNewPassword.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class RequestedNewPassword extends Event
|
||||
{
|
||||
@@ -36,10 +37,10 @@ class RequestedNewPassword extends Event
|
||||
|
||||
/** @var string The users IP address */
|
||||
public $ipAddress;
|
||||
/** @var User The user */
|
||||
public $user;
|
||||
/** @var string The token */
|
||||
public $token;
|
||||
/** @var User The user */
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new event instance. This event is triggered when a users tries to reset his or her password.
|
||||
|
||||
@@ -31,6 +31,8 @@ use Log;
|
||||
|
||||
/**
|
||||
* Class RequestedReportOnJournals
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class RequestedReportOnJournals
|
||||
{
|
||||
|
||||
@@ -30,6 +30,8 @@ use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class RequestedVersionCheckStatus
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class RequestedVersionCheckStatus extends Event
|
||||
{
|
||||
|
||||
@@ -29,6 +29,8 @@ use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class UserChangedEmail.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class UserChangedEmail extends Event
|
||||
{
|
||||
|
||||
@@ -38,6 +38,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class Handler
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
@@ -91,7 +93,7 @@ class Handler extends ExceptionHandler
|
||||
}
|
||||
|
||||
if ($exception instanceof FireflyException || $exception instanceof ErrorException || $exception instanceof OAuthServerException) {
|
||||
$isDebug = env('APP_DEBUG', false);
|
||||
$isDebug = config('app.debug');
|
||||
|
||||
return response()->view('errors.FireflyException', ['exception' => $exception, 'debug' => $isDebug], 500);
|
||||
}
|
||||
@@ -115,11 +117,11 @@ class Handler extends ExceptionHandler
|
||||
public function report(Exception $exception)
|
||||
{
|
||||
|
||||
$doMailError = env('SEND_ERROR_MESSAGE', true);
|
||||
$doMailError = config('firefly.send_error_message');
|
||||
// if the user wants us to mail:
|
||||
if (true === $doMailError
|
||||
// and if is one of these error instances
|
||||
&& ($exception instanceof FireflyException || $exception instanceof ErrorException || $exception instanceof OAuthServerException)) {
|
||||
&& ($exception instanceof FireflyException || $exception instanceof ErrorException)) {
|
||||
$userData = [
|
||||
'id' => 0,
|
||||
'email' => 'unknown@example.com',
|
||||
@@ -144,7 +146,7 @@ class Handler extends ExceptionHandler
|
||||
|
||||
// create job that will mail.
|
||||
$ipAddress = Request::ip() ?? '0.0.0.0';
|
||||
$job = new MailError($userData, env('SITE_OWNER', ''), $ipAddress, $data);
|
||||
$job = new MailError($userData, (string)config('firefly.site_owner'), $ipAddress, $data);
|
||||
dispatch($job);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,13 +28,15 @@ use Crypt;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Storage;
|
||||
|
||||
/**
|
||||
* Class AttachmentCollector.
|
||||
*
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
{
|
||||
@@ -108,7 +110,7 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
|
||||
if ($this->uploadDisk->exists($file)) {
|
||||
try {
|
||||
$decrypted = Crypt::decrypt($this->uploadDisk->get($file));
|
||||
} catch (FileNotFoundException|DecryptException $e) {
|
||||
} catch (DecryptException $e) {
|
||||
Log::error('Catchable error: could not decrypt attachment #' . $attachment->id . ' because: ' . $e->getMessage());
|
||||
|
||||
return false;
|
||||
|
||||
@@ -30,6 +30,9 @@ use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class BasicCollector.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @deprecated
|
||||
*/
|
||||
class BasicCollector
|
||||
{
|
||||
|
||||
@@ -29,6 +29,9 @@ use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface CollectorInterface.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @deprecated
|
||||
*/
|
||||
interface CollectorInterface
|
||||
{
|
||||
|
||||
@@ -31,6 +31,9 @@ use Storage;
|
||||
|
||||
/**
|
||||
* Class UploadCollector.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @deprecated
|
||||
*/
|
||||
class UploadCollector extends BasicCollector implements CollectorInterface
|
||||
{
|
||||
|
||||
@@ -43,6 +43,9 @@ use FireflyIII\Models\Transaction;
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.LongVariable)
|
||||
* @SuppressWarnings(PHPMD.TooManyFields)
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @deprecated
|
||||
*/
|
||||
final class Entry
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ use FireflyIII\Export\Collector\AttachmentCollector;
|
||||
use FireflyIII\Export\Collector\UploadCollector;
|
||||
use FireflyIII\Export\Entry\Entry;
|
||||
use FireflyIII\Export\Exporter\ExporterInterface;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
@@ -42,19 +42,22 @@ use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Storage;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use ZipArchive;
|
||||
|
||||
/**
|
||||
* Class ExpandedProcessor.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects) // its doing a lot.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @deprecated
|
||||
*/
|
||||
class ExpandedProcessor implements ProcessorInterface
|
||||
{
|
||||
/** @var Collection All accounts */
|
||||
public $accounts;
|
||||
/** @var string The export format*/
|
||||
/** @var string The export format */
|
||||
public $exportFormat;
|
||||
/** @var bool Should include attachments */
|
||||
public $includeAttachments;
|
||||
@@ -62,7 +65,7 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
public $includeOldUploads;
|
||||
/** @var ExportJob The export job itself */
|
||||
public $job;
|
||||
/** @var array The settings*/
|
||||
/** @var array The settings */
|
||||
public $settings;
|
||||
/** @var Collection The entries to export. */
|
||||
private $exportEntries;
|
||||
@@ -107,13 +110,13 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
public function collectJournals(): bool
|
||||
{
|
||||
// use journal collector thing.
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($this->job->user);
|
||||
$collector->setAccounts($this->accounts)->setRange($this->settings['startDate'], $this->settings['endDate'])
|
||||
->withOpposingAccount()->withBudgetInformation()->withCategoryInformation()
|
||||
->removeFilter(InternalTransferFilter::class);
|
||||
$transactions = $collector->getJournals();
|
||||
$transactions = $collector->getTransactions();
|
||||
// get some more meta data for each entry:
|
||||
$ids = $transactions->pluck('journal_id')->toArray();
|
||||
$assetIds = $transactions->pluck('account_id')->toArray();
|
||||
@@ -181,7 +184,7 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ZIP file.
|
||||
* Create a ZIP file locally (!) in storage_path('export').
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
@@ -192,9 +195,9 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
{
|
||||
$zip = new ZipArchive;
|
||||
$file = $this->job->key . '.zip';
|
||||
$fullPath = storage_path('export') . '/' . $file;
|
||||
$localPath = storage_path('export') . '/' . $file;
|
||||
|
||||
if (true !== $zip->open($fullPath, ZipArchive::CREATE)) {
|
||||
if (true !== $zip->open($localPath, ZipArchive::CREATE)) {
|
||||
throw new FireflyException('Cannot store zip file.');
|
||||
}
|
||||
// for each file in the collection, add it to the zip file.
|
||||
@@ -222,7 +225,7 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
{
|
||||
$exporterClass = config('firefly.export_formats.' . $this->exportFormat);
|
||||
/** @var ExporterInterface $exporter */
|
||||
$exporter = app($exporterClass);
|
||||
$exporter = app($exporterClass);
|
||||
$exporter->setJob($this->job);
|
||||
$exporter->setEntries($this->exportEntries);
|
||||
$exporter->run();
|
||||
@@ -260,7 +263,7 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
/**
|
||||
* Delete files.
|
||||
*/
|
||||
private function deleteFiles():void
|
||||
private function deleteFiles(): void
|
||||
{
|
||||
$disk = Storage::disk('export');
|
||||
foreach ($this->getFiles() as $file) {
|
||||
|
||||
@@ -29,6 +29,9 @@ use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class BasicExporter.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @deprecated
|
||||
*/
|
||||
class BasicExporter
|
||||
{
|
||||
|
||||
@@ -26,10 +26,13 @@ namespace FireflyIII\Export\Exporter;
|
||||
|
||||
use FireflyIII\Export\Entry\Entry;
|
||||
use League\Csv\Writer;
|
||||
use Storage;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/**
|
||||
* Class CsvExporter.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @deprecated
|
||||
*/
|
||||
class CsvExporter extends BasicExporter implements ExporterInterface
|
||||
{
|
||||
@@ -54,15 +57,11 @@ class CsvExporter extends BasicExporter implements ExporterInterface
|
||||
*/
|
||||
public function run(): bool
|
||||
{
|
||||
// create temporary file:
|
||||
$this->tempFile();
|
||||
|
||||
// necessary for CSV writer:
|
||||
$fullPath = storage_path('export') . DIRECTORY_SEPARATOR . $this->fileName;
|
||||
|
||||
// choose file name:
|
||||
$this->fileName = $this->job->key . '-records.csv';
|
||||
|
||||
//we create the CSV into memory
|
||||
$writer = Writer::createFromPath($fullPath);
|
||||
$writer = Writer::createFromString('');
|
||||
$rows = [];
|
||||
|
||||
// get field names for header row:
|
||||
@@ -83,18 +82,9 @@ class CsvExporter extends BasicExporter implements ExporterInterface
|
||||
$rows[] = $line;
|
||||
}
|
||||
$writer->insertAll($rows);
|
||||
$disk = Storage::disk('export');
|
||||
$disk->put($this->fileName, $writer->getContent());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a temp file.
|
||||
*/
|
||||
private function tempFile()
|
||||
{
|
||||
$this->fileName = $this->job->key . '-records.csv';
|
||||
// touch file in export directory:
|
||||
$disk = Storage::disk('export');
|
||||
$disk->put($this->fileName, '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@ use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface ExporterInterface.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @deprecated
|
||||
*/
|
||||
interface ExporterInterface
|
||||
{
|
||||
|
||||
@@ -28,6 +28,9 @@ use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface ProcessorInterface.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @deprecated
|
||||
*/
|
||||
interface ProcessorInterface
|
||||
{
|
||||
|
||||
@@ -30,8 +30,10 @@ namespace FireflyIII\Factory;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Services\Internal\Support\AccountServiceTrait;
|
||||
use FireflyIII\User;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Factory to create or return accounts.
|
||||
@@ -40,10 +42,22 @@ use FireflyIII\User;
|
||||
*/
|
||||
class AccountFactory
|
||||
{
|
||||
use AccountServiceTrait;
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
use AccountServiceTrait;
|
||||
|
||||
/**
|
||||
* AccountFactory constructor.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === config('app.env')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
@@ -67,7 +81,6 @@ class AccountFactory
|
||||
// account may exist already:
|
||||
$return = $this->find($data['name'], $type->type);
|
||||
|
||||
|
||||
if (null === $return) {
|
||||
// create it:
|
||||
$databaseData
|
||||
@@ -80,8 +93,24 @@ class AccountFactory
|
||||
'iban' => $data['iban'],
|
||||
];
|
||||
|
||||
// remove virtual balance when not an asset account:
|
||||
if ($type->type !== AccountType::ASSET) {
|
||||
// find currency, or use default currency instead.
|
||||
/** @var TransactionCurrencyFactory $factory */
|
||||
$factory = app(TransactionCurrencyFactory::class);
|
||||
/** @var TransactionCurrency $currency */
|
||||
$currency = $factory->find((int)($data['currency_id'] ?? null), (string)($data['currency_code'] ?? null));
|
||||
|
||||
if (null === $currency) {
|
||||
// use default currency:
|
||||
$currency = app('amount')->getDefaultCurrencyByUser($this->user);
|
||||
}
|
||||
$currency->enabled =true;
|
||||
$currency->save();
|
||||
|
||||
unset($data['currency_code']);
|
||||
$data['currency_id'] = $currency->id;
|
||||
// remove virtual balance when not an asset account or a liability
|
||||
$canHaveVirtual = [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD];
|
||||
if (!\in_array($type->type, $canHaveVirtual, true)) {
|
||||
$databaseData['virtual_balance'] = '0';
|
||||
}
|
||||
|
||||
@@ -93,7 +122,7 @@ class AccountFactory
|
||||
$return = Account::create($databaseData);
|
||||
$this->updateMetaData($return, $data);
|
||||
|
||||
if ($type->type === AccountType::ASSET) {
|
||||
if (\in_array($type->type, $canHaveVirtual, true)) {
|
||||
if ($this->validIBData($data)) {
|
||||
$this->updateIB($return, $data);
|
||||
}
|
||||
@@ -130,6 +159,7 @@ class AccountFactory
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $accountName
|
||||
* @param string $accountType
|
||||
*
|
||||
@@ -138,17 +168,23 @@ class AccountFactory
|
||||
*/
|
||||
public function findOrCreate(string $accountName, string $accountType): Account
|
||||
{
|
||||
Log::debug(sprintf('Searching for "%s" of type "%s"', $accountName, $accountType));
|
||||
$type = AccountType::whereType($accountType)->first();
|
||||
$accounts = $this->user->accounts()->where('account_type_id', $type->id)->get(['accounts.*']);
|
||||
$return = null;
|
||||
|
||||
Log::debug(sprintf('Account type is #%d', $type->id));
|
||||
|
||||
/** @var Account $object */
|
||||
foreach ($accounts as $object) {
|
||||
if ($object->name === $accountName) {
|
||||
Log::debug(sprintf('Found account #%d "%s".', $object->id, $object->name));
|
||||
$return = $object;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (null === $return) {
|
||||
Log::debug('Found nothing. Will create a new one.');
|
||||
$return = $this->create(
|
||||
[
|
||||
'user_id' => $this->user->id,
|
||||
@@ -188,9 +224,13 @@ class AccountFactory
|
||||
$result = AccountType::find($accountTypeId);
|
||||
}
|
||||
if (null === $result) {
|
||||
/** @var string $type */
|
||||
$type = (string)config('firefly.accountTypeByIdentifier.' . $accountType);
|
||||
$result = AccountType::whereType($type)->first();
|
||||
Log::debug(sprintf('No account type found by ID, continue search for "%s".', $accountType));
|
||||
/** @var array $types */
|
||||
$types = config('firefly.accountTypeByIdentifier.' . $accountType) ?? [];
|
||||
if (\count($types) > 0) {
|
||||
Log::debug(sprintf('%d accounts in list from config', \count($types)), $types);
|
||||
$result = AccountType::whereIn('type', $types)->first();
|
||||
}
|
||||
if (null === $result && null !== $accountType) {
|
||||
// try as full name:
|
||||
$result = AccountType::whereType($accountType)->first();
|
||||
|
||||
@@ -34,7 +34,15 @@ use Log;
|
||||
*/
|
||||
class AccountMetaFactory
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === config('app.env')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
@@ -65,7 +73,7 @@ class AccountMetaFactory
|
||||
// if $data has field and $entry is null, create new one:
|
||||
if (null === $entry) {
|
||||
Log::debug(sprintf('Created meta-field "%s":"%s" for account #%d ("%s") ', $field, $value, $account->id, $account->name));
|
||||
$this->create(['account_id' => $account->id, 'name' => $field, 'data' => $value]);
|
||||
return $this->create(['account_id' => $account->id, 'name' => $field, 'data' => $value]);
|
||||
}
|
||||
|
||||
// if $data has field and $entry is not null, update $entry:
|
||||
@@ -75,12 +83,13 @@ class AccountMetaFactory
|
||||
Log::debug(sprintf('Updated meta-field "%s":"%s" for #%d ("%s") ', $field, $value, $account->id, $account->name));
|
||||
}
|
||||
}
|
||||
if ('' === $value && null !== $entry && isset($data[$field])) {
|
||||
if ('' === $value && null !== $entry) {
|
||||
try {
|
||||
$entry->delete();
|
||||
} catch (Exception $e) {
|
||||
Log::debug(sprintf('Could not delete entry: %s', $e->getMessage()));
|
||||
} catch (Exception $e) { // @codeCoverageIgnore
|
||||
Log::debug(sprintf('Could not delete entry: %s', $e->getMessage())); // @codeCoverageIgnore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return $entry;
|
||||
|
||||
@@ -23,9 +23,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\User;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class AttachmentFactory
|
||||
@@ -35,19 +39,43 @@ class AttachmentFactory
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === config('app.env')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Attachment|null
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function create(array $data): ?Attachment
|
||||
{
|
||||
// append if necessary.
|
||||
$model = false === strpos('FireflyIII', $data['model']) ? 'FireflyIII\\Models\\' . $data['model'] : $data['model'];
|
||||
|
||||
if (Transaction::class === $model) {
|
||||
/** @var Transaction $transaction */
|
||||
$transaction = $this->user->transactions()->find((int)$data['model_id']);
|
||||
if (null === $transaction) {
|
||||
throw new FireflyException('Unexpectedly could not find transaction');
|
||||
}
|
||||
$data['model_id'] = $transaction->transaction_journal_id;
|
||||
$model = TransactionJournal::class;
|
||||
}
|
||||
|
||||
// create attachment:
|
||||
$attachment = Attachment::create(
|
||||
[
|
||||
'user_id' => $this->user->id,
|
||||
'attachable_id' => $data['model_id'],
|
||||
'attachable_type' => $data['model'],
|
||||
'attachable_type' => $model,
|
||||
'md5' => '',
|
||||
'filename' => $data['filename'],
|
||||
'title' => '' === $data['title'] ? null : $data['title'],
|
||||
|
||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Services\Internal\Support\BillServiceTrait;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -36,6 +37,17 @@ use Log;
|
||||
class BillFactory
|
||||
{
|
||||
use BillServiceTrait;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === config('app.env')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
@@ -46,6 +58,16 @@ class BillFactory
|
||||
*/
|
||||
public function create(array $data): ?Bill
|
||||
{
|
||||
/** @var TransactionCurrencyFactory $factory */
|
||||
$factory = app(TransactionCurrencyFactory::class);
|
||||
/** @var TransactionCurrency $currency */
|
||||
$currency = $factory->find((int)($data['currency_id'] ?? null), (string)($data['currency_code'] ?? null));
|
||||
|
||||
if(null === $currency) {
|
||||
// use default currency:
|
||||
$currency = app('amount')->getDefaultCurrencyByUser($this->user);
|
||||
}
|
||||
|
||||
/** @var Bill $bill */
|
||||
$bill = Bill::create(
|
||||
[
|
||||
@@ -53,12 +75,12 @@ class BillFactory
|
||||
'match' => 'MIGRATED_TO_RULES',
|
||||
'amount_min' => $data['amount_min'],
|
||||
'user_id' => $this->user->id,
|
||||
'transaction_currency_id' => $data['transaction_currency_id'],
|
||||
'transaction_currency_id' => $currency->id,
|
||||
'amount_max' => $data['amount_max'],
|
||||
'date' => $data['date'],
|
||||
'repeat_freq' => $data['repeat_freq'],
|
||||
'skip' => $data['skip'],
|
||||
'automatch' => $data['automatch'] ?? true,
|
||||
'automatch' => true,
|
||||
'active' => $data['active'] ?? true,
|
||||
]
|
||||
);
|
||||
|
||||
@@ -27,12 +27,23 @@ namespace FireflyIII\Factory;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class BudgetFactory.
|
||||
*/
|
||||
class BudgetFactory
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if ('testing' === config('app.env')) {
|
||||
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', \get_class($this)));
|
||||
}
|
||||
}
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user