mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-01-06 10:31:28 +00:00
Compare commits
1258 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d550a626e9 | ||
|
|
31dea785f6 | ||
|
|
4eff0b73c7 | ||
|
|
dc55d712af | ||
|
|
d735694e2a | ||
|
|
f4c2b8e348 | ||
|
|
5ff0ca81b7 | ||
|
|
5fcb5fdaa5 | ||
|
|
03d8543cae | ||
|
|
fb7a74fb5c | ||
|
|
b11f9611ff | ||
|
|
cb7a4fedf7 | ||
|
|
1c68b0902d | ||
|
|
0c967cb011 | ||
|
|
c0fd371430 | ||
|
|
cb9c59e5e3 | ||
|
|
8dccfc796a | ||
|
|
b0b2bfb361 | ||
|
|
62b65927ff | ||
|
|
50fca4f19e | ||
|
|
c6c66b9dcb | ||
|
|
ff3e65baeb | ||
|
|
30f454d38a | ||
|
|
e9782a701f | ||
|
|
1a583c771b | ||
|
|
69af0c3d65 | ||
|
|
a6164456e6 | ||
|
|
377f31b910 | ||
|
|
445ecdca17 | ||
|
|
aa7a35d93d | ||
|
|
eb0d269ce7 | ||
|
|
77084ba72d | ||
|
|
07dd44af2d | ||
|
|
a29e78ed44 | ||
|
|
5d192ad4c2 | ||
|
|
3fb13b870f | ||
|
|
7cb53f4396 | ||
|
|
2d47ee7e21 | ||
|
|
95181a0a6a | ||
|
|
f36b369d73 | ||
|
|
5623c3c43f | ||
|
|
f9f1fa0fcb | ||
|
|
f52584d46b | ||
|
|
bbcb492075 | ||
|
|
0f2040f931 | ||
|
|
2cda6eba94 | ||
|
|
d23656aac9 | ||
|
|
fff98186b2 | ||
|
|
5c468e1c49 | ||
|
|
2bff6b49e6 | ||
|
|
d107e78641 | ||
|
|
47de2fec28 | ||
|
|
4743230136 | ||
|
|
7fb5c12a29 | ||
|
|
ddabf6a246 | ||
|
|
a8b521bdd5 | ||
|
|
e113fea8f0 | ||
|
|
b3cbbeecf0 | ||
|
|
401086b75f | ||
|
|
5a8146aa34 | ||
|
|
4872d3e4bc | ||
|
|
7cee183f1c | ||
|
|
8b0903c32e | ||
|
|
6443b7bde4 | ||
|
|
e75c15a61b | ||
|
|
206dae87ba | ||
|
|
771cf73171 | ||
|
|
0fd7e4363d | ||
|
|
8246d901e7 | ||
|
|
30fc56a0d7 | ||
|
|
01876be152 | ||
|
|
a57a7d3bda | ||
|
|
5c099008e8 | ||
|
|
ce06fb73b1 | ||
|
|
1e9f354a81 | ||
|
|
f5b01c7b21 | ||
|
|
48d3130b36 | ||
|
|
d247ed5dc5 | ||
|
|
4cd52963a6 | ||
|
|
509276e20b | ||
|
|
ca777857c2 | ||
|
|
61b6e266da | ||
|
|
717b9d21fd | ||
|
|
134d1b2746 | ||
|
|
5973b94677 | ||
|
|
40441de545 | ||
|
|
a90eacf686 | ||
|
|
09bc50dd4d | ||
|
|
7685e2007f | ||
|
|
4a3e1a9604 | ||
|
|
9fad13c788 | ||
|
|
97d87b0657 | ||
|
|
1da4597f94 | ||
|
|
e525960320 | ||
|
|
4cdbea2737 | ||
|
|
6a06ab35c9 | ||
|
|
6d3b8e7def | ||
|
|
a6b1fcb609 | ||
|
|
48f0aa842e | ||
|
|
9d8625df3b | ||
|
|
19feefda2d | ||
|
|
91b6b86202 | ||
|
|
f4eca2d4ae | ||
|
|
5fb7635100 | ||
|
|
fa706d27d8 | ||
|
|
e11af70f99 | ||
|
|
0daed6529d | ||
|
|
e5269bb312 | ||
|
|
7eb9086a28 | ||
|
|
33d0b8ca22 | ||
|
|
7720519076 | ||
|
|
57961de214 | ||
|
|
d1eab98281 | ||
|
|
e37abeb36d | ||
|
|
49fc6fbd38 | ||
|
|
467a04ad78 | ||
|
|
7ef1098ab4 | ||
|
|
d050c0269a | ||
|
|
9e4f6abf5d | ||
|
|
c41ae3a9bf | ||
|
|
4ff8b3b556 | ||
|
|
ce5fcbbda2 | ||
|
|
e308b0f617 | ||
|
|
e209766ad0 | ||
|
|
f2c2d4e126 | ||
|
|
96caf3491e | ||
|
|
a67bbaa1eb | ||
|
|
2b40b60d01 | ||
|
|
f9dc58c3a8 | ||
|
|
c2a57a457b | ||
|
|
ac64bac558 | ||
|
|
f884880ab8 | ||
|
|
5e04237a2c | ||
|
|
339ccbc5f8 | ||
|
|
1f3c621bea | ||
|
|
a49e20c2aa | ||
|
|
8978904fdd | ||
|
|
5e0d9bddba | ||
|
|
96222fdcea | ||
|
|
05bee57932 | ||
|
|
1e00d7cb16 | ||
|
|
6bc5794dfd | ||
|
|
1f9fddaa32 | ||
|
|
5d68fab374 | ||
|
|
8680254503 | ||
|
|
c0909aebba | ||
|
|
e16adca336 | ||
|
|
aa1b9fa5a5 | ||
|
|
af2f085aa7 | ||
|
|
6b86a35ffb | ||
|
|
7c5e10de33 | ||
|
|
d836c8217d | ||
|
|
e5e3797d9c | ||
|
|
4b45c0d0a9 | ||
|
|
afcf5f76ef | ||
|
|
5ecb7b0c07 | ||
|
|
a86e956dbb | ||
|
|
731ef7b13c | ||
|
|
2c0ad7047d | ||
|
|
682ad4c5aa | ||
|
|
f090a9534f | ||
|
|
ad289bc8cd | ||
|
|
6f5b6e536d | ||
|
|
c810bad97c | ||
|
|
a172c51495 | ||
|
|
633c776ebf | ||
|
|
19bd295c71 | ||
|
|
3b39fb93e7 | ||
|
|
e3a338db0e | ||
|
|
02df24bbc9 | ||
|
|
4f6ba1e706 | ||
|
|
a1f57a0949 | ||
|
|
3d444eb833 | ||
|
|
57b2a8d459 | ||
|
|
8a06507003 | ||
|
|
04d7137dff | ||
|
|
a2be71499f | ||
|
|
effba42ac2 | ||
|
|
aea8603ca1 | ||
|
|
fdb2abdf92 | ||
|
|
4b1d66bcf6 | ||
|
|
248e393405 | ||
|
|
967ea6a181 | ||
|
|
a11f876c49 | ||
|
|
2a4051fe92 | ||
|
|
10737d10a5 | ||
|
|
6f75e0df3c | ||
|
|
24a2238134 | ||
|
|
c7931f2b72 | ||
|
|
852584b6a8 | ||
|
|
21a9e981a2 | ||
|
|
ecc37b2ed3 | ||
|
|
c0935e192d | ||
|
|
92a2404b61 | ||
|
|
d9a2bd3e5f | ||
|
|
22f110df8d | ||
|
|
c76337926b | ||
|
|
bf57dec07c | ||
|
|
10d760a614 | ||
|
|
7b813065da | ||
|
|
c218a12af7 | ||
|
|
98ae0efb16 | ||
|
|
98cff18efa | ||
|
|
a7b2fbbf10 | ||
|
|
ccc12171d6 | ||
|
|
525f69cf63 | ||
|
|
4d2c5c1b58 | ||
|
|
450d07580e | ||
|
|
246100f2b7 | ||
|
|
9974e0229d | ||
|
|
ad44f99dbf | ||
|
|
12a64fefc8 | ||
|
|
2ee8cbbae4 | ||
|
|
34c19b145c | ||
|
|
c5e047ea02 | ||
|
|
fc78c32fca | ||
|
|
b53cbbe469 | ||
|
|
1d4434698e | ||
|
|
6d1bfd3956 | ||
|
|
1974d5f1e3 | ||
|
|
c235e42d6c | ||
|
|
342985d52a | ||
|
|
c2296c3ad5 | ||
|
|
23479790fe | ||
|
|
44823c6fec | ||
|
|
acfdf7dc90 | ||
|
|
6038a68ba9 | ||
|
|
79cf61b653 | ||
|
|
b97d3d3627 | ||
|
|
7f887e294a | ||
|
|
6f78735bc5 | ||
|
|
3e242aaca6 | ||
|
|
0796e422d4 | ||
|
|
fbd7c9ae07 | ||
|
|
5cfb1b63dc | ||
|
|
f09d0e87e4 | ||
|
|
820358af73 | ||
|
|
5a2998c80e | ||
|
|
a32df0066e | ||
|
|
02db333d46 | ||
|
|
070f46c755 | ||
|
|
b4a732bf77 | ||
|
|
d8eb59736e | ||
|
|
41c15b0cf8 | ||
|
|
fdf99400bc | ||
|
|
1ba45afeab | ||
|
|
1819ece55d | ||
|
|
78335210db | ||
|
|
ca23bb6272 | ||
|
|
eed84e18bb | ||
|
|
12641f96b1 | ||
|
|
1b97c4d58f | ||
|
|
ee3a2ef41c | ||
|
|
084ceb0c4e | ||
|
|
2497c4ee5c | ||
|
|
757a118f87 | ||
|
|
97908932e6 | ||
|
|
4c73ad8306 | ||
|
|
10a2078661 | ||
|
|
3fb09136cf | ||
|
|
843cced454 | ||
|
|
71a501868f | ||
|
|
0a0ad8200a | ||
|
|
a9baf54b12 | ||
|
|
ed565136fc | ||
|
|
4719b87314 | ||
|
|
24b30af018 | ||
|
|
e9f4695355 | ||
|
|
5b969fa014 | ||
|
|
499e713683 | ||
|
|
5eadb51b78 | ||
|
|
713a962005 | ||
|
|
d96e77a3ec | ||
|
|
bc68c367c8 | ||
|
|
33e241d39a | ||
|
|
e67812bf64 | ||
|
|
1090ce6597 | ||
|
|
e358f19548 | ||
|
|
eac406d62d | ||
|
|
142a488ab3 | ||
|
|
893c83e086 | ||
|
|
76dad84ba6 | ||
|
|
6e78d4efa7 | ||
|
|
66ffbf9e47 | ||
|
|
c499899988 | ||
|
|
77ea246fc3 | ||
|
|
80f9896f2a | ||
|
|
90c60e55f7 | ||
|
|
b085ee3437 | ||
|
|
3b3f24fe56 | ||
|
|
1d2c834b2c | ||
|
|
cc243f9fb7 | ||
|
|
788bde5562 | ||
|
|
f67a9547cc | ||
|
|
8545d73119 | ||
|
|
c4964cf603 | ||
|
|
903b4e520c | ||
|
|
c0033ae56b | ||
|
|
3daddd690f | ||
|
|
0d9bae6ec2 | ||
|
|
6e2978231b | ||
|
|
0097c66522 | ||
|
|
93f1854be0 | ||
|
|
b7f3c53688 | ||
|
|
94b8bb8f66 | ||
|
|
edb038c822 | ||
|
|
b6a9204c4f | ||
|
|
1d1b335cac | ||
|
|
0516065f5a | ||
|
|
606f33ceeb | ||
|
|
cb1db06a7c | ||
|
|
7b0ccdbdb4 | ||
|
|
55cf9fa9d0 | ||
|
|
b3156e9798 | ||
|
|
8e51b3edef | ||
|
|
6f8b1f3b9d | ||
|
|
3b81b7a904 | ||
|
|
81cc138700 | ||
|
|
5b908b77f3 | ||
|
|
a248544641 | ||
|
|
b09504d0f7 | ||
|
|
1e3d85439e | ||
|
|
392317b01f | ||
|
|
9d73fb8193 | ||
|
|
64427ef004 | ||
|
|
fd2f4e1459 | ||
|
|
dcbc2ca0c3 | ||
|
|
55a5838b3c | ||
|
|
d7a3fcf26d | ||
|
|
c8c8fce55f | ||
|
|
c32f3254c5 | ||
|
|
3dff8dfaf8 | ||
|
|
53c7c6685b | ||
|
|
564f00561e | ||
|
|
c27db00550 | ||
|
|
717d1a3612 | ||
|
|
9bd238b45f | ||
|
|
d81128d8c6 | ||
|
|
bdf76cf9b2 | ||
|
|
aabf8ce8cc | ||
|
|
8bcf8095a9 | ||
|
|
efc6b0e45a | ||
|
|
00d785d891 | ||
|
|
e37100ae97 | ||
|
|
a077d58e9c | ||
|
|
cc56a981cd | ||
|
|
2147caf3ef | ||
|
|
62b5cf04ad | ||
|
|
d3be043aa7 | ||
|
|
933f02d1d9 | ||
|
|
02c92318fb | ||
|
|
a328d393d3 | ||
|
|
a06868b0c3 | ||
|
|
d38766e5db | ||
|
|
e41211bed7 | ||
|
|
0b6c3efe8d | ||
|
|
616d921bef | ||
|
|
ea52a52022 | ||
|
|
cc76be1aad | ||
|
|
2554840714 | ||
|
|
e1e351aad7 | ||
|
|
e9de7bbf15 | ||
|
|
2bf3bdb3de | ||
|
|
0a2bc99630 | ||
|
|
7f1bd19e45 | ||
|
|
f8d2292fa8 | ||
|
|
b0bd35503f | ||
|
|
0b8427f881 | ||
|
|
cf121fea50 | ||
|
|
75c2529d3e | ||
|
|
b8b59b13a7 | ||
|
|
12c1fa2367 | ||
|
|
febaab62f7 | ||
|
|
43dbad4e4c | ||
|
|
2089ee14e9 | ||
|
|
ec8e1d5a7a | ||
|
|
2d7494f8cd | ||
|
|
8717f469b1 | ||
|
|
40dd2e0f7f | ||
|
|
00dee03709 | ||
|
|
ca9f8b56f7 | ||
|
|
ece0c99dbb | ||
|
|
b217acfe26 | ||
|
|
15d4d185bb | ||
|
|
3435cb937c | ||
|
|
c9f4cf4f34 | ||
|
|
1b3d3de969 | ||
|
|
e80d616ef4 | ||
|
|
2ddf48f15c | ||
|
|
692b256f3f | ||
|
|
3ad4e04e2a | ||
|
|
427de0594d | ||
|
|
6ac08de71d | ||
|
|
494f783a2b | ||
|
|
59801b8bc1 | ||
|
|
3dbde59787 | ||
|
|
ac903b88ba | ||
|
|
fc70afa3ea | ||
|
|
4bd8e1b11e | ||
|
|
04bf92d946 | ||
|
|
eb2ee0c683 | ||
|
|
324e0e7e30 | ||
|
|
81dce5d7c7 | ||
|
|
b049ca27f1 | ||
|
|
9b574ce7ad | ||
|
|
5524941c90 | ||
|
|
67c0ef6ec6 | ||
|
|
d94d34ca63 | ||
|
|
6ff4a0b45c | ||
|
|
ee95606ec0 | ||
|
|
226e2f7185 | ||
|
|
1e7e0facf1 | ||
|
|
b7a4b0fdfd | ||
|
|
5242c0368b | ||
|
|
8f9ba21f4d | ||
|
|
58d370a893 | ||
|
|
3b8e95fcca | ||
|
|
889b7e9a18 | ||
|
|
6d34cfb940 | ||
|
|
63832b31f8 | ||
|
|
4de537ce76 | ||
|
|
a42992efb0 | ||
|
|
7d482aa24c | ||
|
|
a9f34e9dd1 | ||
|
|
f795cb07e1 | ||
|
|
17a66b3056 | ||
|
|
531161db09 | ||
|
|
2772a1bb3b | ||
|
|
0263e2b720 | ||
|
|
5d81de6117 | ||
|
|
a70b7cc7b9 | ||
|
|
def307010c | ||
|
|
806ea2edbd | ||
|
|
45b8c36272 | ||
|
|
45ddb64186 | ||
|
|
24efe9a096 | ||
|
|
2210b8054d | ||
|
|
3eb695f2ad | ||
|
|
7fd3f77c3e | ||
|
|
3c5c14ff5a | ||
|
|
54623061d8 | ||
|
|
5bbe1eab7c | ||
|
|
94acb50a6f | ||
|
|
6197c77303 | ||
|
|
947b83cbd1 | ||
|
|
003d07504f | ||
|
|
cf904eb677 | ||
|
|
6d68020cf4 | ||
|
|
9e9e5bd6dd | ||
|
|
43d753e5bd | ||
|
|
8f25562923 | ||
|
|
29158acfff | ||
|
|
c98d2187a0 | ||
|
|
b3349f1f9d | ||
|
|
9f50c5db3d | ||
|
|
311659ba0d | ||
|
|
956ec23d3c | ||
|
|
940a730827 | ||
|
|
2710a30a7c | ||
|
|
0f70cc5780 | ||
|
|
150818e673 | ||
|
|
317fea6cb9 | ||
|
|
abf70a235a | ||
|
|
74a3d155b0 | ||
|
|
c72cc2482a | ||
|
|
2d3d7f7720 | ||
|
|
fb1af395f9 | ||
|
|
f3123802a9 | ||
|
|
b2628a290b | ||
|
|
47c2d0eaf1 | ||
|
|
e80cde86d6 | ||
|
|
72c0d7a874 | ||
|
|
1ce1a84c9e | ||
|
|
3a34037f30 | ||
|
|
bc33d1b67d | ||
|
|
23d7abd55f | ||
|
|
4a1e56671b | ||
|
|
5d1cfc661f | ||
|
|
162c8af6ca | ||
|
|
b46f641b62 | ||
|
|
6964424bdc | ||
|
|
6bcb2ec144 | ||
|
|
aacd218056 | ||
|
|
6fdfa722dd | ||
|
|
5f768a0525 | ||
|
|
b632405a11 | ||
|
|
9e2a2bca0a | ||
|
|
6675749349 | ||
|
|
2ab9d2e6ee | ||
|
|
8efb73694d | ||
|
|
d95544d588 | ||
|
|
c02ab6f6d8 | ||
|
|
2b76b4a2b2 | ||
|
|
851c4d2907 | ||
|
|
42bd5d05b5 | ||
|
|
9d0a5c97c2 | ||
|
|
a1929b0521 | ||
|
|
57cfd7e3bc | ||
|
|
55345fa931 | ||
|
|
3c2dfc52bc | ||
|
|
73e32efd79 | ||
|
|
ced12ca83f | ||
|
|
85f9c256a1 | ||
|
|
7c2c24d330 | ||
|
|
3681bf258b | ||
|
|
8b5551fc26 | ||
|
|
779650f63d | ||
|
|
9c5df6ab6e | ||
|
|
fba3cb6d90 | ||
|
|
e4a9abc315 | ||
|
|
a845cb9af9 | ||
|
|
9b7835c9ed | ||
|
|
6a6d67f2b4 | ||
|
|
f46834e203 | ||
|
|
2a2f29533d | ||
|
|
0a6e20eae4 | ||
|
|
e15c35de64 | ||
|
|
eb6329e556 | ||
|
|
8b7e87ae57 | ||
|
|
10a6ff9bf8 | ||
|
|
bdf48227bb | ||
|
|
ad32c30f82 | ||
|
|
9e235ac5c8 | ||
|
|
bff156aad4 | ||
|
|
7e2159d12c | ||
|
|
280b2efee6 | ||
|
|
d13317095f | ||
|
|
627ef09f11 | ||
|
|
3ec7336d5c | ||
|
|
47e0f6ed89 | ||
|
|
8f1928c933 | ||
|
|
695244c928 | ||
|
|
6e9128d894 | ||
|
|
9a53f17fff | ||
|
|
91183a91b6 | ||
|
|
7aef52870f | ||
|
|
5d09d7e923 | ||
|
|
fd28589395 | ||
|
|
c0029af929 | ||
|
|
43a17d8676 | ||
|
|
4c8f26f25e | ||
|
|
9015a5e0c1 | ||
|
|
8676764513 | ||
|
|
d5c5fa4fad | ||
|
|
912fe99981 | ||
|
|
4d3af1dcde | ||
|
|
66c55b7bbe | ||
|
|
5ac39dbdef | ||
|
|
6f063a134f | ||
|
|
966186cccd | ||
|
|
784d990e20 | ||
|
|
80896b7181 | ||
|
|
97726c3822 | ||
|
|
63070bffc3 | ||
|
|
b3e48ede70 | ||
|
|
13afd4582f | ||
|
|
4eb8b1a7da | ||
|
|
251e9f9ba1 | ||
|
|
c7bf167f81 | ||
|
|
c07ca12574 | ||
|
|
bc735e3a59 | ||
|
|
47fdf4b1a2 | ||
|
|
c519b4d0df | ||
|
|
846fb57520 | ||
|
|
88001f4bc4 | ||
|
|
b692cccdfb | ||
|
|
50a071119b | ||
|
|
66d275a90d | ||
|
|
c07ef3658b | ||
|
|
636eeffaed | ||
|
|
5b1fb5354e | ||
|
|
484ed6a585 | ||
|
|
11e537810a | ||
|
|
cc67445f35 | ||
|
|
c4ceb9d2cd | ||
|
|
bc43ea2c25 | ||
|
|
c946a4040f | ||
|
|
f5c415f079 | ||
|
|
638f361479 | ||
|
|
ff23898c83 | ||
|
|
d94b23b15d | ||
|
|
fb304de75e | ||
|
|
5f76b563dc | ||
|
|
ce30375341 | ||
|
|
1b0be2a47e | ||
|
|
a89be86ca4 | ||
|
|
f84655e339 | ||
|
|
a0cead6548 | ||
|
|
4dbc5f1413 | ||
|
|
943620c035 | ||
|
|
a1268ffd39 | ||
|
|
fcd98b4d33 | ||
|
|
e411d7a825 | ||
|
|
3545d894fd | ||
|
|
200a4b18a8 | ||
|
|
6bd2b4f288 | ||
|
|
c4d57af936 | ||
|
|
76aa8acf0f | ||
|
|
220add3eda | ||
|
|
541280ee91 | ||
|
|
01219c951c | ||
|
|
69fa60cd21 | ||
|
|
a11d2df6bb | ||
|
|
07d39a23a8 | ||
|
|
ca67d98676 | ||
|
|
7b60d210ee | ||
|
|
78d955ebf6 | ||
|
|
f6f21e02ac | ||
|
|
e2ebd01719 | ||
|
|
b8ac7c9d89 | ||
|
|
037d9b7017 | ||
|
|
6462d2b87a | ||
|
|
cb4ff35adb | ||
|
|
d063f32c1c | ||
|
|
244d8eecab | ||
|
|
b66f6d7e2e | ||
|
|
aa3a88f537 | ||
|
|
e5476e6e7a | ||
|
|
4d976312e8 | ||
|
|
2ef5d3d4c6 | ||
|
|
eb3a89555d | ||
|
|
0a80b7fca7 | ||
|
|
431cf08401 | ||
|
|
e6d7c0ddbd | ||
|
|
f682981c1e | ||
|
|
4aac969ae4 | ||
|
|
00651adf5e | ||
|
|
ed94e71168 | ||
|
|
e4fb223f77 | ||
|
|
6e12f434ad | ||
|
|
b8c4ec1449 | ||
|
|
4ca60ca92a | ||
|
|
48219c9af3 | ||
|
|
9887b9809d | ||
|
|
a13ad5b417 | ||
|
|
3f28fd689f | ||
|
|
959025545e | ||
|
|
1978463e59 | ||
|
|
e85ac07c49 | ||
|
|
b7f0a6fff4 | ||
|
|
3a57e09447 | ||
|
|
87d5cabe52 | ||
|
|
af07522f16 | ||
|
|
1b8d4e4c63 | ||
|
|
9f3c114d57 | ||
|
|
c51c1b8098 | ||
|
|
143fe2a71f | ||
|
|
3379b723cf | ||
|
|
39321b320e | ||
|
|
fe738fd321 | ||
|
|
95720673d2 | ||
|
|
963be4a4fa | ||
|
|
61db419485 | ||
|
|
cb17b09b24 | ||
|
|
0f1236a597 | ||
|
|
ac26427a63 | ||
|
|
491903778a | ||
|
|
405c3e110a | ||
|
|
5464bfac19 | ||
|
|
ad31cc1c1f | ||
|
|
3aa79fb1e4 | ||
|
|
e3de03e50d | ||
|
|
d8b4af34e0 | ||
|
|
222d8e071a | ||
|
|
36c2f27d59 | ||
|
|
5d43faab96 | ||
|
|
07048cb5fb | ||
|
|
38c79c3dc4 | ||
|
|
7610d9e0db | ||
|
|
e4f3d0a0ea | ||
|
|
fdf147d9c6 | ||
|
|
f7e418f517 | ||
|
|
738f6ed232 | ||
|
|
12217d9850 | ||
|
|
87c8b3d7c6 | ||
|
|
fd571abbb0 | ||
|
|
64ae56757e | ||
|
|
7d75f00696 | ||
|
|
451c86e431 | ||
|
|
c8c71da903 | ||
|
|
423f3a9296 | ||
|
|
7658b7d9a6 | ||
|
|
0d0906c5e2 | ||
|
|
e0aa7f3ff5 | ||
|
|
59fdf5b77a | ||
|
|
e28cfade8d | ||
|
|
19710c3eab | ||
|
|
0782354160 | ||
|
|
22bc6d507e | ||
|
|
bf3c74e65f | ||
|
|
71fb9d8fa5 | ||
|
|
9a461fc7b7 | ||
|
|
e0d87aa11e | ||
|
|
b273af341c | ||
|
|
2117fc2a5a | ||
|
|
58e55dc789 | ||
|
|
ac9b8b8c30 | ||
|
|
4dcc66238e | ||
|
|
90c0aa6360 | ||
|
|
1594335487 | ||
|
|
2517674849 | ||
|
|
c00bc2a1f3 | ||
|
|
f999be81c2 | ||
|
|
e2530c5486 | ||
|
|
7526f13ca9 | ||
|
|
ed08d299de | ||
|
|
b6ea2f1c64 | ||
|
|
9ee14374bb | ||
|
|
925401682b | ||
|
|
53c71bb7a2 | ||
|
|
3c036ae021 | ||
|
|
bf89d9956d | ||
|
|
71104f375c | ||
|
|
4c94820cf4 | ||
|
|
8998c9a672 | ||
|
|
ccf60f4cdc | ||
|
|
c5af1d363c | ||
|
|
c6e3b54705 | ||
|
|
4f274a290e | ||
|
|
1774bcbabe | ||
|
|
492c11784b | ||
|
|
21ddbd220a | ||
|
|
e4a95e55ed | ||
|
|
3a0eb5a428 | ||
|
|
e55fd968cf | ||
|
|
d41be08b48 | ||
|
|
a18272513d | ||
|
|
e88061199c | ||
|
|
d0d7c437f2 | ||
|
|
a1ac1a4a29 | ||
|
|
41d22876c4 | ||
|
|
e1bb0298cb | ||
|
|
1ec2772255 | ||
|
|
40d77d82cd | ||
|
|
311d51464d | ||
|
|
d63c9c9aea | ||
|
|
f1e83f240e | ||
|
|
b0f847959f | ||
|
|
d3d4439b03 | ||
|
|
0e1da3f797 | ||
|
|
def95df49e | ||
|
|
73c8c6de37 | ||
|
|
25b2b43a38 | ||
|
|
1fc2c998de | ||
|
|
b7a577cc4c | ||
|
|
2cdedd9c29 | ||
|
|
cf47daa2a0 | ||
|
|
926e2db1d6 | ||
|
|
d092034ec5 | ||
|
|
d13b9a0cc3 | ||
|
|
bbbaf6c868 | ||
|
|
833add99a0 | ||
|
|
b54e7f0d46 | ||
|
|
a90981481f | ||
|
|
edff3d7fb0 | ||
|
|
88d65b4784 | ||
|
|
6db869de23 | ||
|
|
c645cb18e5 | ||
|
|
298132298b | ||
|
|
400b50a1f0 | ||
|
|
5b597e9b1f | ||
|
|
e55de9c1d5 | ||
|
|
33ccf7c707 | ||
|
|
6b94210de5 | ||
|
|
745624f044 | ||
|
|
68956eabf2 | ||
|
|
87591f6868 | ||
|
|
cc238a639e | ||
|
|
de6758a972 | ||
|
|
49647eedae | ||
|
|
f24e35236f | ||
|
|
6f200a423e | ||
|
|
ef57c0601a | ||
|
|
9632e99bd3 | ||
|
|
93e18ea195 | ||
|
|
f39676eedd | ||
|
|
1d73ff7c13 | ||
|
|
384e64d94d | ||
|
|
96bb880d1b | ||
|
|
cf307a00e1 | ||
|
|
5a97bcb123 | ||
|
|
50f7620d7a | ||
|
|
78ec3ebe59 | ||
|
|
96f0faa546 | ||
|
|
4307bf3b83 | ||
|
|
d56bd85328 | ||
|
|
9f2f258ad9 | ||
|
|
894b48df8e | ||
|
|
195fba5931 | ||
|
|
0556516524 | ||
|
|
5cad4e9d82 | ||
|
|
8607fd4997 | ||
|
|
d905849b71 | ||
|
|
968505ac0e | ||
|
|
e482b079df | ||
|
|
13cddd8f12 | ||
|
|
20b458f35d | ||
|
|
cec8210d8b | ||
|
|
e6ff895eff | ||
|
|
74ff17da7e | ||
|
|
7e1d430003 | ||
|
|
eeff2895aa | ||
|
|
f6d88521dd | ||
|
|
c3e6e4f034 | ||
|
|
6c09330e74 | ||
|
|
b100c02779 | ||
|
|
ef6f00fcf5 | ||
|
|
ad9405887a | ||
|
|
01e45de605 | ||
|
|
aebefe8bcf | ||
|
|
5e41641d7c | ||
|
|
0f3b3a07d1 | ||
|
|
156d2fbaa4 | ||
|
|
4866b9dabb | ||
|
|
62ce9660b4 | ||
|
|
873c2ce10d | ||
|
|
2c2410e710 | ||
|
|
624eb0f958 | ||
|
|
770e44d1bd | ||
|
|
7144798377 | ||
|
|
606ff3ed00 | ||
|
|
ca731adce7 | ||
|
|
ca71f3008c | ||
|
|
7c56c14fa0 | ||
|
|
e3433aa95b | ||
|
|
0df00556db | ||
|
|
a55dd97d51 | ||
|
|
b52959d41a | ||
|
|
163b0a2105 | ||
|
|
d33c89a8ee | ||
|
|
d0d73c5e3e | ||
|
|
799331b945 | ||
|
|
43073fa1fc | ||
|
|
7f91ff4b0c | ||
|
|
ba778d4c60 | ||
|
|
cddb3d82dd | ||
|
|
a221f02393 | ||
|
|
fa4959fc6a | ||
|
|
bbd68e78c1 | ||
|
|
3c20938e0f | ||
|
|
94745cb3d5 | ||
|
|
602b328914 | ||
|
|
27802c930f | ||
|
|
3b4622a9ac | ||
|
|
18fb2e91b1 | ||
|
|
214cd9c262 | ||
|
|
337c289a74 | ||
|
|
0d560ec442 | ||
|
|
a4d4bf3006 | ||
|
|
40028c8be7 | ||
|
|
961e7e92b3 | ||
|
|
d3576c4151 | ||
|
|
1d51a0f396 | ||
|
|
f62b7e4ae9 | ||
|
|
62135bc1cb | ||
|
|
b245facdfe | ||
|
|
577f024310 | ||
|
|
1c2206cb9f | ||
|
|
16ba65c424 | ||
|
|
59cfaa20ab | ||
|
|
ab0471c78e | ||
|
|
464642250b | ||
|
|
d7bf9e234c | ||
|
|
bf257574f9 | ||
|
|
92e42199b5 | ||
|
|
99b0b24a89 | ||
|
|
d86383eba8 | ||
|
|
4fc12f232a | ||
|
|
729483102e | ||
|
|
7ac00935d5 | ||
|
|
639be5b104 | ||
|
|
17359c5e42 | ||
|
|
7aa5eee3aa | ||
|
|
98d6a7f32e | ||
|
|
0475b68817 | ||
|
|
2a89d49ba7 | ||
|
|
aeab5f0333 | ||
|
|
f80de95bb0 | ||
|
|
e7bcc01fe8 | ||
|
|
9fcbce241e | ||
|
|
78a71fb7c6 | ||
|
|
3e25d66902 | ||
|
|
005e4ba4d1 | ||
|
|
0f83582fed | ||
|
|
d736ffec8e | ||
|
|
27d6091e45 | ||
|
|
290405b987 | ||
|
|
7fa2fed147 | ||
|
|
fd233510ee | ||
|
|
354be8dc88 | ||
|
|
9750bcba76 | ||
|
|
15d08ca17b | ||
|
|
1bc72fa49f | ||
|
|
68061fd292 | ||
|
|
2b77e9d96d | ||
|
|
5c48d2d56a | ||
|
|
11a0734009 | ||
|
|
2ccbfe45f2 | ||
|
|
3793b08d90 | ||
|
|
06b63209b1 | ||
|
|
02e318b3e6 | ||
|
|
3b78b26039 | ||
|
|
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 |
@@ -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/
|
||||
@@ -1,73 +1,3 @@
|
||||
# This is the main Apache server configuration file. It contains the
|
||||
# configuration directives that give the server its instructions.
|
||||
# See http://httpd.apache.org/docs/2.4/ for detailed information about
|
||||
# the directives and /usr/share/doc/apache2/README.Debian about Debian specific
|
||||
# hints.
|
||||
#
|
||||
#
|
||||
# Summary of how the Apache 2 configuration works in Debian:
|
||||
# The Apache 2 web server configuration in Debian is quite different to
|
||||
# upstream's suggested way to configure the web server. This is because Debian's
|
||||
# default Apache2 installation attempts to make adding and removing modules,
|
||||
# virtual hosts, and extra configuration directives as flexible as possible, in
|
||||
# order to make automating the changes and administering the server as easy as
|
||||
# possible.
|
||||
|
||||
# It is split into several files forming the configuration hierarchy outlined
|
||||
# below, all located in the /etc/apache2/ directory:
|
||||
#
|
||||
# /etc/apache2/
|
||||
# |-- apache2.conf
|
||||
# | `-- ports.conf
|
||||
# |-- mods-enabled
|
||||
# | |-- *.load
|
||||
# | `-- *.conf
|
||||
# |-- conf-enabled
|
||||
# | `-- *.conf
|
||||
# `-- sites-enabled
|
||||
# `-- *.conf
|
||||
#
|
||||
#
|
||||
# * apache2.conf is the main configuration file (this file). It puts the pieces
|
||||
# together by including all remaining configuration files when starting up the
|
||||
# web server.
|
||||
#
|
||||
# * ports.conf is always included from the main configuration file. It is
|
||||
# supposed to determine listening ports for incoming connections which can be
|
||||
# customized anytime.
|
||||
#
|
||||
# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/
|
||||
# directories contain particular configuration snippets which manage modules,
|
||||
# global configuration fragments, or virtual host configurations,
|
||||
# respectively.
|
||||
#
|
||||
# They are activated by symlinking available configuration files from their
|
||||
# respective *-available/ counterparts. These should be managed by using our
|
||||
# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See
|
||||
# their respective man pages for detailed information.
|
||||
#
|
||||
# * The binary is called apache2. Due to the use of environment variables, in
|
||||
# the default configuration, apache2 needs to be started/stopped with
|
||||
# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not
|
||||
# work with the default configuration.
|
||||
|
||||
|
||||
# Global configuration
|
||||
#
|
||||
|
||||
#
|
||||
# ServerRoot: The top of the directory tree under which the server's
|
||||
# configuration, error, and log files are kept.
|
||||
#
|
||||
# NOTE! If you intend to place this on an NFS (or otherwise network)
|
||||
# mounted filesystem then please read the Mutex documentation (available
|
||||
# at <URL:http://httpd.apache.org/docs/2.4/mod/core.html#mutex>);
|
||||
# you will save yourself a lot of trouble.
|
||||
#
|
||||
# Do NOT add a slash at the end of the directory path.
|
||||
#
|
||||
#ServerRoot "/etc/apache2"
|
||||
|
||||
#
|
||||
# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
|
||||
#
|
||||
|
||||
20
.deploy/docker/build-amd64.sh
Executable file
20
.deploy/docker/build-amd64.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# build image
|
||||
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
|
||||
|
||||
if [ "$TRAVIS_BRANCH" == "develop" ]; then
|
||||
echo "Build develop amd64"
|
||||
docker build -t jc5x/firefly-iii:develop-amd64 -f Dockerfile.amd64 .
|
||||
docker tag jc5x/firefly-iii:develop-amd64 jc5x/firefly-iii:develop-$VERSION-amd64
|
||||
docker push jc5x/firefly-iii:develop-amd64
|
||||
docker push jc5x/firefly-iii:develop-$VERSION-amd64
|
||||
fi
|
||||
|
||||
if [ "$TRAVIS_BRANCH" == "master" ]; then
|
||||
echo "Build master amd64"
|
||||
docker build -t jc5x/firefly-iii:latest-amd64 -f Dockerfile.amd64 .
|
||||
docker tag jc5x/firefly-iii:latest-amd64 jc5x/firefly-iii:release-$VERSION-amd64
|
||||
docker push jc5x/firefly-iii:latest-amd64
|
||||
docker push jc5x/firefly-iii:release-$VERSION-amd64
|
||||
fi
|
||||
29
.deploy/docker/build-arm.sh
Executable file
29
.deploy/docker/build-arm.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
docker run --rm --privileged multiarch/qemu-user-static:register --reset
|
||||
|
||||
# get qemu-arm-static binary
|
||||
mkdir tmp
|
||||
pushd tmp && \
|
||||
curl -L -o qemu-arm-static.tar.gz https://github.com/multiarch/qemu-user-static/releases/download/v2.6.0/qemu-arm-static.tar.gz && \
|
||||
tar xzf qemu-arm-static.tar.gz && \
|
||||
popd
|
||||
|
||||
# build image
|
||||
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
|
||||
|
||||
if [ "$TRAVIS_BRANCH" == "develop" ]; then
|
||||
echo "Build develop arm"
|
||||
docker build --tag jc5x/firefly-iii:develop-arm --file Dockerfile.arm .
|
||||
docker tag jc5x/firefly-iii:develop-arm jc5x/firefly-iii:develop-$VERSION-arm
|
||||
docker push jc5x/firefly-iii:develop-arm
|
||||
docker push jc5x/firefly-iii:develop-$VERSION-arm
|
||||
fi
|
||||
|
||||
if [ "$TRAVIS_BRANCH" == "master" ]; then
|
||||
echo "Build master arm"
|
||||
docker build --tag jc5x/firefly-iii:latest-arm --file Dockerfile.arm .
|
||||
docker tag jc5x/firefly-iii:latest-arm jc5x/firefly-iii:release-$VERSION-arm
|
||||
docker push jc5x/firefly-iii:latest-arm
|
||||
docker push jc5x/firefly-iii:release-$VERSION-arm
|
||||
fi
|
||||
3314
.deploy/docker/cacert.pem
Normal file
3314
.deploy/docker/cacert.pem
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,11 +0,0 @@
|
||||
[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
|
||||
@@ -1,6 +0,0 @@
|
||||
FF_APP_ENV=local
|
||||
FF_APP_KEY=S0m3R@nd0mString0f32Ch@rsEx@ct1y
|
||||
FF_DB_HOST=
|
||||
FF_DB_NAME=
|
||||
FF_DB_USER=
|
||||
FF_DB_PASSWORD=
|
||||
@@ -1,29 +1,101 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Now in entrypoint.sh for Firefly III"
|
||||
|
||||
# make sure the correct directories exists (suggested by @chrif):
|
||||
mkdir -p $FIREFLY_PATH/storage/app
|
||||
echo "Making directories..."
|
||||
mkdir -p $FIREFLY_PATH/storage/app/public
|
||||
mkdir -p $FIREFLY_PATH/storage/build
|
||||
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
|
||||
mkdir -p $FIREFLY_PATH/storage/framework/views/twig
|
||||
mkdir -p $FIREFLY_PATH/storage/framework/views/v1
|
||||
mkdir -p $FIREFLY_PATH/storage/framework/views/v2
|
||||
mkdir -p $FIREFLY_PATH/storage/logs
|
||||
mkdir -p $FIREFLY_PATH/storage/upload
|
||||
|
||||
|
||||
echo "Touch DB file (if SQLlite)..."
|
||||
if [[ $DB_CONNECTION == "sqlite" ]]
|
||||
then
|
||||
touch $FIREFLY_PATH/storage/database/database.sqlite
|
||||
echo "Touched!"
|
||||
fi
|
||||
|
||||
# make sure we own the volumes:
|
||||
echo "Run chown on ${FIREFLY_PATH}/storage..."
|
||||
chown -R www-data:www-data -R $FIREFLY_PATH/storage
|
||||
echo "Run chmod on ${FIREFLY_PATH}/storage..."
|
||||
chmod -R 775 $FIREFLY_PATH/storage
|
||||
|
||||
# remove any lingering files that may break upgrades:
|
||||
echo "Remove log file..."
|
||||
rm -f $FIREFLY_PATH/storage/logs/laravel.log
|
||||
|
||||
cat .env.docker | envsubst > .env
|
||||
echo "Dump auto load..."
|
||||
composer dump-autoload
|
||||
echo "Discover packages..."
|
||||
php artisan package:discover
|
||||
|
||||
echo "Run various artisan commands..."
|
||||
if [[ -z "$DB_PORT" ]]; then
|
||||
if [[ $DB_CONNECTION == "pgsql" ]]; then
|
||||
DB_PORT=5432
|
||||
elif [[ $DB_CONNECTION == "mysql" ]]; then
|
||||
DB_PORT=3306
|
||||
fi
|
||||
fi
|
||||
if [[ ! -z "$DB_PORT" ]]; then
|
||||
$FIREFLY_PATH/.deploy/docker/wait-for-it.sh "${DB_HOST}:${DB_PORT}" -- echo "db is up. Time to execute artisan commands"
|
||||
fi
|
||||
#env $(grep -v "^\#" .env | xargs)
|
||||
php artisan cache:clear
|
||||
php artisan migrate --seed
|
||||
php artisan firefly-iii:decrypt-all
|
||||
|
||||
# there are 13 upgrade commands
|
||||
php artisan firefly-iii:transaction-identifiers
|
||||
php artisan firefly-iii:migrate-to-groups
|
||||
php artisan firefly-iii:account-currencies
|
||||
php artisan firefly-iii:transfer-currencies
|
||||
php artisan firefly-iii:other-currencies
|
||||
php artisan firefly-iii:migrate-notes
|
||||
php artisan firefly-iii:migrate-attachments
|
||||
php artisan firefly-iii:bills-to-rules
|
||||
php artisan firefly-iii:bl-currency
|
||||
php artisan firefly-iii:cc-liabilities
|
||||
php artisan firefly-iii:back-to-journals
|
||||
php artisan firefly-iii:rename-account-meta
|
||||
php artisan firefly-iii:migrate-recurrence-meta
|
||||
|
||||
# there are 14 verify commands
|
||||
php artisan firefly-iii:fix-piggies
|
||||
php artisan firefly-iii:create-link-types
|
||||
php artisan firefly-iii:create-access-tokens
|
||||
php artisan firefly-iii:remove-bills
|
||||
php artisan firefly-iii:enable-currencies
|
||||
php artisan firefly-iii:fix-transfer-budgets
|
||||
php artisan firefly-iii:fix-uneven-amount
|
||||
php artisan firefly-iii:delete-zero-amount
|
||||
php artisan firefly-iii:delete-orphaned-transactions
|
||||
php artisan firefly-iii:delete-empty-journals
|
||||
php artisan firefly-iii:delete-empty-groups
|
||||
php artisan firefly-iii:fix-account-types
|
||||
php artisan firefly-iii:rename-meta-fields
|
||||
php artisan firefly-iii:fix-ob-currencies
|
||||
|
||||
# report commands
|
||||
php artisan firefly-iii:report-empty-objects
|
||||
php artisan firefly-iii:report-sum
|
||||
|
||||
php artisan passport:install
|
||||
php artisan cache:clear
|
||||
|
||||
php artisan firefly:instructions install
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf --nodaemon
|
||||
|
||||
echo "Go!"
|
||||
exec apache2-foreground
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
[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
|
||||
35
.deploy/docker/manifest.sh
Executable file
35
.deploy/docker/manifest.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [ "$TRAVIS_BRANCH" == "develop" ]; then
|
||||
TARGET=jc5x/firefly-iii:develop
|
||||
ARM=jc5x/firefly-iii:develop-arm
|
||||
AMD=jc5x/firefly-iii:develop-amd64
|
||||
|
||||
docker manifest create $TARGET $AMD $ARM
|
||||
docker manifest annotate $TARGET $ARM --arch arm --os linux
|
||||
docker manifest annotate $TARGET $AMD --arch amd64 --os linux
|
||||
docker manifest push $TARGET
|
||||
fi
|
||||
|
||||
echo "The version is $VERSION"
|
||||
|
||||
if [ "$TRAVIS_BRANCH" == "master" ]; then
|
||||
TARGET=jc5x/firefly-iii:latest
|
||||
ARM=jc5x/firefly-iii:latest-arm
|
||||
AMD=jc5x/firefly-iii:latest-amd64
|
||||
|
||||
docker manifest create $TARGET $AMD $ARM
|
||||
docker manifest annotate $TARGET $ARM --arch arm --os linux
|
||||
docker manifest annotate $TARGET $AMD --arch amd64 --os linux
|
||||
docker manifest push $TARGET
|
||||
|
||||
# and another one for version specific:
|
||||
TARGET=jc5x/firefly-iii:release-$VERSION
|
||||
ARM=jc5x/firefly-iii:release-$VERSION-arm
|
||||
AMD=jc5x/firefly-iii:release-$VERSION-amd64
|
||||
|
||||
docker manifest create $TARGET $AMD $ARM
|
||||
docker manifest annotate $TARGET $ARM --arch arm --os linux
|
||||
docker manifest annotate $TARGET $AMD --arch amd64 --os linux
|
||||
docker manifest push $TARGET
|
||||
fi
|
||||
@@ -1,30 +0,0 @@
|
||||
# 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
|
||||
178
.deploy/docker/wait-for-it.sh
Executable file
178
.deploy/docker/wait-for-it.sh
Executable file
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env bash
|
||||
# Use this script to test if a given TCP host/port are available
|
||||
|
||||
WAITFORIT_cmdname=${0##*/}
|
||||
|
||||
echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
|
||||
|
||||
usage()
|
||||
{
|
||||
cat << USAGE >&2
|
||||
Usage:
|
||||
$WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args]
|
||||
-h HOST | --host=HOST Host or IP under test
|
||||
-p PORT | --port=PORT TCP port under test
|
||||
Alternatively, you specify the host and port as host:port
|
||||
-s | --strict Only execute subcommand if the test succeeds
|
||||
-q | --quiet Don't output any status messages
|
||||
-t TIMEOUT | --timeout=TIMEOUT
|
||||
Timeout in seconds, zero for no timeout
|
||||
-- COMMAND ARGS Execute command with args after the test finishes
|
||||
USAGE
|
||||
exit 1
|
||||
}
|
||||
|
||||
wait_for()
|
||||
{
|
||||
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
|
||||
echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
|
||||
else
|
||||
echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout"
|
||||
fi
|
||||
WAITFORIT_start_ts=$(date +%s)
|
||||
while :
|
||||
do
|
||||
if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then
|
||||
nc -z $WAITFORIT_HOST $WAITFORIT_PORT
|
||||
WAITFORIT_result=$?
|
||||
else
|
||||
(echo > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1
|
||||
WAITFORIT_result=$?
|
||||
fi
|
||||
if [[ $WAITFORIT_result -eq 0 ]]; then
|
||||
WAITFORIT_end_ts=$(date +%s)
|
||||
echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
return $WAITFORIT_result
|
||||
}
|
||||
|
||||
wait_for_wrapper()
|
||||
{
|
||||
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
|
||||
if [[ $WAITFORIT_QUIET -eq 1 ]]; then
|
||||
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
|
||||
else
|
||||
timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
|
||||
fi
|
||||
WAITFORIT_PID=$!
|
||||
trap "kill -INT -$WAITFORIT_PID" INT
|
||||
wait $WAITFORIT_PID
|
||||
WAITFORIT_RESULT=$?
|
||||
if [[ $WAITFORIT_RESULT -ne 0 ]]; then
|
||||
echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT"
|
||||
fi
|
||||
return $WAITFORIT_RESULT
|
||||
}
|
||||
|
||||
# process arguments
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
case "$1" in
|
||||
*:* )
|
||||
WAITFORIT_hostport=(${1//:/ })
|
||||
WAITFORIT_HOST=${WAITFORIT_hostport[0]}
|
||||
WAITFORIT_PORT=${WAITFORIT_hostport[1]}
|
||||
shift 1
|
||||
;;
|
||||
--child)
|
||||
WAITFORIT_CHILD=1
|
||||
shift 1
|
||||
;;
|
||||
-q | --quiet)
|
||||
WAITFORIT_QUIET=1
|
||||
shift 1
|
||||
;;
|
||||
-s | --strict)
|
||||
WAITFORIT_STRICT=1
|
||||
shift 1
|
||||
;;
|
||||
-h)
|
||||
WAITFORIT_HOST="$2"
|
||||
if [[ $WAITFORIT_HOST == "" ]]; then break; fi
|
||||
shift 2
|
||||
;;
|
||||
--host=*)
|
||||
WAITFORIT_HOST="${1#*=}"
|
||||
shift 1
|
||||
;;
|
||||
-p)
|
||||
WAITFORIT_PORT="$2"
|
||||
if [[ $WAITFORIT_PORT == "" ]]; then break; fi
|
||||
shift 2
|
||||
;;
|
||||
--port=*)
|
||||
WAITFORIT_PORT="${1#*=}"
|
||||
shift 1
|
||||
;;
|
||||
-t)
|
||||
WAITFORIT_TIMEOUT="$2"
|
||||
if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi
|
||||
shift 2
|
||||
;;
|
||||
--timeout=*)
|
||||
WAITFORIT_TIMEOUT="${1#*=}"
|
||||
shift 1
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
WAITFORIT_CLI=("$@")
|
||||
break
|
||||
;;
|
||||
--help)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
echoerr "Unknown argument: $1"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then
|
||||
echoerr "Error: you need to provide a host and port to test."
|
||||
usage
|
||||
fi
|
||||
|
||||
WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15}
|
||||
WAITFORIT_STRICT=${WAITFORIT_STRICT:-0}
|
||||
WAITFORIT_CHILD=${WAITFORIT_CHILD:-0}
|
||||
WAITFORIT_QUIET=${WAITFORIT_QUIET:-0}
|
||||
|
||||
# check to see if timeout is from busybox?
|
||||
WAITFORIT_TIMEOUT_PATH=$(type -p timeout)
|
||||
WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH)
|
||||
if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then
|
||||
WAITFORIT_ISBUSY=1
|
||||
WAITFORIT_BUSYTIMEFLAG="-t"
|
||||
|
||||
else
|
||||
WAITFORIT_ISBUSY=0
|
||||
WAITFORIT_BUSYTIMEFLAG=""
|
||||
fi
|
||||
|
||||
if [[ $WAITFORIT_CHILD -gt 0 ]]; then
|
||||
wait_for
|
||||
WAITFORIT_RESULT=$?
|
||||
exit $WAITFORIT_RESULT
|
||||
else
|
||||
if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
|
||||
wait_for_wrapper
|
||||
WAITFORIT_RESULT=$?
|
||||
else
|
||||
wait_for
|
||||
WAITFORIT_RESULT=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $WAITFORIT_CLI != "" ]]; then
|
||||
if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then
|
||||
echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess"
|
||||
exit $WAITFORIT_RESULT
|
||||
fi
|
||||
exec "${WAITFORIT_CLI[@]}"
|
||||
else
|
||||
exit $WAITFORIT_RESULT
|
||||
fi
|
||||
@@ -42,13 +42,31 @@ DB_CONNECTION=pgsql
|
||||
|
||||
|
||||
|
||||
|
||||
# PostgreSQL supports SSL. You can configure it here.
|
||||
PGSQL_SSL_MODE=prefer
|
||||
PGSQL_SSL_ROOT_CERT=null
|
||||
PGSQL_SSL_CERT=null
|
||||
PGSQL_SSL_KEY=null
|
||||
PGSQL_SSL_CRL_FILE=null
|
||||
|
||||
|
||||
# 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=
|
||||
@@ -74,11 +92,20 @@ 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=
|
||||
|
||||
# Set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this will only work for paid fixer.io accounts because they severly limited
|
||||
# Firefly III currently supports two provider for live Currency Exchange Rates:
|
||||
# "fixer" is the default (for backward compatibility), and "ratesapi" is the new one.
|
||||
# RatesApi.IO (see https://ratesapi.io) is a FREE and OPEN SOURCE live currency exchange rates,
|
||||
# built compatible with Fixer.IO, based on data published by European Central Bank, and don't require API key.
|
||||
CER_PROVIDER=fixer
|
||||
# If you have select "fixer" as default currency exchange rates,
|
||||
# set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this WILL ONLY WORK FOR PAID fixer.io accounts because they severely limited
|
||||
# the free API up to the point where you might as well offer nothing.
|
||||
FIXER_API_KEY=
|
||||
|
||||
@@ -89,9 +116,54 @@ 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 "ldap" 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=
|
||||
|
||||
# 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
|
||||
@@ -108,5 +180,4 @@ IS_DOCKER=false
|
||||
IS_SANDSTORM=false
|
||||
IS_HEROKU=true
|
||||
BUNQ_USE_SANDBOX=false
|
||||
MAILGUN_DOMAIN=
|
||||
MAILGUN_SECRET=
|
||||
FFIII_LAYOUT=v1
|
||||
14
.deploy/heroku/.locales
Normal file
14
.deploy/heroku/.locales
Normal file
@@ -0,0 +1,14 @@
|
||||
en_US
|
||||
cs_CZ
|
||||
es_ES
|
||||
de_DE
|
||||
fr_FR
|
||||
it_IT
|
||||
nb_NO
|
||||
nl_NL
|
||||
pl_PL
|
||||
pt_BR
|
||||
ro_RO
|
||||
ru_RU
|
||||
hu_HU
|
||||
el_GR
|
||||
@@ -44,17 +44,17 @@ spec:
|
||||
- image: firefly-local
|
||||
name: firefly-local
|
||||
env:
|
||||
- name: FF_APP_ENV
|
||||
- name: APP_ENV
|
||||
value: "local"
|
||||
- name: FF_APP_KEY
|
||||
- name: APP_KEY
|
||||
value: "S0m3R@nd0mString0f32Ch@rsEx@ct1y"
|
||||
- name: FF_DB_HOST
|
||||
- name: DB_HOST
|
||||
value: "172.17.0.9"
|
||||
- name: FF_DB_NAME
|
||||
- name: DB_NAME
|
||||
value: "firefly_db"
|
||||
- name: FF_DB_USER
|
||||
- name: DB_USER
|
||||
value: "firefly_db"
|
||||
- name: FF_DB_PASSWORD
|
||||
- name: DB_PASSWORD
|
||||
value: "password"
|
||||
volumeMounts:
|
||||
- mountPath: "/var/www/firefly-iii/storage/export"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
APP_ENV=local
|
||||
|
||||
# Set to true if you want to see debug information in error screens.
|
||||
APP_DEBUG=false
|
||||
APP_DEBUG=true
|
||||
|
||||
# This should be your email address
|
||||
SITE_OWNER=sandstorm@example.com
|
||||
@@ -49,6 +49,19 @@ DB_PASSWORD=firefly
|
||||
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=
|
||||
@@ -74,11 +87,20 @@ 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=
|
||||
|
||||
# Set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this will only work for paid fixer.io accounts because they severly limited
|
||||
# Firefly III currently supports two provider for live Currency Exchange Rates:
|
||||
# "fixer" is the default (for backward compatibility), and "ratesapi" is the new one.
|
||||
# RatesApi.IO (see https://ratesapi.io) is a FREE and OPEN SOURCE live currency exchange rates,
|
||||
# built compatible with Fixer.IO, based on data published by European Central Bank, and don't require API key.
|
||||
CER_PROVIDER=fixer
|
||||
# If you have select "fixer" as default currency exchange rates,
|
||||
# set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this WILL ONLY WORK FOR PAID fixer.io accounts because they severely limited
|
||||
# the free API up to the point where you might as well offer nothing.
|
||||
FIXER_API_KEY=
|
||||
|
||||
@@ -89,9 +111,54 @@ 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 "ldap" 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=
|
||||
|
||||
# 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
|
||||
@@ -108,5 +175,4 @@ IS_DOCKER=false
|
||||
IS_SANDSTORM=true
|
||||
IS_HEROKU=false
|
||||
BUNQ_USE_SANDBOX=false
|
||||
MAILGUN_DOMAIN=
|
||||
MAILGUN_SECRET=
|
||||
FFIII_LAYOUT=v1
|
||||
112
.env.docker
112
.env.docker
@@ -1,112 +0,0 @@
|
||||
# You can leave this on "local". If you change it to production most console commands will ask for extra confirmation.
|
||||
# Never set it to "testing".
|
||||
APP_ENV=${FF_APP_ENV}
|
||||
|
||||
# Set to true if you want to see debug information in error screens.
|
||||
APP_DEBUG=${APP_DEBUG}
|
||||
|
||||
# This should be your email address
|
||||
SITE_OWNER=${SITE_OWNER}
|
||||
|
||||
# The encryption key for your database and sessions. Keep this very secure.
|
||||
# If you generate a new one all existing data must be considered LOST.
|
||||
# Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it
|
||||
APP_KEY=${FF_APP_KEY}
|
||||
|
||||
# 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.
|
||||
# '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=${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
|
||||
|
||||
# Cookie settings. Should not be necessary to change these.
|
||||
COOKIE_PATH="/"
|
||||
COOKIE_DOMAIN=
|
||||
COOKIE_SECURE=false
|
||||
|
||||
# If you want Firefly III to mail you, update these settings
|
||||
# For instructions, see: https://firefly-iii.readthedocs.io/en/latest/installation/mail.html
|
||||
MAIL_DRIVER=${MAIL_DRIVER}
|
||||
MAIL_HOST=${MAIL_HOST}
|
||||
MAIL_PORT=${MAIL_PORT}
|
||||
MAIL_FROM=${MAIL_FROM}
|
||||
MAIL_USERNAME=${MAIL_USERNAME}
|
||||
MAIL_PASSWORD=${MAIL_PASSWORD}
|
||||
MAIL_ENCRYPTION=${MAIL_ENCRYPTION}
|
||||
|
||||
# Other mail drivers:
|
||||
MAILGUN_DOMAIN=${MAILGUN_DOMAIN}
|
||||
MAILGUN_SECRET=${MAILGUN_SECRET}
|
||||
MANDRILL_SECRET=${MANDRILL_SECRET}
|
||||
SPARKPOST_SECRET=${SPARKPOST_SECRET}
|
||||
|
||||
# Firefly III can send you the following messages
|
||||
SEND_REGISTRATION_MAIL=true
|
||||
SEND_ERROR_MESSAGE=false
|
||||
|
||||
# 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}
|
||||
|
||||
# Set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this will only work for paid fixer.io accounts because they severly limited
|
||||
# the free API up to the point where you might as well offer nothing.
|
||||
FIXER_API_KEY=${FIXER_API_KEY}
|
||||
|
||||
# If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here.
|
||||
ANALYTICS_ID=${ANALYTICS_ID}
|
||||
|
||||
# Most parts of the database are encrypted by default, but you can turn this off if you want to.
|
||||
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
||||
USE_ENCRYPTION=true
|
||||
|
||||
# Leave the following configuration vars as is.
|
||||
# Unless you like to tinker and know what you're doing.
|
||||
APP_NAME=FireflyIII
|
||||
BROADCAST_DRIVER=log
|
||||
QUEUE_DRIVER=sync
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
CACHE_PREFIX=firefly
|
||||
SEARCH_RESULT_LIMIT=50
|
||||
PUSHER_KEY=
|
||||
PUSHER_SECRET=
|
||||
PUSHER_ID=
|
||||
DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
IS_DOCKER=true
|
||||
IS_SANDSTORM=false
|
||||
IS_HEROKU=false
|
||||
BUNQ_USE_SANDBOX=false
|
||||
MAILGUN_DOMAIN=
|
||||
MAILGUN_SECRET=
|
||||
102
.env.example
102
.env.example
@@ -8,8 +8,8 @@ APP_DEBUG=false
|
||||
# This should be your email address
|
||||
SITE_OWNER=mail@example.com
|
||||
|
||||
# The encryption key for your database and sessions. Keep this very secure.
|
||||
# If you generate a new one all existing data must be considered LOST.
|
||||
# The encryption key for your sessions. Keep this very secure.
|
||||
# If you generate a new one existing data must be considered LOST.
|
||||
# Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it
|
||||
APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
|
||||
@@ -22,6 +22,7 @@ TZ=Europe/Amsterdam
|
||||
APP_URL=http://localhost
|
||||
|
||||
# TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy.
|
||||
# Set it to ** and reverse proxies work just fine.
|
||||
TRUSTED_PROXIES=
|
||||
|
||||
# The log channel defines where your log entries go to.
|
||||
@@ -38,17 +39,37 @@ 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
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=homestead
|
||||
DB_USERNAME=homestead
|
||||
DB_PASSWORD=secret
|
||||
DB_CONNECTION=pgsql
|
||||
DB_HOST=firefly_iii_db
|
||||
DB_PORT=5432
|
||||
DB_DATABASE=firefly
|
||||
DB_USERNAME=firefly
|
||||
DB_PASSWORD=secret_firefly_password
|
||||
|
||||
# PostgreSQL supports SSL. You can configure it here.
|
||||
PGSQL_SSL_MODE=prefer
|
||||
PGSQL_SSL_ROOT_CERT=null
|
||||
PGSQL_SSL_CERT=null
|
||||
PGSQL_SSL_KEY=null
|
||||
PGSQL_SSL_CRL_FILE=null
|
||||
|
||||
# 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=
|
||||
@@ -74,24 +95,75 @@ 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=
|
||||
|
||||
# Set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this will only work for paid fixer.io accounts because they severly limited
|
||||
# Firefly III currently supports two provider for live Currency Exchange Rates:
|
||||
# "fixer", and "ratesapi".
|
||||
# RatesApi.IO (see https://ratesapi.io) is a FREE and OPEN SOURCE live currency exchange rates,
|
||||
# built compatible with Fixer.IO, based on data published by European Central Bank, and doesn't require API key.
|
||||
CER_PROVIDER=ratesapi
|
||||
|
||||
# If you have select "fixer" as default currency exchange rates,
|
||||
# set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this WILL ONLY WORK FOR PAID fixer.io accounts because they severely limited
|
||||
# the free API up to the point where you might as well offer nothing.
|
||||
FIXER_API_KEY=
|
||||
|
||||
# If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here.
|
||||
ANALYTICS_ID=
|
||||
|
||||
# Most parts of the database are encrypted by default, but you can turn this off if you want to.
|
||||
# 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 "ldap" 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=
|
||||
|
||||
# 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,8 +177,8 @@ PUSHER_ID=
|
||||
DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
IS_DOCKER=false
|
||||
USE_ENCRYPTION=false
|
||||
IS_SANDSTORM=false
|
||||
IS_HEROKU=false
|
||||
BUNQ_USE_SANDBOX=false
|
||||
MAILGUN_DOMAIN=
|
||||
MAILGUN_SECRET=
|
||||
FFIII_LAYOUT=v1
|
||||
|
||||
112
.env.testing
112
.env.testing
@@ -1,112 +0,0 @@
|
||||
# You can leave this on "local". If you change it to production most console commands will ask for extra confirmation.
|
||||
# Never set it to "testing".
|
||||
APP_ENV=testing
|
||||
|
||||
# Set to true if you want to see debug information in error screens.
|
||||
APP_DEBUG=true
|
||||
|
||||
# This should be your email address
|
||||
SITE_OWNER=thegrumpydictator+testing@gmail.com
|
||||
|
||||
# The encryption key for your database and sessions. Keep this very secure.
|
||||
# If you generate a new one all existing data must be considered LOST.
|
||||
# Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it
|
||||
APP_KEY=TestTestTestTestTestTestTestTest
|
||||
|
||||
# Change this value to your preferred time zone.
|
||||
# Example: Europe/Amsterdam
|
||||
TZ=Europe/Amsterdam
|
||||
|
||||
# This variable must match your installation's external address but keep in mind that
|
||||
# it's only used on the command line as a fallback value.
|
||||
APP_URL=http://localhost
|
||||
|
||||
# TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy.
|
||||
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=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
|
||||
|
||||
# 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
|
||||
|
||||
# Cookie settings. Should not be necessary to change these.
|
||||
COOKIE_PATH="/"
|
||||
COOKIE_DOMAIN=
|
||||
COOKIE_SECURE=false
|
||||
|
||||
# If you want Firefly III to mail you, update these settings
|
||||
# For instructions, see: https://firefly-iii.readthedocs.io/en/latest/installation/mail.html
|
||||
MAIL_DRIVER=log
|
||||
MAIL_HOST=smtp.mailtrap.io
|
||||
MAIL_PORT=2525
|
||||
MAIL_FROM=changeme@example.com
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
|
||||
# Other mail drivers:
|
||||
MAILGUN_DOMAIN=
|
||||
MAILGUN_SECRET=
|
||||
MANDRILL_SECRET=
|
||||
SPARKPOST_SECRET=
|
||||
|
||||
# Firefly III can send you the following messages
|
||||
SEND_REGISTRATION_MAIL=true
|
||||
SEND_ERROR_MESSAGE=false
|
||||
|
||||
# Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places.
|
||||
MAPBOX_API_KEY=
|
||||
|
||||
# Set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this will only work for paid fixer.io accounts because they severly limited
|
||||
# the free API up to the point where you might as well offer nothing.
|
||||
FIXER_API_KEY=
|
||||
|
||||
# If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here.
|
||||
ANALYTICS_ID=
|
||||
|
||||
# Most parts of the database are encrypted by default, but you can turn this off if you want to.
|
||||
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
||||
USE_ENCRYPTION=false
|
||||
|
||||
# Leave the following configuration vars as is.
|
||||
# Unless you like to tinker and know what you're doing.
|
||||
APP_NAME=FireflyIII
|
||||
BROADCAST_DRIVER=log
|
||||
QUEUE_DRIVER=sync
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
CACHE_PREFIX=firefly_tst
|
||||
SEARCH_RESULT_LIMIT=50
|
||||
PUSHER_KEY=
|
||||
PUSHER_SECRET=
|
||||
PUSHER_ID=
|
||||
DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
IS_DOCKER=false
|
||||
IS_SANDSTORM=false
|
||||
IS_HEROKU=false
|
||||
BUNQ_USE_SANDBOX=true
|
||||
MAILGUN_DOMAIN=
|
||||
MAILGUN_SECRET=
|
||||
17
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
17
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@@ -5,18 +5,23 @@ about: Create a report to help Firefly III improve
|
||||
---
|
||||
|
||||
**Bug description**
|
||||
I am running Firefly III version x.x.x
|
||||
I am running Firefly III version x.x.x, and my problem is:
|
||||
|
||||
(please give a clear and concise description of what the bug is)
|
||||
<!-- Replace the version and describe your problem or your issue will be closed. -->
|
||||
|
||||
**Steps to reproduce**
|
||||
What do you need to do to trigger this bug?
|
||||
<!-- 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).
|
||||
<!-- Please add extra info here, such as OS, browser, and the output from the /debug page of your Firefly III installation (click the version at the bottom). -->
|
||||
|
||||
**Bonus points**
|
||||
Earn bonus points by:
|
||||
<!-- Earn bonus points by:
|
||||
|
||||
- Post a stacktrace from your log files
|
||||
- Add a screenshot
|
||||
- Add a screenshot
|
||||
- Remember the human
|
||||
-->
|
||||
18
.github/ISSUE_TEMPLATE/Custom.md
vendored
18
.github/ISSUE_TEMPLATE/Custom.md
vendored
@@ -7,21 +7,19 @@ about: Ask away!
|
||||
I am running Firefly III version x.x.x
|
||||
|
||||
**Description**
|
||||
|
||||
|
||||
|
||||
**Steps to reproduce**
|
||||
(if relevant of course)
|
||||
|
||||
|
||||
<!-- (if relevant of course) -->
|
||||
|
||||
**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).
|
||||
<!-- Please add extra info here, such as OS, browser, and the output from the `/debug`-page of your Firefly III installation (click the version at the bottom). -->
|
||||
|
||||
|
||||
|
||||
**Bonus points**
|
||||
Earn bonus points by:
|
||||
<!-- Earn bonus points by:
|
||||
|
||||
- Add a screenshot
|
||||
- Replicate the problem on the demo site https://demo.firefly-iii.org/
|
||||
- Make a drawing
|
||||
- Donate money (just kidding ;)
|
||||
- Replicate the problem on the demo site https://demo.firefly-iii.org/
|
||||
- Remember the human
|
||||
-->
|
||||
23
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
23
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
@@ -5,17 +5,28 @@ about: Suggest an idea or feature for Firefly III
|
||||
---
|
||||
|
||||
**Description**
|
||||
<!--
|
||||
Please describe your feature request:
|
||||
|
||||
- I would like Firefly III to do X.
|
||||
- What if you would add feature Y?
|
||||
- Firefly III doesn't do Z.
|
||||
- I would like Firefly III to do ABC.
|
||||
- What if you would add feature XYZ?
|
||||
- Firefly III doesn't do DEF.
|
||||
|
||||
-->
|
||||
|
||||
**Solution**
|
||||
Describe what your feature would add to Firefly III.
|
||||
<!-- Describe what your feature would add to Firefly III. -->
|
||||
|
||||
**What are alternatives?**
|
||||
Please describe what alternatives currently exist.
|
||||
<!-- Please describe what alternatives currently exist. -->
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
<!-- Add any other context or screenshots about the feature request here. -->
|
||||
|
||||
**Bonus points**
|
||||
<!-- Earn bonus points by:
|
||||
|
||||
- Make a drawing
|
||||
- Donate money (just kidding ;)
|
||||
- Remember the human
|
||||
-->
|
||||
5
.github/funding.yml
vendored
Normal file
5
.github/funding.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
#github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: JC5
|
||||
custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA
|
||||
11
.github/pull_request_template.md
vendored
11
.github/pull_request_template.md
vendored
@@ -1,4 +1,13 @@
|
||||
Fixes # (if relevant)
|
||||
<!--
|
||||
Before you create a new PR, please consider the following two considerations.
|
||||
|
||||
1) Pull request for the MASTER branch will be closed.
|
||||
2) We cannot accept pull requests to add new currencies.
|
||||
|
||||
Thanks.
|
||||
-->
|
||||
|
||||
Fixes issue # (if relevant)
|
||||
|
||||
Changes in this pull request:
|
||||
|
||||
|
||||
8
.github/ranger.yml
vendored
Normal file
8
.github/ranger.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# in .github/ranger.yml
|
||||
comments:
|
||||
-
|
||||
action: delete_comment
|
||||
pattern: 1
|
||||
-
|
||||
action: delete_comment
|
||||
pattern: ":+1:"
|
||||
12
.github/security.md
vendored
Normal file
12
.github/security.md
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Only the latest version of Firefly III is supported. If you're not running the latest version of Firefly III, please upgrade at your earliest convenience.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you find something that compromises the security of Firefly III, you should [send me a message](mailto:thegrumpydictator@gmail.com) as soon as possible. These issues will be fixed immediately. You can also open an issue, but if you feel the issue is sensitive, please drop me a message instead.
|
||||
|
||||
You can use my [GPG key](https://keybase.io/jc5) for extra security. My [GitHub commits](https://github.com/firefly-iii/firefly-iii/commits/master) are almost always signed with this key.
|
||||
|
||||
7
.github/stale.yml
vendored
7
.github/stale.yml
vendored
@@ -1,7 +1,7 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 14
|
||||
daysUntilStale: 7
|
||||
|
||||
# Number of days of inactivity before a stale Issue or Pull Request is closed.
|
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||
@@ -13,6 +13,9 @@ exemptLabels:
|
||||
- enhancement
|
||||
- feature
|
||||
- bug
|
||||
- possible-bug
|
||||
- "possible bug"
|
||||
- announcement
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
@@ -53,4 +56,4 @@ limitPerRun: 30
|
||||
|
||||
# issues:
|
||||
# exemptLabels:
|
||||
# - confirmed
|
||||
# - confirmed
|
||||
|
||||
@@ -6,7 +6,7 @@ set -euo pipefail
|
||||
echo "In build.sh"
|
||||
|
||||
cd /opt/app
|
||||
cp .env.sandstorm .env
|
||||
cp .deploy/sandstorm/.env.sandstorm .env
|
||||
|
||||
if [ -f /opt/app/composer.json ] ; then
|
||||
if [ ! -f composer.phar ] ; then
|
||||
|
||||
@@ -1,3 +1,397 @@
|
||||
# 4.8.1 (API 0.10.2)
|
||||
|
||||
- Firefly III 4.8.1 requires PHP 7.3.
|
||||
- Support for Greek
|
||||
- [Issue 2383](https://github.com/firefly-iii/firefly-iii/issues/2383) Some tables in reports now also report percentages.
|
||||
- [Issue 2389](https://github.com/firefly-iii/firefly-iii/issues/2389) Add category / budget information to transaction lists.
|
||||
- [Issue 2464](https://github.com/firefly-iii/firefly-iii/issues/2464) Can now search for tag.
|
||||
- [Issue 2466](https://github.com/firefly-iii/firefly-iii/issues/2466) Can order recurring transactions in a more useful manner.
|
||||
- [Issue 2497](https://github.com/firefly-iii/firefly-iii/issues/2497) Transaction creation moment in hover of tag title.
|
||||
- [Issue 2471](https://github.com/firefly-iii/firefly-iii/issues/2471) Added date tag to table cells.
|
||||
- [Issue 2291](https://github.com/firefly-iii/firefly-iii/issues/2291) All reports are now properly multi-currency.
|
||||
- [Issue 2481](https://github.com/firefly-iii/firefly-iii/issues/2481) As part of the removal of local encryption, uploads and imports are no longer encrypted.
|
||||
- [Issue 2495](https://github.com/firefly-iii/firefly-iii/issues/2495) A better message of transaction submission.
|
||||
- [Issue 2506](https://github.com/firefly-iii/firefly-iii/issues/2506) Some bugs in tag report fixed.
|
||||
- [Issue 2510](https://github.com/firefly-iii/firefly-iii/issues/2510) All transaction descriptions cut off at 255 chars.
|
||||
- Better sum in bill view.
|
||||
- Clean up docker files for flawless operation.
|
||||
- The bunq API has changed, and support for bunq has been disabled.
|
||||
- [Issue 2470](https://github.com/firefly-iii/firefly-iii/issues/2470) Bad links for transactions.
|
||||
- [Issue 2480](https://github.com/firefly-iii/firefly-iii/issues/2480) Large queries would break in SQLite.
|
||||
- [Issue 2484](https://github.com/firefly-iii/firefly-iii/issues/2484) Transaction description auto-complete.
|
||||
- [Issue 2487](https://github.com/firefly-iii/firefly-iii/issues/2487) Fix issues with FinTS
|
||||
- [Issue 2488](https://github.com/firefly-iii/firefly-iii/issues/2488) 404 after deleting a tag.
|
||||
- [Issue 2490](https://github.com/firefly-iii/firefly-iii/issues/2490) "Reset form after submission" doesn't work.
|
||||
- [Issue 2492](https://github.com/firefly-iii/firefly-iii/issues/2492) After submitting and fixing an error, the error is persistent.
|
||||
- [Issue 2493](https://github.com/firefly-iii/firefly-iii/issues/2493) Auto detect transaction type is a bit better now.
|
||||
- [Issue 2498](https://github.com/firefly-iii/firefly-iii/issues/2498) Pressing enter in some fields breaks the form.
|
||||
- [Issue 2499](https://github.com/firefly-iii/firefly-iii/issues/2499) Auto-complete issues in transaction link form.
|
||||
- [Issue 2500](https://github.com/firefly-iii/firefly-iii/issues/2500) Issue when submitting edited transactions.
|
||||
- [Issue 2501](https://github.com/firefly-iii/firefly-iii/issues/2501) Better error messages for empty submissions.
|
||||
- [Issue 2508](https://github.com/firefly-iii/firefly-iii/issues/2508) Can remove category from transaction.
|
||||
- [Issue 2516](https://github.com/firefly-iii/firefly-iii/issues/2516) Can no longer import transactions with no amount.
|
||||
- [Issue 2518](https://github.com/firefly-iii/firefly-iii/issues/2518) Link in balance box goes to current period.
|
||||
- [Issue 2521](https://github.com/firefly-iii/firefly-iii/issues/2521) Foreign transaction currency is hidden when the user hasn't enabled foreign currencies.
|
||||
- [Issue 2522](https://github.com/firefly-iii/firefly-iii/issues/2522) Some reports were missing the "overspent" field.
|
||||
- [Issue 2526](https://github.com/firefly-iii/firefly-iii/issues/2526) It was impossible to remove the budget of a transaction.
|
||||
- [Issue 2527](https://github.com/firefly-iii/firefly-iii/issues/2527) Some bulk edits were buggy.
|
||||
- [Issue 2539](https://github.com/firefly-iii/firefly-iii/issues/2539) Fixed a typo.
|
||||
- [Issue 2545](https://github.com/firefly-iii/firefly-iii/issues/2545) Deleted tags would still show up.
|
||||
- [Issue 2547](https://github.com/firefly-iii/firefly-iii/issues/2547) Changing the opening balance to 0 will now remove it.
|
||||
- [Issue 2549](https://github.com/firefly-iii/firefly-iii/issues/2549) Can now clone transactions again.
|
||||
- [Issue 2550](https://github.com/firefly-iii/firefly-iii/issues/2550) Added missing locales for moment.js
|
||||
- [Issue 2553](https://github.com/firefly-iii/firefly-iii/issues/2553) Fixed an issue with split transactions.
|
||||
- [Issue 2555](https://github.com/firefly-iii/firefly-iii/issues/2555) Better error for when you submit the same account twice.
|
||||
- [Issue 2439](https://github.com/firefly-iii/firefly-iii/issues/2439) SQL error in API post new user
|
||||
- ... and many other bugs.
|
||||
- [Issue 2475](https://github.com/firefly-iii/firefly-iii/issues/2475) Tags are now the same for all views.
|
||||
- [Issue 2476](https://github.com/firefly-iii/firefly-iii/issues/2476) Amount is now represented equally in all views.
|
||||
- [Issue 2477](https://github.com/firefly-iii/firefly-iii/issues/2477) Rules are easier to update.
|
||||
- [Issue 2483](https://github.com/firefly-iii/firefly-iii/issues/2483) Several consistencies fixed.
|
||||
- [Issue 2484](https://github.com/firefly-iii/firefly-iii/issues/2484) Transaction link view fixed.
|
||||
- [Issue 2557](https://github.com/firefly-iii/firefly-iii/issues/2557) Fix for issue in summary API
|
||||
- No longer have to submit mandatory fields to account end point. Just submit the field you wish to update, the rest will be untouched.
|
||||
- Rules will no longer list the "user-action" trigger Rules will have a "moment" field that says either "update-journal" or "store-journal".
|
||||
|
||||
# 4.8.0.3 (API 0.10.1)
|
||||
|
||||
- Autocomplete for transaction description.
|
||||
- [Issue 2438](https://github.com/firefly-iii/firefly-iii/issues/2438) Some balance issues when working with multiple currencies (a known issue)
|
||||
- [Issue 2425](https://github.com/firefly-iii/firefly-iii/issues/2425) Transaction edit/create form is weird with the enter button
|
||||
- [Issue 2424](https://github.com/firefly-iii/firefly-iii/issues/2424) auto complete tab doesn't work.
|
||||
- [Issue 2441](https://github.com/firefly-iii/firefly-iii/issues/2441) Inconsistent character limit for currencies.
|
||||
- [Issue 2443](https://github.com/firefly-iii/firefly-iii/issues/2443) 500 error when submitting budgets
|
||||
- [Issue 2446](https://github.com/firefly-iii/firefly-iii/issues/2446) Can't update current amount for piggy bank
|
||||
- [Issue 2440](https://github.com/firefly-iii/firefly-iii/issues/2440) Errors when interacting with recurring transactions
|
||||
- [Issue 2439](https://github.com/firefly-iii/firefly-iii/issues/2439) SQL error in API post new user
|
||||
- Transaction report (after import, over email) is mostly empty
|
||||
- Mass edit checkboxes doesn't work in a tag overview
|
||||
- [Issue 2437](https://github.com/firefly-iii/firefly-iii/issues/2437) CPU issues when viewing accounts, probably run-away queries.
|
||||
- [Issue 2432](https://github.com/firefly-iii/firefly-iii/issues/2432) Can't disable all currencies except one / can't disable EUR and switch to something else.
|
||||
- Option to edit the budget is gone from edit transaction form.
|
||||
- [Issue 2453](https://github.com/firefly-iii/firefly-iii/issues/2453) Search view things
|
||||
- [Issue 2449](https://github.com/firefly-iii/firefly-iii/issues/2449) Can't add invoice date.
|
||||
- [Issue 2448](https://github.com/firefly-iii/firefly-iii/issues/2448) Bad link in transaction overview
|
||||
- [Issue 2447](https://github.com/firefly-iii/firefly-iii/issues/2447) Bad link in bill overview
|
||||
- Improvements to various API end-points. Docs are updated.
|
||||
|
||||
# 4.8.0.2 (API 0.10.0)
|
||||
|
||||
- [Issue 2203](https://github.com/firefly-iii/firefly-iii/issues/2203) Reconciliation inconsistencies.
|
||||
- [Issue 2392](https://github.com/firefly-iii/firefly-iii/issues/2392) Bad namespace leads to installation errors.
|
||||
- [Issue 2393](https://github.com/firefly-iii/firefly-iii/issues/2393) Missing budget selector.
|
||||
- [Issue 2402](https://github.com/firefly-iii/firefly-iii/issues/2402) bad amounts in default report
|
||||
- [Issue 2405](https://github.com/firefly-iii/firefly-iii/issues/2405) Due date can't be edited.
|
||||
- [Issue 2404](https://github.com/firefly-iii/firefly-iii/issues/2404) bad page indicator in the "no category" transaction overview.
|
||||
- [Issue 2407](https://github.com/firefly-iii/firefly-iii/issues/2407) Fix recurring transaction dates
|
||||
- [Issue 2410](https://github.com/firefly-iii/firefly-iii/issues/2410) Transaction links inconsistent
|
||||
- [Issue 2414](https://github.com/firefly-iii/firefly-iii/issues/2414) Can't edit recurring transactions
|
||||
- [Issue 2415](https://github.com/firefly-iii/firefly-iii/issues/2415) Return here + reset form results in empty transaction form
|
||||
- [Issue 2416](https://github.com/firefly-iii/firefly-iii/issues/2416) Some form inconsistencies.
|
||||
- [Issue 2418](https://github.com/firefly-iii/firefly-iii/issues/2418) Reports are inaccurate or broken.
|
||||
- [Issue 2422](https://github.com/firefly-iii/firefly-iii/issues/2422) PHP error when matching transactions.
|
||||
- [Issue 2423](https://github.com/firefly-iii/firefly-iii/issues/2423) Reports are inaccurate or broken.
|
||||
- [Issue 2426](https://github.com/firefly-iii/firefly-iii/issues/2426) Inconsistent documentation and instructions.
|
||||
- [Issue 2427](https://github.com/firefly-iii/firefly-iii/issues/2427) Deleted account and "initial balance" accounts may appear in dropdowns.
|
||||
- [Issue 2428](https://github.com/firefly-iii/firefly-iii/issues/2428) Reports are inaccurate or broken.
|
||||
- [Issue 2429](https://github.com/firefly-iii/firefly-iii/issues/2429) Typo leads to SQL errors in available budgets API
|
||||
- [Issue 2431](https://github.com/firefly-iii/firefly-iii/issues/2431) Issues creating new recurring transactions.
|
||||
- [Issue 2434](https://github.com/firefly-iii/firefly-iii/issues/2434) You can edit the initial balance transaction but it fails to save.
|
||||
- ARM build should work now.
|
||||
|
||||
# 4.8.0.1 (API 0.10.0)
|
||||
|
||||
- The balance box on the dashboard shows only negative numbers, skewing the results.
|
||||
- Selecting or using tags in new transactions results in an error.
|
||||
- Editing a transaction with tags will drop the tags from the transaction.
|
||||
- [Issue 2382](https://github.com/firefly-iii/firefly-iii/issues/2382) Ranger config
|
||||
- [Issue 2384](https://github.com/firefly-iii/firefly-iii/issues/2384) When upgrading manually, you may see: `The command "generate-keys" does not exist.`
|
||||
- [Issue 2385](https://github.com/firefly-iii/firefly-iii/issues/2385) When upgrading manually, the firefly:verify command may fail to run.
|
||||
- [Issue 2388](https://github.com/firefly-iii/firefly-iii/issues/2388) When registering as a new user, leaving the opening balance at 0 will give you an error.
|
||||
- [Issue 2395](https://github.com/firefly-iii/firefly-iii/issues/2395) Editing split transactions is broken.
|
||||
- [Issue 2397](https://github.com/firefly-iii/firefly-iii/issues/2397) Transfers are stored the wrong way around.
|
||||
- [Issue 2399](https://github.com/firefly-iii/firefly-iii/issues/2399) Not all account balances are updated after you create a new transaction.
|
||||
- [Issue 2401](https://github.com/firefly-iii/firefly-iii/issues/2401) Could not delete a split from a split transaction.
|
||||
|
||||
# 4.8.0 (API 0.10.0)
|
||||
|
||||
- Hungarian translation!
|
||||
- New database model that changes the concept of "split transactions";
|
||||
- New installation routine with rewritten database integrity tests and upgrade code;
|
||||
- Rewritten screen to create transactions which will now completely rely on the API;
|
||||
- Most terminal commands now have the prefix `firefly-iii`.
|
||||
- New MFA code that will generate backup codes for you and is more robust. MFA will have to be re-enabled for ALL users.
|
||||
- This will probably be the last Firefly III version to have import routines for files, Bunq and others. These will be moved to separate applications that use the Firefly III API.
|
||||
- The export function has been removed.
|
||||
- [Issue 1652](https://github.com/firefly-iii/firefly-iii/issues/1652), new strings to use during the import.
|
||||
- [Issue 1860](https://github.com/firefly-iii/firefly-iii/issues/1860), fixing the default currency not being on top in a JSON box.
|
||||
- [Issue 2031](https://github.com/firefly-iii/firefly-iii/issues/2031), a fix for Triodos imports.
|
||||
- [Issue 2153](https://github.com/firefly-iii/firefly-iii/issues/2153), problems with editing credit cards.
|
||||
- [Issue 2179](https://github.com/firefly-iii/firefly-iii/issues/2179), consistent and correct redirect behavior.
|
||||
- [Issue 2180](https://github.com/firefly-iii/firefly-iii/issues/2180), API issues with foreign amounts.
|
||||
- [Issue 2187](https://github.com/firefly-iii/firefly-iii/issues/2187), bulk editing reconciled transactions was broken.
|
||||
- [Issue 2188](https://github.com/firefly-iii/firefly-iii/issues/2188), redirect loop in bills
|
||||
- [Issue 2189](https://github.com/firefly-iii/firefly-iii/issues/2189), bulk edit could not handle tags.
|
||||
- [Issue 2203](https://github.com/firefly-iii/firefly-iii/issues/2203), [issue 2208](https://github.com/firefly-iii/firefly-iii/issues/2208), [issue 2352](https://github.com/firefly-iii/firefly-iii/issues/2352), reconciliation fixes
|
||||
- [Issue 2204](https://github.com/firefly-iii/firefly-iii/issues/2204), transaction type fix
|
||||
- [Issue 2211](https://github.com/firefly-iii/firefly-iii/issues/2211), mass edit fixes.
|
||||
- [Issue 2212](https://github.com/firefly-iii/firefly-iii/issues/2212), bug in the API when deleting objects.
|
||||
- [Issue 2214](https://github.com/firefly-iii/firefly-iii/issues/2214), could not view attachment.
|
||||
- [Issue 2219](https://github.com/firefly-iii/firefly-iii/issues/2219), max amount was a little low.
|
||||
- [Issue 2239](https://github.com/firefly-iii/firefly-iii/issues/2239), fixed ordering issue.
|
||||
- [Issue 2246](https://github.com/firefly-iii/firefly-iii/issues/2246), could not disable EUR.
|
||||
- [Issue 2268](https://github.com/firefly-iii/firefly-iii/issues/2268), could not import into liability accounts.
|
||||
- [Issue 2293](https://github.com/firefly-iii/firefly-iii/issues/2293), could not trigger rule on deposits in some circumstances
|
||||
- [Issue 2314](https://github.com/firefly-iii/firefly-iii/issues/2314), could not trigger rule on transfers in some circumstances
|
||||
- [Issue 2325](https://github.com/firefly-iii/firefly-iii/issues/2325), some balance issues on the frontpage.
|
||||
- [Issue 2328](https://github.com/firefly-iii/firefly-iii/issues/2328), some date range issues in reports
|
||||
- [Issue 2331](https://github.com/firefly-iii/firefly-iii/issues/2331), some broken fields in reports.
|
||||
- [Issue 2333](https://github.com/firefly-iii/firefly-iii/issues/2333), API issues with piggy banks.
|
||||
- [Issue 2355](https://github.com/firefly-iii/firefly-iii/issues/2355), configuration issues with LDAP
|
||||
- [Issue 2361](https://github.com/firefly-iii/firefly-iii/issues/2361), some ordering issues.
|
||||
- Updated API to reflect the changes in the database.
|
||||
- New API end-point for a summary of your data.
|
||||
- Some new API charts.
|
||||
|
||||
# 4.7.17.6 (API 0.9.2)
|
||||
|
||||
- XSS issue in liability account redirect, found by [@0x2500](https://github.com/0x2500).
|
||||
|
||||
# 4.7.17.5 (API 0.9.2)
|
||||
|
||||
- Several XSS issues, found by [@0x2500](https://github.com/0x2500).
|
||||
|
||||
# 4.7.17.4 (API 0.9.2)
|
||||
|
||||
- Several XSS issues, found by [@0x2500](https://github.com/0x2500).
|
||||
|
||||
# 4.7.17.3 (API 0.9.2)
|
||||
|
||||
- XSS bug in file uploads (x2), found by [@dayn1ne](https://github.com/dayn1ne).
|
||||
- XSS bug in search, found by [@dayn1ne](https://github.com/dayn1ne).
|
||||
|
||||
# 4.7.17.2 (API 0.9.2)
|
||||
- XSS bug in budget title, found by [@dayn1ne](https://github.com/dayn1ne).
|
||||
|
||||
# 4.7.17 (API 0.9.2)
|
||||
- Support for Norwegian!
|
||||
- Clear cache during install routine.
|
||||
- Add Firefly III version number to install routine.
|
||||
- Initial release.
|
||||
- [Issue 2159](https://github.com/firefly-iii/firefly-iii/issues/2159) Bad redirect due to Laravel upgrade.
|
||||
- [Issue 2166](https://github.com/firefly-iii/firefly-iii/issues/2166) Importer had some issues with distinguishing double transfers.
|
||||
- [Issue 2167](https://github.com/firefly-iii/firefly-iii/issues/2167) New LDAP package gave some configuration changes.
|
||||
- [Issue 2173](https://github.com/firefly-iii/firefly-iii/issues/2173) Missing class when generating 2FA codes.
|
||||
|
||||
# 4.7.16 (API 0.9.2)
|
||||
- 4.7.16 was released to fix a persistent issue with broken user preferences.
|
||||
- Firefly III now uses Laravel 5.8
|
||||
|
||||
# 4.7.15 (API 0.9.2)
|
||||
- 4.7.15 was released to fix some issues upgrading from older versions.
|
||||
- [Issue 2128](https://github.com/firefly-iii/firefly-iii/issues/2128) Support for Postgres SSL
|
||||
- [Issue 2120](https://github.com/firefly-iii/firefly-iii/issues/2120) Add a missing meta tag, thanks to @lastlink
|
||||
- Search is a lot faster now.
|
||||
- [Issue 2125](https://github.com/firefly-iii/firefly-iii/issues/2125) Decryption issues during upgrade
|
||||
- [Issue 2130](https://github.com/firefly-iii/firefly-iii/issues/2130) Fixed database migrations and rollbacks.
|
||||
- [Issue 2135](https://github.com/firefly-iii/firefly-iii/issues/2135) Date fixes in transaction overview
|
||||
|
||||
# 4.7.14 (API 0.9.2)
|
||||
- 4.7.14 was released to fix an issue with the Composer installation script.
|
||||
|
||||
# 4.7.13 (API 0.9.2)
|
||||
- 4.7.13 was released to fix an issue that affected the Softaculous build.
|
||||
- A routine has been added that warns about transactions with a 0.00 amount.
|
||||
- PHP maximum execution time is now 600 seconds in the Docker image.
|
||||
- Moved several files outside of the root of Firefly III
|
||||
- Fix issue where missing preference breaks the database upgrade.
|
||||
- [Issue 2100](https://github.com/firefly-iii/firefly-iii/issues/2100) Mass edit transactions results in a reset of the date.
|
||||
|
||||
# 4.7.12
|
||||
- 4.7.12 was released to fix several shortcomings in v4.7.11's Docker image. Those in turn were caused by me. My apologies.
|
||||
- [Issue 2085](https://github.com/firefly-iii/firefly-iii/issues/2085) Upgraded the LDAP code. To keep using LDAP, set the `LOGIN_PROVIDER` to `ldap`.
|
||||
- [Issue 2061](https://github.com/firefly-iii/firefly-iii/issues/2061) Some users reported empty update popups.
|
||||
- [Issue 2070](https://github.com/firefly-iii/firefly-iii/issues/2070) A cache issue prevented rules from being applied correctly.
|
||||
- [Issue 2071](https://github.com/firefly-iii/firefly-iii/issues/2071) Several issues with Postgres and date values with time zone information in them.
|
||||
- [Issue 2081](https://github.com/firefly-iii/firefly-iii/issues/2081) Rules were not being applied when importing using FinTS.
|
||||
- [Issue 2082](https://github.com/firefly-iii/firefly-iii/issues/2082) The mass-editor changed all dates to today.
|
||||
|
||||
# 4.7.11
|
||||
- Experimental audit logging channel to track important events (separate from debug logging).
|
||||
- [Issue 2003](https://github.com/firefly-iii/firefly-iii/issues/2003), [issue 2006](https://github.com/firefly-iii/firefly-iii/issues/2006) Transactions can be stored with a timestamp. The user-interface does not support this yet. But the API does.
|
||||
- Docker image tags a new manifest for arm and amd64.
|
||||
- [skuzzle](https://github.com/skuzzle) removed an annoying console.log statement.
|
||||
- [Issue 2048](https://github.com/firefly-iii/firefly-iii/issues/2048) Fix "Are you sure?" popup, thanks to @nescafe2002!
|
||||
- [Issue 2049](https://github.com/firefly-iii/firefly-iii/issues/2049) Empty preferences would crash Firefly III.
|
||||
- [Issue 2052](https://github.com/firefly-iii/firefly-iii/issues/2052) Rules could not auto-covert to liabilities.
|
||||
- Webbased upgrade routine will also decrypt the database.
|
||||
- Last use date for categories was off.
|
||||
- The `date`-field in any transaction object now returns a ISO 8601 timestamp instead of a date.
|
||||
|
||||
# 4.7.10
|
||||
- [Issue 2037](https://github.com/firefly-iii/firefly-iii/issues/2037) Added some new magic keywords to reports.
|
||||
- Added a new currency exchange rate service, [ratesapi.io](https://ratesapi.io/), that does not require expensive API keys. Built by [@BoGnY](https://github.com/BoGnY).
|
||||
- Added Chinese Traditional translations. Thanks!
|
||||
- [Issue 1977](https://github.com/firefly-iii/firefly-iii/issues/1977) Docker image now includes memcached support
|
||||
- [Issue 2031](https://github.com/firefly-iii/firefly-iii/issues/2031) A new generic debit/credit indicator for imports.
|
||||
- The new Docker image no longer has the capability to run cron jobs, and will no longer generate your recurring transactions for you. This has been done to simplify the build and make sure your Docker container runs one service, as it should. To set up a cron job for your new Docker container, [check out the documentation](https://docs.firefly-iii.org/en/latest/installation/cronjob.html).
|
||||
- Due to a change in the database structure, this upgrade will reset your preferences. Sorry about that.
|
||||
- I will no longer accept PR's that introduce new currencies.
|
||||
- Firefly III no longer encrypts the database and will [decrypt the database]() on its first run.
|
||||
- [Issue 1923](https://github.com/firefly-iii/firefly-iii/issues/1923) Broken window position for date picker.
|
||||
- [Issue 1967](https://github.com/firefly-iii/firefly-iii/issues/1967) Attachments were hidden in bill view.
|
||||
- [Issue 1927](https://github.com/firefly-iii/firefly-iii/issues/1927) It was impossible to make recurring transactions skip.
|
||||
- [Issue 1929](https://github.com/firefly-iii/firefly-iii/issues/1929) Fix the recurring transactions calendar overview.
|
||||
- [Issue 1933](https://github.com/firefly-iii/firefly-iii/issues/1933) Fixed a bug that made it impossible to authenticate to FreeIPA servers.
|
||||
- [Issue 1938](https://github.com/firefly-iii/firefly-iii/issues/1938) The importer can now handle the insane way Postbank (DE) formats its numbers.
|
||||
- [Issue 1942](https://github.com/firefly-iii/firefly-iii/issues/1942) Favicons are relative so Scriptaculous installations work better.
|
||||
- [Issue 1944](https://github.com/firefly-iii/firefly-iii/issues/1944) Make sure that the search allows you to mass-select transactions.
|
||||
- [Issue 1945](https://github.com/firefly-iii/firefly-iii/issues/1945) Slight UI change so the drop-down menu renders better.
|
||||
- [Issue 1955](https://github.com/firefly-iii/firefly-iii/issues/1955) Fixed a bug in the category report.
|
||||
- [Issue 1968](https://github.com/firefly-iii/firefly-iii/issues/1968) The yearly range would jump to 1-Jan / 1-Jan instead of 1-Jan / 31-Dec
|
||||
- [Issue 1975](https://github.com/firefly-iii/firefly-iii/issues/1975) Fixed explanation for missing credit card liabilities.
|
||||
- [Issue 1979](https://github.com/firefly-iii/firefly-iii/issues/1979) Make sure tags are trimmed.
|
||||
- [Issue 1983](https://github.com/firefly-iii/firefly-iii/issues/1983) Could not use your favorite decimal separator.
|
||||
- [Issue 1989](https://github.com/firefly-iii/firefly-iii/issues/1989) Bug in YNAB importer forced you to select all accounts.
|
||||
- [Issue 1990](https://github.com/firefly-iii/firefly-iii/issues/1990) Rule description was invisible in edit screen.
|
||||
- [Issue 1996](https://github.com/firefly-iii/firefly-iii/issues/1996) Deleted budget would inadvertently also hide transactions.
|
||||
- [Issue 2001](https://github.com/firefly-iii/firefly-iii/issues/2001) Various issues with tag chart view.
|
||||
- [Issue 2009](https://github.com/firefly-iii/firefly-iii/issues/2009) Could not change recurrence back to "forever".
|
||||
- [Issue 2033](https://github.com/firefly-iii/firefly-iii/issues/2033) Longitude can go from -180 to 180.
|
||||
- [Issue 2034](https://github.com/firefly-iii/firefly-iii/issues/2034) Rules were not being triggered in mass-edit.
|
||||
- [Issue 2043](https://github.com/firefly-iii/firefly-iii/issues/2043) In rare instances the repetition of a recurring transaction was displayed incorrectly.
|
||||
- Fixed broken translations in the recurring transactions overview.
|
||||
- When you create a recurring transfer you make make it fill (or empty) a piggy bank. This was not working, despite a fix in 4.7.8.
|
||||
- Fixed a bug where the importer would not be capable of creating new currencies.
|
||||
- Rule trigger tester would skip the amount.
|
||||
- OAuth2 form can now submit back to original requester.
|
||||
- Submitting transactions with a disabled currency will auto-enable the currency.
|
||||
- The documentation now states that "Deposit" is a possible return when you get a transaction.
|
||||
- "savingAsset" was incorrectly documented as "savingsAsset".
|
||||
- Account endpoint can now return type "reconciliation" and "initial-balance" correctly.
|
||||
- New API endpoint under `/summary/basic` that gives you a basic overview of the user's finances.
|
||||
- New API endpoints under `/chart/*` to allow you to render charts.
|
||||
- `/accounts/x/transactions` now supports the limit query parameter.
|
||||
- `/budgets/x/transactions` now supports the limit query parameter.
|
||||
- `/available_budgets` now supports custom start and end date parameters.
|
||||
- New endpoint `/preferences/prefName` to retrieve a single preference.
|
||||
- Added field `account_name` to all piggy banks.
|
||||
- New tag cloud in API.
|
||||
|
||||
# 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
|
||||
@@ -40,11 +434,12 @@
|
||||
- [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 expenses a budget.
|
||||
- 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.
|
||||
|
||||
@@ -11,7 +11,7 @@ mkdir -p /var/log
|
||||
mkdir -p /var/log/mysql
|
||||
mkdir -p /var/log/nginx
|
||||
# Wipe /var/run, since pidfiles and socket files from previous launches should go away
|
||||
# TODO someday: I'd prefer a tmpfs for these.
|
||||
# Someday: I'd prefer a tmpfs for these.
|
||||
rm -rf /var/run
|
||||
mkdir -p /var/run
|
||||
rm -rf /var/tmp
|
||||
@@ -25,9 +25,9 @@ mkdir -p /var/storage/build
|
||||
mkdir -p /var/storage/database
|
||||
mkdir -p /var/storage/debugbar
|
||||
mkdir -p /var/storage/export
|
||||
mkdir -p /var/storage/framework/cache
|
||||
mkdir -p /var/storage/framework/cache/v1
|
||||
mkdir -p /var/storage/framework/sessions
|
||||
mkdir -p /var/storage/framework/views
|
||||
mkdir -p /var/storage/framework/views/v1
|
||||
mkdir -p /var/storage/logs
|
||||
mkdir -p /var/storage/upload
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -58,9 +58,5 @@ echo "Migrating..."
|
||||
php /opt/app/artisan migrate --seed --force
|
||||
echo "Done!"
|
||||
|
||||
echo "Clear cache.."
|
||||
php /opt/app/artisan cache:clear
|
||||
echo "Done"
|
||||
|
||||
# Start nginx.
|
||||
/usr/sbin/nginx -c /opt/app/.sandstorm/service-config/nginx.conf -g "daemon off;"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,8 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
|
||||
manifest = (
|
||||
appTitle = (defaultText = "Firefly III"),
|
||||
appVersion = 16,
|
||||
appMarketingVersion = (defaultText = "4.7.6.1"),
|
||||
appVersion = 36,
|
||||
appMarketingVersion = (defaultText = "4.8.1"),
|
||||
|
||||
actions = [
|
||||
# Define your "new document" handlers here.
|
||||
@@ -103,7 +103,7 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
# not have been detected as a dependency during `spk dev`. If you list
|
||||
# a directory here, its entire contents will be included recursively.
|
||||
|
||||
#bridgeConfig = (
|
||||
bridgeConfig = (
|
||||
# # Used for integrating permissions and roles into the Sandstorm shell
|
||||
# # and for sandstorm-http-bridge to pass to your app.
|
||||
# # Uncomment this block and adjust the permissions and roles to make
|
||||
@@ -165,12 +165,12 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
# ),
|
||||
# ],
|
||||
# ),
|
||||
# #apiPath = "/api",
|
||||
apiPath = "/api/v1/",
|
||||
# # Apps can export an API to the world. The API is to be used primarily by Javascript
|
||||
# # code and native apps, so it can't serve out regular HTML to browsers. If a request
|
||||
# # comes in to your app's API, sandstorm-http-bridge will prefix the request's path with
|
||||
# # this string, if specified.
|
||||
#),
|
||||
),
|
||||
);
|
||||
|
||||
const myCommand :Spk.Manifest.Command = (
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -13,6 +13,8 @@ apt-get update
|
||||
apt-get install -y python-software-properties software-properties-common
|
||||
|
||||
# install all languages
|
||||
#en_US
|
||||
sed -i 's/# es_ES.UTF-8 UTF-8/es_ES.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# it_IT.UTF-8 UTF-8/it_IT.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
@@ -20,13 +22,17 @@ sed -i 's/# nl_NL.UTF-8 UTF-8/nl_NL.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# pl_PL.UTF-8 UTF-8/pl_PL.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# pt_BR.UTF-8 UTF-8/pt_BR.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# ru_RU.UTF-8 UTF-8/ru_RU.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# tr_TR.UTF-8 UTF-8/tr_TR.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# zh_TW.UTF-8 UTF-8/zh_TW.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# nb_NO.UTF-8 UTF-8/nb_NO.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# ro_RO.UTF-8 UTF-8/ro_RO.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# cs_CZ.UTF-8 UTF-8/cs_CZ.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# id_ID.UTF-8 UTF-8/id_ID.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# hu_HU.UTF-8 UTF-8/hu_HU.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# el_GR.UTF-8 UTF-8/el_GR.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
|
||||
dpkg-reconfigure --frontend=noninteractive locales
|
||||
|
||||
|
||||
|
||||
|
||||
# actually add repository
|
||||
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E9C74FEEA2098A6E
|
||||
add-apt-repository "deb http://packages.dotdeb.org jessie all"
|
||||
@@ -38,37 +44,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 php7.2-ldap 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='' \
|
||||
|
||||
44
.travis.yml
44
.travis.yml
@@ -1,29 +1,29 @@
|
||||
language: php
|
||||
php:
|
||||
- 7.1.18
|
||||
sudo: required
|
||||
language: bash
|
||||
env:
|
||||
- VERSION=4.8.1
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- vendor
|
||||
- $HOME/.composer/cache
|
||||
|
||||
install:
|
||||
- rm composer.lock
|
||||
- composer update --no-scripts
|
||||
- cp .env.testing .env
|
||||
- php artisan clear-compiled
|
||||
- php artisan env
|
||||
- wget -q https://github.com/firefly-iii/test-data/raw/master/storage/database.sqlite -O storage/database/database.sqlite
|
||||
- mkdir -p build/logs
|
||||
|
||||
script:
|
||||
- ./vendor/bin/phpunit -c phpunit.coverage.xml
|
||||
|
||||
after_success:
|
||||
- travis_retry php vendor/bin/php-coveralls -x storage/build/clover-all.xml
|
||||
dist: xenial
|
||||
|
||||
# safelist
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
- master
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
script:
|
||||
# enable experimental features.
|
||||
- echo '{"experimental":true}' | sudo tee /etc/docker/daemon.json
|
||||
- mkdir $HOME/.docker
|
||||
- touch $HOME/.docker/config.json
|
||||
- echo '{"experimental":"enabled"}' | sudo tee $HOME/.docker/config.json
|
||||
- sudo service docker restart
|
||||
- docker version -f '{{.Server.Experimental}}'
|
||||
- docker version
|
||||
# build everything
|
||||
- .deploy/docker/build-amd64.sh
|
||||
- .deploy/docker/build-arm.sh
|
||||
- .deploy/docker/manifest.sh
|
||||
|
||||
111
Dockerfile
111
Dockerfile
@@ -1,113 +1,18 @@
|
||||
FROM php:7.1-apache
|
||||
|
||||
# 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/
|
||||
ENV CURL_VERSION 7.60.0
|
||||
ENV OPENSSL_VERSION 1.1.1-pre6
|
||||
|
||||
LABEL version="1.0" maintainer="thegrumpydictator@gmail.com"
|
||||
|
||||
|
||||
# install packages
|
||||
RUN apt-get update -y && \
|
||||
apt-get install -y --no-install-recommends libcurl4-openssl-dev \
|
||||
zlib1g-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
wget \
|
||||
libpng-dev \
|
||||
libicu-dev \
|
||||
libedit-dev \
|
||||
libtidy-dev \
|
||||
libxml2-dev \
|
||||
unzip \
|
||||
libsqlite3-dev \
|
||||
nano \
|
||||
libpq-dev \
|
||||
libbz2-dev \
|
||||
gettext-base \
|
||||
cron \
|
||||
rsyslog \
|
||||
supervisor \
|
||||
locales && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 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 -j${CORES} && \
|
||||
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 --host=$(gcc -dumpmachine) && \
|
||||
make -j${CORES} && \
|
||||
make install
|
||||
|
||||
# Make sure that libcurl is using the newer curl libaries
|
||||
RUN echo "/usr/local/lib" >> /etc/ld.so.conf.d/00-curl.conf && ldconfig
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
# copy Firefly III supervisor conf file.
|
||||
COPY ./.deploy/docker/firefly-iii.conf /etc/supervisor/conf.d/firefly-iii.conf
|
||||
|
||||
# copy cron job supervisor conf file.
|
||||
COPY ./.deploy/docker/cronjob.conf /etc/supervisor/conf.d/cronjob.conf
|
||||
|
||||
# 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.
|
||||
RUN docker-php-ext-install -j$(nproc) gd intl tidy zip bcmath pdo_mysql bz2 pdo_pgsql
|
||||
|
||||
# Install composer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# 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 Apache config to correct spot.
|
||||
COPY ./.deploy/docker/apache2.conf /etc/apache2/apache2.conf
|
||||
|
||||
# Enable apache mod rewrite..
|
||||
RUN a2enmod rewrite
|
||||
|
||||
# Enable apache mod ssl..
|
||||
RUN a2enmod ssl
|
||||
FROM jc5x/firefly-iii-base-image:latest
|
||||
ENV FIREFLY_PATH=/var/www/firefly-iii COMPOSER_ALLOW_SUPERUSER=1
|
||||
LABEL version="1.5" maintainer="thegrumpydictator@gmail.com"
|
||||
|
||||
# Create volumes
|
||||
VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload
|
||||
|
||||
# Enable default site (Firefly III)
|
||||
COPY ./.deploy/docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf
|
||||
|
||||
# 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
|
||||
# Copy in Firefly III source
|
||||
WORKDIR $FIREFLY_PATH
|
||||
ADD . $FIREFLY_PATH
|
||||
|
||||
# Run composer
|
||||
ENV COMPOSER_ALLOW_SUPERUSER 1
|
||||
RUN composer install --prefer-dist --no-dev --no-scripts --no-suggest
|
||||
# Ensure correct app directory permission, then `composer install`
|
||||
RUN chown -R www-data:www-data /var/www && \
|
||||
chmod -R 775 $FIREFLY_PATH/storage && \
|
||||
composer install --prefer-dist --no-dev --no-scripts --no-suggest
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
21
Dockerfile.amd64
Normal file
21
Dockerfile.amd64
Normal file
@@ -0,0 +1,21 @@
|
||||
FROM jc5x/firefly-iii-base-image:latest
|
||||
ENV FIREFLY_PATH=/var/www/firefly-iii COMPOSER_ALLOW_SUPERUSER=1
|
||||
LABEL version="1.5" maintainer="thegrumpydictator@gmail.com"
|
||||
|
||||
# Create volumes
|
||||
VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload
|
||||
|
||||
# Copy in Firefly III source
|
||||
WORKDIR $FIREFLY_PATH
|
||||
ADD . $FIREFLY_PATH
|
||||
|
||||
# Ensure correct app directory permission, then `composer install`
|
||||
RUN chown -R www-data:www-data /var/www && \
|
||||
chmod -R 775 $FIREFLY_PATH/storage && \
|
||||
composer install --prefer-dist --no-dev --no-scripts --no-suggest
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
# Run entrypoint thing
|
||||
ENTRYPOINT [".deploy/docker/entrypoint.sh"]
|
||||
21
Dockerfile.arm
Normal file
21
Dockerfile.arm
Normal file
@@ -0,0 +1,21 @@
|
||||
FROM jc5x/firefly-iii-base-image:latest-arm
|
||||
ENV FIREFLY_PATH=/var/www/firefly-iii COMPOSER_ALLOW_SUPERUSER=1
|
||||
LABEL version="1.5" maintainer="thegrumpydictator@gmail.com"
|
||||
|
||||
# Create volumes
|
||||
VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload
|
||||
|
||||
# Copy in Firefly III source
|
||||
WORKDIR $FIREFLY_PATH
|
||||
ADD . $FIREFLY_PATH
|
||||
|
||||
# Ensure correct app directory permission, then `composer install`
|
||||
RUN chown -R www-data:www-data /var/www && \
|
||||
chmod -R 775 $FIREFLY_PATH/storage && \
|
||||
composer install --prefer-dist --no-dev --no-scripts --no-suggest
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
# Run entrypoint thing
|
||||
ENTRYPOINT [".deploy/docker/entrypoint.sh"]
|
||||
45
Dockerfile.arm64
Normal file
45
Dockerfile.arm64
Normal file
@@ -0,0 +1,45 @@
|
||||
FROM arm32v7/php:7.2-apache-stretch
|
||||
ARG ARCH
|
||||
COPY tmp/qemu-arm-static /usr/bin/qemu-arm-static
|
||||
ENV FIREFLY_PATH=/var/www/firefly-iii COMPOSER_ALLOW_SUPERUSER=1
|
||||
LABEL version="1.5" maintainer="thegrumpydictator@gmail.com"
|
||||
|
||||
# Create volumes
|
||||
VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload
|
||||
|
||||
# Install stuff Firefly III runs with & depends on: php extensions, locales, dev headers and composer
|
||||
RUN apt-get update && apt-get install -y locales unzip && apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ADD https://raw.githubusercontent.com/mlocati/docker-php-extension-installer/master/install-php-extensions /usr/local/bin/
|
||||
|
||||
RUN chmod uga+x /usr/local/bin/install-php-extensions && sync && \
|
||||
install-php-extensions --cleanup bcmath ldap gd pdo_pgsql pdo_sqlite pdo_mysql intl opcache memcached
|
||||
|
||||
RUN a2enmod rewrite && a2enmod ssl
|
||||
RUN echo "hu_HU.UTF-8 UTF-8\nro_RO.UTF-8 UTF-8\nnb_NO.UTF-8 UTF-8\nde_DE.UTF-8 UTF-8\ncs_CZ.UTF-8 UTF-8\nen_US.UTF-8 UTF-8\nes_ES.UTF-8 UTF-8\nfr_FR.UTF-8 UTF-8\nid_ID.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\nzh_TW.UTF-8 UTF-8\nzh_CN.UTF-8 UTF-8\n\n" > /etc/locale.gen
|
||||
RUN locale-gen
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Copy in Firefly III source
|
||||
WORKDIR $FIREFLY_PATH
|
||||
ADD . $FIREFLY_PATH
|
||||
|
||||
# Ensure correct app directory permission, then `composer install`
|
||||
RUN chown -R www-data:www-data /var/www && \
|
||||
chmod -R 775 $FIREFLY_PATH/storage && \
|
||||
composer install --prefer-dist --no-dev --no-scripts --no-suggest
|
||||
|
||||
# copy ca certs to correct location
|
||||
COPY ./.deploy/docker/cacert.pem /usr/local/ssl/cert.pem
|
||||
|
||||
# copy Apache config to correct spot.
|
||||
COPY ./.deploy/docker/apache2.conf /etc/apache2/apache2.conf
|
||||
|
||||
# Enable default site (Firefly III)
|
||||
COPY ./.deploy/docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
# 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": {
|
||||
|
||||
@@ -27,14 +27,12 @@ namespace FireflyIII\Api\V1\Controllers;
|
||||
use DB;
|
||||
use FireflyIII\Transformers\UserTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Returns basic information about this installation.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* Class AboutController.
|
||||
*/
|
||||
class AboutController extends Controller
|
||||
@@ -51,8 +49,10 @@ class AboutController extends Controller
|
||||
$phpVersion = str_replace($search, $replace, PHP_VERSION);
|
||||
$phpOs = str_replace($search, $replace, PHP_OS);
|
||||
$currentDriver = DB::getDriverName();
|
||||
|
||||
|
||||
$data
|
||||
= [
|
||||
= [
|
||||
'version' => config('firefly.version'),
|
||||
'api_version' => config('firefly.api_version'),
|
||||
'php_version' => $phpVersion,
|
||||
@@ -60,22 +60,23 @@ class AboutController extends Controller
|
||||
'driver' => $currentDriver,
|
||||
];
|
||||
|
||||
return response()->json(['data' => $data], 200)->header('Content-Type', 'application/vnd.api+json');
|
||||
return response()->json(['data' => $data])->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the user.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function user(Request $request): JsonResponse
|
||||
public function user(): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item(auth()->user(), new UserTransformer($this->parameters), 'users');
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @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');
|
||||
}
|
||||
|
||||
@@ -23,36 +23,39 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\AccountRequest;
|
||||
use FireflyIII\Api\V1\Requests\AccountStoreRequest;
|
||||
use FireflyIII\Api\V1\Requests\AccountUpdateRequest;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
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\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class AccountController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class AccountController extends Controller
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface The currency repository */
|
||||
private $currencyRepository;
|
||||
use AccountFilter, TransactionFilter;
|
||||
/** @var AccountRepositoryInterface The account repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -65,9 +68,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);
|
||||
}
|
||||
);
|
||||
@@ -76,8 +76,9 @@ class AccountController extends Controller
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \FireflyIII\Models\Account $account
|
||||
* @param Account $account
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function delete(Account $account): JsonResponse
|
||||
@@ -92,20 +93,17 @@ class AccountController extends Controller
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// read type from URI
|
||||
$type = $request->get('type') ?? 'all';
|
||||
$manager = $this->getManager();
|
||||
$type = $request->get('type') ?? 'all';
|
||||
$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.
|
||||
@@ -117,33 +115,70 @@ class AccountController extends Controller
|
||||
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.accounts.index') . $this->buildParams());
|
||||
|
||||
// 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 piggies.
|
||||
*
|
||||
* @param Account $account
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
*/
|
||||
public function piggyBanks(Account $account): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = $this->getManager();
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of 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());
|
||||
|
||||
/** @var PiggyBankTransformer $transformer */
|
||||
$transformer = app(PiggyBankTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy_banks');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show single instance.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(Request $request, Account $account): JsonResponse
|
||||
public function show(Account $account): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$manager = $this->getManager();
|
||||
|
||||
// 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');
|
||||
}
|
||||
@@ -151,24 +186,75 @@ class AccountController extends Controller
|
||||
/**
|
||||
* Store a new instance.
|
||||
*
|
||||
* @param AccountRequest $request
|
||||
* @param AccountStoreRequest $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(AccountRequest $request): JsonResponse
|
||||
public function store(AccountStoreRequest $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->getAllAccountData();
|
||||
$account = $this->repository->store($data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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 transaction groups related to the account.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @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);
|
||||
|
||||
// user can overrule page size with limit parameter.
|
||||
$limit = $this->parameters->get('limit');
|
||||
if (null !== $limit && $limit > 0) {
|
||||
$pageSize = $limit;
|
||||
}
|
||||
|
||||
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setUser($admin)->setAccounts(new Collection([$account]))
|
||||
->withAPIInformation()->setLimit($pageSize)->setPage($this->parameters->get('page'))->setTypes($types);
|
||||
|
||||
// set range if necessary:
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.accounts.transactions', [$account->id]) . $this->buildParams());
|
||||
$groups = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($groups, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -176,76 +262,23 @@ class AccountController extends Controller
|
||||
/**
|
||||
* Update account.
|
||||
*
|
||||
* @param AccountRequest $request
|
||||
* @param Account $account
|
||||
* @param AccountUpdateRequest $request
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(AccountRequest $request, Account $account): JsonResponse
|
||||
public function update(AccountUpdateRequest $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->getUpdateData();
|
||||
$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));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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,],
|
||||
'liability' => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD],
|
||||
'liabilities' => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD],
|
||||
'cc' => [AccountType::CREDITCARD],
|
||||
'creditcard' => [AccountType::CREDITCARD],
|
||||
'credit_card' => [AccountType::CREDITCARD],
|
||||
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],
|
||||
AccountType::MORTGAGE => [AccountType::MORTGAGE],
|
||||
AccountType::DEBT => [AccountType::DEBT],
|
||||
AccountType::CREDITCARD => [AccountType::CREDITCARD],
|
||||
|
||||
];
|
||||
$return = $types['all'];
|
||||
if (isset($types[$type])) {
|
||||
$return = $types[$type];
|
||||
}
|
||||
|
||||
return $return; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\AttachmentRequest;
|
||||
use FireflyIII\Api\V1\Requests\AttachmentStoreRequest;
|
||||
use FireflyIII\Api\V1\Requests\AttachmentUpdateRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||
use FireflyIII\Models\Attachment;
|
||||
@@ -34,16 +35,14 @@ use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response as LaravelResponse;
|
||||
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;
|
||||
use function strlen;
|
||||
|
||||
/**
|
||||
* Class AttachmentController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class AttachmentController extends Controller
|
||||
{
|
||||
@@ -52,6 +51,8 @@ class AttachmentController extends Controller
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -71,6 +72,8 @@ class AttachmentController extends Controller
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return JsonResponse
|
||||
@@ -87,8 +90,9 @@ class AttachmentController extends Controller
|
||||
*
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @return LaravelResponse
|
||||
* @throws FireflyException
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function download(Attachment $attachment): LaravelResponse
|
||||
{
|
||||
@@ -100,7 +104,7 @@ class AttachmentController extends Controller
|
||||
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
|
||||
|
||||
/** @var LaravelResponse $response */
|
||||
$response = response($content, 200);
|
||||
$response = response($content);
|
||||
$response
|
||||
->header('Content-Description', 'File Transfer')
|
||||
->header('Content-Type', 'application/octet-stream')
|
||||
@@ -110,7 +114,7 @@ class AttachmentController extends Controller
|
||||
->header('Expires', '0')
|
||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||
->header('Pragma', 'public')
|
||||
->header('Content-Length', \strlen($content));
|
||||
->header('Content-Length', strlen($content));
|
||||
|
||||
return $response;
|
||||
}
|
||||
@@ -120,15 +124,12 @@ class AttachmentController extends Controller
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager = $this->getManager();
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
@@ -142,9 +143,11 @@ class AttachmentController extends Controller
|
||||
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.attachments.index') . $this->buildParams());
|
||||
|
||||
// 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');
|
||||
@@ -153,22 +156,18 @@ class AttachmentController extends Controller
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(Request $request, Attachment $attachment): JsonResponse
|
||||
public function show(Attachment $attachment): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$manager = $this->getManager();
|
||||
/** @var AttachmentTransformer $transformer */
|
||||
$transformer = app(AttachmentTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
// 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');
|
||||
$resource = new Item($attachment, $transformer, 'attachments');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -176,19 +175,22 @@ class AttachmentController extends Controller
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param AttachmentRequest $request
|
||||
* @param AttachmentStoreRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function store(AttachmentRequest $request): JsonResponse
|
||||
public function store(AttachmentStoreRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$attachment = $this->repository->store($data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($attachment, new AttachmentTransformer($this->parameters), 'attachments');
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @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');
|
||||
}
|
||||
@@ -196,20 +198,22 @@ class AttachmentController extends Controller
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param AttachmentRequest $request
|
||||
* @param Attachment $attachment
|
||||
* @param AttachmentUpdateRequest $request
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(AttachmentRequest $request, Attachment $attachment): JsonResponse
|
||||
public function update(AttachmentUpdateRequest $request, Attachment $attachment): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$this->repository->update($attachment, $data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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');
|
||||
}
|
||||
@@ -217,6 +221,8 @@ class AttachmentController extends Controller
|
||||
/**
|
||||
* Upload an attachment.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
|
||||
@@ -24,35 +24,31 @@ declare(strict_types=1);
|
||||
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\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
|
||||
use FireflyIII\Transformers\AvailableBudgetTransformer;
|
||||
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 AvailableBudgetController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class AvailableBudgetController extends Controller
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface The currency repository */
|
||||
private $currencyRepository;
|
||||
/** @var BudgetRepositoryInterface The budget repository */
|
||||
private $repository;
|
||||
/** @var AvailableBudgetRepositoryInterface */
|
||||
private $abRepository;
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
* AvailableBudgetController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -60,10 +56,9 @@ class AvailableBudgetController extends Controller
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
$user = auth()->user();
|
||||
$this->abRepository = app(AvailableBudgetRepositoryInterface::class);
|
||||
$this->abRepository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -75,11 +70,13 @@ class AvailableBudgetController extends Controller
|
||||
*
|
||||
* @param AvailableBudget $availableBudget
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function delete(AvailableBudget $availableBudget): JsonResponse
|
||||
{
|
||||
$this->repository->destroyAvailableBudget($availableBudget);
|
||||
$this->abRepository->destroyAvailableBudget($availableBudget);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
@@ -87,21 +84,21 @@ class AvailableBudgetController extends Controller
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager = $this->getManager();
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
$start = $this->parameters->get('start');
|
||||
$end = $this->parameters->get('end');
|
||||
|
||||
// get list of available budgets. Count it and split it.
|
||||
$collection = $this->repository->getAvailableBudgets();
|
||||
$collection = $this->abRepository->getAvailableBudgetsByDate($start, $end);
|
||||
$count = $collection->count();
|
||||
$availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
@@ -109,9 +106,11 @@ class AvailableBudgetController extends Controller
|
||||
$paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.available_budgets.index') . $this->buildParams());
|
||||
|
||||
// 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');
|
||||
@@ -120,23 +119,20 @@ class AvailableBudgetController extends Controller
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param AvailableBudget $availableBudget
|
||||
* @param AvailableBudget $availableBudget
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, AvailableBudget $availableBudget): JsonResponse
|
||||
public function show(AvailableBudget $availableBudget): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
|
||||
$manager = new Manager;
|
||||
/** @var AvailableBudgetTransformer $transformer */
|
||||
$transformer = app(AvailableBudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
// 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');
|
||||
$resource = new Item($availableBudget, $transformer, 'available_budgets');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -147,30 +143,31 @@ class AvailableBudgetController extends Controller
|
||||
* @param AvailableBudgetRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function store(AvailableBudgetRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$currency = $this->currencyRepository->findNull($data['currency_id']);
|
||||
if (null === $currency) {
|
||||
$currency = $this->currencyRepository->findByCodeNull($data['currency_code']);
|
||||
}
|
||||
if (null === $currency) {
|
||||
throw new FireflyException('Could not find the indicated currency.');
|
||||
}
|
||||
$availableBudget = $this->repository->setAvailableBudget($currency, $data['start_date'], $data['end_date'], $data['amount']);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$data = $request->getAll();
|
||||
/** @var TransactionCurrencyFactory $factory */
|
||||
$factory = app(TransactionCurrencyFactory::class);
|
||||
$currency = $factory->find($data['currency_id'], $data['currency_code']);
|
||||
|
||||
$resource = new Item($availableBudget, new AvailableBudgetTransformer($this->parameters), 'available_budgets');
|
||||
if (null === $currency) {
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
}
|
||||
$data['currency'] = $currency;
|
||||
$availableBudget = $this->abRepository->store($data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @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.
|
||||
*
|
||||
@@ -182,12 +179,30 @@ class AvailableBudgetController extends Controller
|
||||
public function update(AvailableBudgetRequest $request, AvailableBudget $availableBudget): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$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 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->abRepository->updateAvailableBudget($availableBudget, $data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @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,29 +26,36 @@ namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\BillRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
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\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class BillController.
|
||||
*
|
||||
*/
|
||||
class BillController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var BillRepositoryInterface The bill repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* BillController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -68,11 +75,43 @@ class BillController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Bill $bill
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function attachments(Bill $bill): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
$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());
|
||||
|
||||
/** @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.
|
||||
*
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(Bill $bill): JsonResponse
|
||||
{
|
||||
@@ -84,47 +123,80 @@ class BillController extends Controller
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
$bills = $this->repository->getBills();
|
||||
$manager = $this->getManager();
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$paginator = $this->repository->getPaginator($pageSize);
|
||||
/** @var Collection $bills */
|
||||
$bills = $paginator->getCollection();
|
||||
$count = $bills->count();
|
||||
$bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
|
||||
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($bills, new BillTransformer($this->parameters), 'bills');
|
||||
$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 Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function rules(Bill $bill): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
|
||||
// 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());
|
||||
|
||||
/** @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.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Bill $bill): JsonResponse
|
||||
public function show(Bill $bill): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
$manager = $this->getManager();
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($bill, new BillTransformer($this->parameters), 'bills');
|
||||
$resource = new Item($bill, $transformer, 'bills');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -141,11 +213,13 @@ class BillController extends Controller
|
||||
{
|
||||
$bill = $this->repository->store($request->getAll());
|
||||
if (null !== $bill) {
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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 +227,63 @@ class BillController extends Controller
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
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 = $this->getManager();
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// include source + destination account name and type.
|
||||
->setBill($bill)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
// set page size:
|
||||
->setLimit($pageSize)
|
||||
// set page to retrieve
|
||||
->setPage($this->parameters->get('page'))
|
||||
// set types of transactions to return.
|
||||
->setTypes($types);
|
||||
|
||||
// do parameter stuff on new group collector.
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
|
||||
// get paginator.
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.bills.transactions', [$bill->id]) . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a bill.
|
||||
@@ -166,11 +297,13 @@ class BillController extends Controller
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$bill = $this->repository->update($bill, $data);
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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,33 +23,42 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
|
||||
use FireflyIII\Api\V1\Requests\BudgetRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||
use FireflyIII\Transformers\BudgetTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
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 BudgetController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class BudgetController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var BudgetLimitRepositoryInterface */
|
||||
private $blRepository;
|
||||
/** @var BudgetRepositoryInterface The budget repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* BudgetController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -59,21 +68,53 @@ class BudgetController extends Controller
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var BudgetRepositoryInterface repository */
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->blRepository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function budgetLimits(Budget $budget): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$this->parameters->set('budget_id', $budget->id);
|
||||
$collection = $this->blRepository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end'));
|
||||
$count = $collection->count();
|
||||
$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());
|
||||
|
||||
/** @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.
|
||||
*
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(Budget $budget): JsonResponse
|
||||
{
|
||||
@@ -85,15 +126,12 @@ class BudgetController extends Controller
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager = $this->getManager();
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
@@ -107,34 +145,33 @@ class BudgetController extends Controller
|
||||
$paginator = new LengthAwarePaginator($budgets, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.budgets.index') . $this->buildParams());
|
||||
|
||||
// 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.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Budget $budget
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Budget $budget): JsonResponse
|
||||
public function show(Budget $budget): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
$manager = $this->getManager();
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
/** @var BudgetTransformer $transformer */
|
||||
$transformer = app(BudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($budget, new BudgetTransformer($this->parameters), 'budgets');
|
||||
$resource = new Item($budget, $transformer, 'budgets');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -146,22 +183,113 @@ class BudgetController extends Controller
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*
|
||||
*/
|
||||
public function store(BudgetRequest $request): JsonResponse
|
||||
{
|
||||
$budget = $this->repository->store($request->getAll());
|
||||
if (null !== $budget) {
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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
|
||||
* @throws Exception
|
||||
*/
|
||||
public function storeBudgetLimit(BudgetLimitRequest $request, Budget $budget): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$data['budget'] = $budget;
|
||||
$budgetLimit = $this->blRepository->storeBudgetLimit($data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @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
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function transactions(Request $request, Budget $budget): JsonResponse
|
||||
{
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// user can overrule page size with limit parameter.
|
||||
$limit = $this->parameters->get('limit');
|
||||
if (null !== $limit && $limit > 0) {
|
||||
$pageSize = $limit;
|
||||
}
|
||||
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$this->parameters->set('type', $type);
|
||||
|
||||
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// filter on budget.
|
||||
->setBudget($budget)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
// set page size:
|
||||
->setLimit($pageSize)
|
||||
// set page to retrieve
|
||||
->setPage($this->parameters->get('page'))
|
||||
// set types of transactions to return.
|
||||
->setTypes($types);
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.budgets.transactions', [$budget->id]) . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a budget.
|
||||
@@ -175,11 +303,13 @@ class BudgetController extends Controller
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$budget = $this->repository->update($budget, $data);
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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,33 +26,38 @@ namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
|
||||
/**
|
||||
* Class BudgetLimitController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class BudgetLimitController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var BudgetLimitRepositoryInterface */
|
||||
private $blRepository;
|
||||
/** @var BudgetRepositoryInterface The budget repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
* BudgetLimitController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -60,9 +65,11 @@ class BudgetLimitController extends Controller
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$user = auth()->user();
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
$this->blRepository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -75,10 +82,11 @@ class BudgetLimitController extends Controller
|
||||
* @param BudgetLimit $budgetLimit
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(BudgetLimit $budgetLimit): JsonResponse
|
||||
{
|
||||
$this->repository->destroyBudgetLimit($budgetLimit);
|
||||
$this->blRepository->destroyBudgetLimit($budgetLimit);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
@@ -89,11 +97,11 @@ class BudgetLimitController extends Controller
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager = $this->getManager();
|
||||
$budgetId = (int)($request->get('budget_id') ?? 0);
|
||||
$budget = $this->repository->findNull($budgetId);
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
@@ -101,10 +109,10 @@ class BudgetLimitController extends Controller
|
||||
|
||||
$collection = new Collection;
|
||||
if (null === $budget) {
|
||||
$collection = $this->repository->getAllBudgetLimits($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
$collection = $this->blRepository->getAllBudgetLimits($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
if (null !== $budget) {
|
||||
$collection = $this->repository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end'));
|
||||
$collection = $this->blRepository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
|
||||
$count = $collection->count();
|
||||
@@ -112,8 +120,11 @@ class BudgetLimitController extends Controller
|
||||
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
|
||||
$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');
|
||||
@@ -122,22 +133,20 @@ class BudgetLimitController extends Controller
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param BudgetLimit $budgetLimit
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, BudgetLimit $budgetLimit): JsonResponse
|
||||
public function show(BudgetLimit $budgetLimit): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$manager = $this->getManager();
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
/** @var BudgetLimitTransformer $transformer */
|
||||
$transformer = app(BudgetLimitTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($budgetLimit, new BudgetLimitTransformer($this->parameters), 'budget_limits');
|
||||
$resource = new Item($budgetLimit, $transformer, 'budget_limits');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -149,6 +158,7 @@ class BudgetLimitController extends Controller
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*
|
||||
*/
|
||||
public function store(BudgetLimitRequest $request): JsonResponse
|
||||
{
|
||||
@@ -158,12 +168,67 @@ class BudgetLimitController extends Controller
|
||||
throw new FireflyException('Unknown budget.');
|
||||
}
|
||||
$data['budget'] = $budget;
|
||||
$budgetLimit = $this->repository->storeBudgetLimit($data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$budgetLimit = $this->blRepository->storeBudgetLimit($data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
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 = $this->getManager();
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// filter on budget.
|
||||
->setBudget($budgetLimit->budget)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
// set page size:
|
||||
->setLimit($pageSize)
|
||||
// set page to retrieve
|
||||
->setPage($this->parameters->get('page'))
|
||||
// set types of transactions to return.
|
||||
->setTypes($types);
|
||||
|
||||
$collector->setRange($budgetLimit->start_date, $budgetLimit->end_date);
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.budget_limits.transactions', [$budgetLimit->id]) . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -178,18 +243,16 @@ 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;
|
||||
$budgetLimit = $this->repository->updateBudgetLimit($budgetLimit, $data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$data = $request->getAll();
|
||||
$data['budget'] = $budgetLimit->budget;
|
||||
$budgetLimit = $this->blRepository->updateBudgetLimit($budgetLimit, $data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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,31 +25,34 @@ namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\CategoryRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\CategoryTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
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 CategoryController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var CategoryRepositoryInterface The category repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* CategoryController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -74,6 +77,7 @@ class CategoryController extends Controller
|
||||
* @param Category $category
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(Category $category): JsonResponse
|
||||
{
|
||||
@@ -85,15 +89,12 @@ class CategoryController extends Controller
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager = $this->getManager();
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
@@ -107,9 +108,12 @@ class CategoryController extends Controller
|
||||
$paginator = new LengthAwarePaginator($categories, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.categories.index') . $this->buildParams());
|
||||
|
||||
// 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');
|
||||
@@ -119,22 +123,20 @@ class CategoryController extends Controller
|
||||
/**
|
||||
* Show the category.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Category $category
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Category $category): JsonResponse
|
||||
public function show(Category $category): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
$manager = $this->getManager();
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
/** @var CategoryTransformer $transformer */
|
||||
$transformer = app(CategoryTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($category, new CategoryTransformer($this->parameters), 'categories');
|
||||
$resource = new Item($category, $transformer, 'categories');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -151,17 +153,74 @@ class CategoryController extends Controller
|
||||
{
|
||||
$category = $this->repository->store($request->getAll());
|
||||
if (null !== $category) {
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
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 = $this->getManager();
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// filter on category.
|
||||
->setCategory($category)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
// set page size:
|
||||
->setLimit($pageSize)
|
||||
// set page to retrieve
|
||||
->setPage($this->parameters->get('page'))
|
||||
// set types of transactions to return.
|
||||
->setTypes($types);
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.categories.transactions', [$category->id]) . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the category.
|
||||
@@ -175,11 +234,13 @@ class CategoryController extends Controller
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$category = $this->repository->update($category, $data);
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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');
|
||||
|
||||
|
||||
307
app/Api/V1/Controllers/Chart/AccountController.php
Normal file
307
app/Api/V1/Controllers/Chart/AccountController.php
Normal file
@@ -0,0 +1,307 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AccountController.php
|
||||
* Copyright (c) 2019 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\Chart;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\DateRequest;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ApiSupport;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
* Class AccountController
|
||||
*/
|
||||
class AccountController extends Controller
|
||||
{
|
||||
use ApiSupport;
|
||||
/** @var CurrencyRepositoryInterface */
|
||||
private $currencyRepository;
|
||||
/** @var AccountRepositoryInterface */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$this->repository = app(AccountRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
|
||||
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
||||
$this->currencyRepository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function expenseOverview(DateRequest $request): JsonResponse
|
||||
{
|
||||
// parameters for chart:
|
||||
$dates = $request->getAll();
|
||||
/** @var Carbon $start */
|
||||
$start = $dates['start'];
|
||||
/** @var Carbon $end */
|
||||
$end = $dates['end'];
|
||||
|
||||
$start->subDay();
|
||||
|
||||
// prep some vars:
|
||||
$currencies = [];
|
||||
$chartData = [];
|
||||
$tempData = [];
|
||||
|
||||
// grab all accounts and names
|
||||
$accounts = $this->repository->getAccountsByType([AccountType::EXPENSE]);
|
||||
$accountNames = $this->extractNames($accounts);
|
||||
$startBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $start);
|
||||
$endBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $end);
|
||||
|
||||
// loop the end balances. This is an array for each account ($expenses)
|
||||
foreach ($endBalances as $accountId => $expenses) {
|
||||
$accountId = (int)$accountId;
|
||||
// loop each expense entry (each entry can be a different currency).
|
||||
foreach ($expenses as $currencyId => $endAmount) {
|
||||
$currencyId = (int)$currencyId;
|
||||
|
||||
// see if there is an accompanying start amount.
|
||||
// grab the difference and find the currency.
|
||||
$startAmount = $startBalances[$accountId][$currencyId] ?? '0';
|
||||
$diff = bcsub($endAmount, $startAmount);
|
||||
$currencies[$currencyId] = $currencies[$currencyId] ?? $this->currencyRepository->findNull($currencyId);
|
||||
if (0 !== bccomp($diff, '0')) {
|
||||
// store the values in a temporary array.
|
||||
$tempData[] = [
|
||||
'name' => $accountNames[$accountId],
|
||||
'difference' => $diff,
|
||||
'diff_float' => (float)$diff,
|
||||
'currency_id' => $currencyId,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort temp array by amount.
|
||||
$amounts = array_column($tempData, 'diff_float');
|
||||
array_multisort($amounts, SORT_DESC, $tempData);
|
||||
|
||||
// loop all found currencies and build the data array for the chart.
|
||||
/**
|
||||
* @var int $currencyId
|
||||
* @var TransactionCurrency $currency
|
||||
*/
|
||||
foreach ($currencies as $currencyId => $currency) {
|
||||
$currentSet = [
|
||||
'label' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'type' => 'bar', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => $this->expandNames($tempData),
|
||||
];
|
||||
$chartData[$currencyId] = $currentSet;
|
||||
}
|
||||
|
||||
// loop temp data and place data in correct array:
|
||||
foreach ($tempData as $entry) {
|
||||
$currencyId = $entry['currency_id'];
|
||||
$name = $entry['name'];
|
||||
$chartData[$currencyId]['entries'][$name] = round($entry['difference'], $chartData[$currencyId]['currency_decimal_places']);
|
||||
}
|
||||
$chartData = array_values($chartData);
|
||||
|
||||
return response()->json($chartData);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function overview(DateRequest $request): JsonResponse
|
||||
{
|
||||
// parameters for chart:
|
||||
$dates = $request->getAll();
|
||||
/** @var Carbon $start */
|
||||
$start = $dates['start'];
|
||||
/** @var Carbon $end */
|
||||
$end = $dates['end'];
|
||||
|
||||
// user's preferences
|
||||
$defaultSet = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray();
|
||||
$frontPage = app('preferences')->get('frontPageAccounts', $defaultSet);
|
||||
$default = app('amount')->getDefaultCurrency();
|
||||
// @codeCoverageIgnoreStart
|
||||
if (0 === count($frontPage->data)) {
|
||||
$frontPage->data = $defaultSet;
|
||||
$frontPage->save();
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// get accounts:
|
||||
$accounts = $this->repository->getAccountsById($frontPage->data);
|
||||
$chartData = [];
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$currency = $this->repository->getAccountCurrency($account);
|
||||
if (null === $currency) {
|
||||
$currency = $default; // @codeCoverageIgnore
|
||||
}
|
||||
$currentSet = [
|
||||
'label' => $account->name,
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'type' => 'line', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [],
|
||||
];
|
||||
/** @var Carbon $currentStart */
|
||||
$currentStart = clone $start;
|
||||
$range = app('steam')->balanceInRange($account, $start, clone $end);
|
||||
$previous = round(array_values($range)[0], 12);
|
||||
while ($currentStart <= $end) {
|
||||
$format = $currentStart->format('Y-m-d');
|
||||
$label = $currentStart->format('Y-m-d');
|
||||
$balance = isset($range[$format]) ? round($range[$format], 12) : $previous;
|
||||
$previous = $balance;
|
||||
$currentStart->addDay();
|
||||
$currentSet['entries'][$label] = $balance;
|
||||
}
|
||||
$chartData[] = $currentSet;
|
||||
}
|
||||
|
||||
return response()->json($chartData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function revenueOverview(DateRequest $request): JsonResponse
|
||||
{
|
||||
// parameters for chart:
|
||||
$dates = $request->getAll();
|
||||
/** @var Carbon $start */
|
||||
$start = $dates['start'];
|
||||
/** @var Carbon $end */
|
||||
$end = $dates['end'];
|
||||
|
||||
$start->subDay();
|
||||
|
||||
// prep some vars:
|
||||
$currencies = [];
|
||||
$chartData = [];
|
||||
$tempData = [];
|
||||
|
||||
// grab all accounts and names
|
||||
$accounts = $this->repository->getAccountsByType([AccountType::REVENUE]);
|
||||
$accountNames = $this->extractNames($accounts);
|
||||
$startBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $start);
|
||||
$endBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $end);
|
||||
|
||||
// loop the end balances. This is an array for each account ($expenses)
|
||||
foreach ($endBalances as $accountId => $expenses) {
|
||||
$accountId = (int)$accountId;
|
||||
// loop each expense entry (each entry can be a different currency).
|
||||
foreach ($expenses as $currencyId => $endAmount) {
|
||||
$currencyId = (int)$currencyId;
|
||||
|
||||
// see if there is an accompanying start amount.
|
||||
// grab the difference and find the currency.
|
||||
$startAmount = $startBalances[$accountId][$currencyId] ?? '0';
|
||||
$diff = bcsub($endAmount, $startAmount);
|
||||
$currencies[$currencyId] = $currencies[$currencyId] ?? $this->currencyRepository->findNull($currencyId);
|
||||
if (0 !== bccomp($diff, '0')) {
|
||||
// store the values in a temporary array.
|
||||
$tempData[] = [
|
||||
'name' => $accountNames[$accountId],
|
||||
'difference' => bcmul($diff, '-1'),
|
||||
// For some reason this line is never covered in code coverage:
|
||||
'diff_float' => ((float)$diff) * -1, // @codeCoverageIgnore
|
||||
'currency_id' => $currencyId,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort temp array by amount.
|
||||
$amounts = array_column($tempData, 'diff_float');
|
||||
array_multisort($amounts, SORT_DESC, $tempData);
|
||||
|
||||
// loop all found currencies and build the data array for the chart.
|
||||
/**
|
||||
* @var int $currencyId
|
||||
* @var TransactionCurrency $currency
|
||||
*/
|
||||
foreach ($currencies as $currencyId => $currency) {
|
||||
$currentSet = [
|
||||
'label' => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'type' => 'bar', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => $this->expandNames($tempData),
|
||||
];
|
||||
$chartData[$currencyId] = $currentSet;
|
||||
}
|
||||
|
||||
// loop temp data and place data in correct array:
|
||||
foreach ($tempData as $entry) {
|
||||
$currencyId = $entry['currency_id'];
|
||||
$name = $entry['name'];
|
||||
$chartData[$currencyId]['entries'][$name] = round($entry['difference'], $chartData[$currencyId]['currency_decimal_places']);
|
||||
}
|
||||
$chartData = array_values($chartData);
|
||||
|
||||
return response()->json($chartData);
|
||||
}
|
||||
|
||||
}
|
||||
118
app/Api/V1/Controllers/Chart/AvailableBudgetController.php
Normal file
118
app/Api/V1/Controllers/Chart/AvailableBudgetController.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AvailableBudgetController.php
|
||||
* Copyright (c) 2019 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\Chart;
|
||||
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Models\AvailableBudget;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class AvailableBudgetController
|
||||
*/
|
||||
class AvailableBudgetController extends Controller
|
||||
{
|
||||
/** @var OperationsRepositoryInterface */
|
||||
private $opsRepository;
|
||||
/** @var BudgetRepositoryInterface */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* AvailableBudgetController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->opsRepository = app(OperationsRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
$this->opsRepository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AvailableBudget $availableBudget
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function overview(AvailableBudget $availableBudget): JsonResponse
|
||||
{
|
||||
$currency = $availableBudget->transactionCurrency;
|
||||
$budgets = $this->repository->getActiveBudgets();
|
||||
$budgetInformation = $this->opsRepository->spentInPeriodMc($budgets, new Collection, $availableBudget->start_date, $availableBudget->end_date);
|
||||
$spent = 0.0;
|
||||
|
||||
// get for current currency
|
||||
foreach ($budgetInformation as $spentInfo) {
|
||||
if ($spentInfo['currency_id'] === $availableBudget->transaction_currency_id) {
|
||||
$spent = $spentInfo['amount'];
|
||||
}
|
||||
}
|
||||
$left = bcadd($availableBudget->amount, (string)$spent);
|
||||
// left less than zero? Set to zero.
|
||||
if (bccomp($left, '0') === -1) {
|
||||
$left = '0';
|
||||
}
|
||||
|
||||
$chartData = [
|
||||
[
|
||||
'label' => trans('firefly.spent'),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'type' => 'pie',
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [$spent * -1],
|
||||
],
|
||||
[
|
||||
'label' => trans('firefly.left'),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'type' => 'line', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [round($left, $currency->decimal_places)],
|
||||
],
|
||||
];
|
||||
|
||||
return response()->json($chartData);
|
||||
}
|
||||
|
||||
}
|
||||
202
app/Api/V1/Controllers/Chart/CategoryController.php
Normal file
202
app/Api/V1/Controllers/Chart/CategoryController.php
Normal file
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CategoryController.php
|
||||
* Copyright (c) 2019 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\Chart;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\DateRequest;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\NoCategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\OperationsRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
* Class CategoryController
|
||||
*/
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
/** @var CategoryRepositoryInterface */
|
||||
private $categoryRepository;
|
||||
/** @var NoCategoryRepositoryInterface */
|
||||
private $noCatRepository;
|
||||
/** @var OperationsRepositoryInterface */
|
||||
private $opsRepository;
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$this->categoryRepository = app(CategoryRepositoryInterface::class);
|
||||
$this->opsRepository = app(OperationsRepositoryInterface::class);
|
||||
$this->noCatRepository = app(NoCategoryRepositoryInterface::class);
|
||||
$this->categoryRepository->setUser($user);
|
||||
$this->opsRepository->setUser($user);
|
||||
$this->noCatRepository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*
|
||||
* TODO after 4.8,0, simplify
|
||||
*/
|
||||
public function overview(DateRequest $request): JsonResponse
|
||||
{
|
||||
// parameters for chart:
|
||||
$dates = $request->getAll();
|
||||
/** @var Carbon $start */
|
||||
$start = $dates['start'];
|
||||
/** @var Carbon $end */
|
||||
$end = $dates['end'];
|
||||
|
||||
|
||||
$tempData = [];
|
||||
$spentWith = $this->opsRepository->listExpenses($start, $end);
|
||||
$earnedWith = $this->opsRepository->listIncome($start, $end);
|
||||
$spentWithout = $this->noCatRepository->listExpenses($start, $end);
|
||||
$earnedWithout = $this->noCatRepository->listIncome($start, $end);
|
||||
$categories = [];
|
||||
|
||||
|
||||
foreach ([$spentWith, $earnedWith] as $set) {
|
||||
foreach ($set as $currency) {
|
||||
foreach ($currency['categories'] as $category) {
|
||||
$categories[] = $category['name'];
|
||||
$inKey = sprintf('%d-i', $currency['currency_id']);
|
||||
$outKey = sprintf('%d-e', $currency['currency_id']);
|
||||
// make data arrays if not yet present.
|
||||
$tempData[$inKey] = $tempData[$inKey] ?? [
|
||||
'currency_id' => $currency['currency_id'],
|
||||
'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'currency_code' => $currency['currency_code'],
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
'currency_decimal_places' => $currency['currency_decimal_places'],
|
||||
'type' => 'bar', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [
|
||||
// per category:
|
||||
// "category" => 5,
|
||||
],
|
||||
];
|
||||
$tempData[$outKey] = $tempData[$outKey] ?? [
|
||||
'currency_id' => $currency['currency_id'],
|
||||
'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'currency_code' => $currency['currency_code'],
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
'currency_decimal_places' => $currency['currency_decimal_places'],
|
||||
'type' => 'bar', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [
|
||||
// per category:
|
||||
// "category" => 5,
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($category['transaction_journals'] as $journal) {
|
||||
// is it expense or income?
|
||||
$letter = -1 === bccomp($journal['amount'], '0') ? 'e' : 'i';
|
||||
$currentKey = sprintf('%d-%s', $currency['currency_id'], $letter);
|
||||
$name = $category['name'];
|
||||
$tempData[$currentKey]['entries'][$name] = $tempData[$currentKey]['entries'][$name] ?? '0';
|
||||
$tempData[$currentKey]['entries'][$name] = bcadd($tempData[$currentKey]['entries'][$name], $journal['amount']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ([$spentWithout, $earnedWithout] as $set) {
|
||||
foreach ($set as $currency) {
|
||||
$inKey = sprintf('%d-i', $currency['currency_id']);
|
||||
$outKey = sprintf('%d-e', $currency['currency_id']);
|
||||
$categories[] = (string)trans('firefly.no_category');
|
||||
// make data arrays if not yet present.
|
||||
$tempData[$inKey] = $tempData[$inKey] ?? [
|
||||
'currency_id' => $currency['currency_id'],
|
||||
'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'currency_code' => $currency['currency_code'],
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
'currency_decimal_places' => $currency['currency_decimal_places'],
|
||||
'type' => 'bar', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [
|
||||
// per category:
|
||||
// "category" => 5,
|
||||
],
|
||||
];
|
||||
$tempData[$outKey] = $tempData[$outKey] ?? [
|
||||
'currency_id' => $currency['currency_id'],
|
||||
'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
|
||||
'currency_code' => $currency['currency_code'],
|
||||
'currency_symbol' => $currency['currency_symbol'],
|
||||
'currency_decimal_places' => $currency['currency_decimal_places'],
|
||||
'type' => 'bar', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [
|
||||
// per category:
|
||||
// "category" => 5,
|
||||
],
|
||||
];
|
||||
foreach ($currency['transaction_journals'] as $journal) {
|
||||
// is it expense or income?
|
||||
$letter = -1 === bccomp($journal['amount'], '0') ? 'e' : 'i';
|
||||
$currentKey = sprintf('%d-%s', $currency['currency_id'], $letter);
|
||||
$name = (string)trans('firefly.no_category');
|
||||
$tempData[$currentKey]['entries'][$name] = $tempData[$currentKey]['entries'][$name] ?? '0';
|
||||
$tempData[$currentKey]['entries'][$name] = bcadd($tempData[$currentKey]['entries'][$name], $journal['amount']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// re-sort every spent array and add 0 for missing entries.
|
||||
foreach ($tempData as $index => $set) {
|
||||
$oldSet = $set['entries'];
|
||||
$newSet = [];
|
||||
foreach ($categories as $category) {
|
||||
$value = $oldSet[$category] ?? '0';
|
||||
$value = -1 === bccomp($value, '0') ? bcmul($value, '-1') : $value;
|
||||
$newSet[$category] = $value;
|
||||
}
|
||||
$tempData[$index]['entries'] = $newSet;
|
||||
}
|
||||
$chartData = array_values($tempData);
|
||||
|
||||
return response()->json($chartData);
|
||||
}
|
||||
}
|
||||
@@ -23,15 +23,17 @@ 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.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ConfigurationController extends Controller
|
||||
{
|
||||
@@ -41,7 +43,8 @@ class ConfigurationController extends Controller
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* BudgetController constructor.
|
||||
* ConfigurationController constructor.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -54,7 +57,6 @@ class ConfigurationController extends Controller
|
||||
$admin = auth()->user();
|
||||
|
||||
if (!$this->repository->hasRole($admin, 'owner')) {
|
||||
/** @noinspection ExceptionsAnnotatingAndHandlingInspection */
|
||||
throw new FireflyException('No access to method.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
@@ -72,47 +74,30 @@ class ConfigurationController extends Controller
|
||||
{
|
||||
$configData = $this->getConfigData();
|
||||
|
||||
return response()->json(['data' => $configData], 200)->header('Content-Type', 'application/vnd.api+json');
|
||||
return response()->json(['data' => $configData])->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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');
|
||||
return response()->json(['data' => $configData])->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all config values.
|
||||
*
|
||||
* @return array
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
private function getConfigData(): array
|
||||
{
|
||||
|
||||
@@ -30,6 +30,8 @@ use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Log;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
|
||||
@@ -37,7 +39,7 @@ use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
* Class Controller.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @SuppressWarnings(PHPMD.NumberOfChildren)
|
||||
*
|
||||
*/
|
||||
class Controller extends BaseController
|
||||
{
|
||||
@@ -61,7 +63,6 @@ class Controller extends BaseController
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
protected function buildParams(): string
|
||||
{
|
||||
@@ -82,11 +83,23 @@ class Controller extends BaseController
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Manager
|
||||
*/
|
||||
protected function getManager(): Manager
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = request()->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
return $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to grab all parameters from the URI.
|
||||
*
|
||||
* @return ParameterBag
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
private function getParameters(): ParameterBag
|
||||
{
|
||||
@@ -100,11 +113,11 @@ 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 {
|
||||
$obj = new Carbon($date);
|
||||
$obj = Carbon::parse($date);
|
||||
} catch (InvalidDateException $e) {
|
||||
// don't care
|
||||
Log::error(sprintf('Invalid date exception in API controller: %s', $e->getMessage()));
|
||||
@@ -113,6 +126,15 @@ class Controller extends BaseController
|
||||
$bag->set($field, $obj);
|
||||
}
|
||||
|
||||
// integer fields:
|
||||
$integers = ['limit'];
|
||||
foreach ($integers as $integer) {
|
||||
$value = request()->query->get($integer);
|
||||
if (null !== $value) {
|
||||
$bag->set($integer, (int)$value);
|
||||
}
|
||||
}
|
||||
|
||||
return $bag;
|
||||
|
||||
}
|
||||
|
||||
@@ -26,27 +26,49 @@ namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\CurrencyRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Models\RecurrenceTransaction;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleTrigger;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||
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\TransactionGroupTransformer;
|
||||
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 CurrencyController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class CurrencyController extends Controller
|
||||
{
|
||||
use AccountFilter, TransactionFilter;
|
||||
/** @var CurrencyRepositoryInterface The currency repository */
|
||||
private $repository;
|
||||
/** @var UserRepositoryInterface The user repository */
|
||||
@@ -54,6 +76,8 @@ class CurrencyController extends Controller
|
||||
|
||||
/**
|
||||
* CurrencyRepository constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -73,13 +97,214 @@ class CurrencyController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a list of accounts.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function accounts(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
|
||||
// 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(
|
||||
static 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());
|
||||
|
||||
/** @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 TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function availableBudgets(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
$manager = $this->getManager();
|
||||
// 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);
|
||||
|
||||
/** @var AvailableBudgetRepositoryInterface $abRepository */
|
||||
$abRepository = app(AvailableBudgetRepositoryInterface::class);
|
||||
|
||||
$repository->setUser($admin);
|
||||
$collection = $abRepository->getAvailableBudgetsByCurrency($currency);
|
||||
$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());
|
||||
|
||||
/** @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 TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function bills(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @var BillRepositoryInterface $repository */
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$unfiltered = $repository->getBills();
|
||||
|
||||
// filter and paginate list:
|
||||
$collection = $unfiltered->filter(
|
||||
static 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());
|
||||
|
||||
/** @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 TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function budgetLimits(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
/** @var BudgetLimitRepositoryInterface $blRepository */
|
||||
$blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||
|
||||
$manager = $this->getManager();
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$collection = $blRepository->getAllBudgetLimitsByCurrency($currency, $this->parameters->get('start'), $this->parameters->get('end'));
|
||||
$count = $collection->count();
|
||||
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.currencies.budget_limits', [$currency->code]) . $this->buildParams());
|
||||
|
||||
/** @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 TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function cer(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = $this->getManager();
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$collection = $this->repository->getExchangeRates($currency);
|
||||
|
||||
|
||||
$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());
|
||||
|
||||
/** @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.
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
@@ -90,7 +315,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);
|
||||
@@ -99,16 +324,71 @@ class CurrencyController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
* Disable a currency.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
public function disable(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
// must be unused.
|
||||
if ($this->repository->currencyInUse($currency)) {
|
||||
return response()->json([], 409);
|
||||
}
|
||||
$this->repository->disable($currency);
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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 TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function enable(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$this->repository->enable($currency);
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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.
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(): 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);
|
||||
@@ -116,40 +396,169 @@ class CurrencyController extends Controller
|
||||
$paginator->setPath(route('api.v1.currencies.index') . $this->buildParams());
|
||||
|
||||
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
$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 TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function makeDefault(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$this->repository->enable($currency);
|
||||
|
||||
app('preferences')->set('currencyPreference', $currency->code);
|
||||
app('preferences')->mark();
|
||||
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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 TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function recurrences(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
// 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(
|
||||
static 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());
|
||||
|
||||
/** @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 TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function rules(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
$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(
|
||||
static 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());
|
||||
|
||||
/** @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.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
public function show(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));
|
||||
$manager = $this->getManager();
|
||||
$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');
|
||||
}
|
||||
@@ -171,13 +580,15 @@ class CurrencyController extends Controller
|
||||
app('preferences')->set('currencyPreference', $currency->code);
|
||||
app('preferences')->mark();
|
||||
}
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
$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 +596,61 @@ class CurrencyController extends Controller
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
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 = $this->getManager();
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// filter on currency.
|
||||
->setCurrency($currency)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
// set page size:
|
||||
->setLimit($pageSize)
|
||||
// set page to retrieve
|
||||
->setPage($this->parameters->get('page'))
|
||||
// set types of transactions to return.
|
||||
->setTypes($types);
|
||||
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.currencies.transactions', [$currency->code]) . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a currency.
|
||||
@@ -204,14 +670,16 @@ class CurrencyController extends Controller
|
||||
app('preferences')->mark();
|
||||
}
|
||||
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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');
|
||||
|
||||
|
||||
@@ -31,12 +31,12 @@ use FireflyIII\Transformers\CurrencyExchangeRateTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class CurrencyExchangeRateController
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class CurrencyExchangeRateController extends Controller
|
||||
{
|
||||
@@ -45,6 +45,7 @@ class CurrencyExchangeRateController extends Controller
|
||||
|
||||
/**
|
||||
* CurrencyExchangeRateController constructor.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -73,11 +74,7 @@ class CurrencyExchangeRateController extends Controller
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$manager = $this->getManager();
|
||||
$fromCurrency = $this->repository->findByCodeNull($request->get('from') ?? 'EUR');
|
||||
$toCurrency = $this->repository->findByCodeNull($request->get('to') ?? 'USD');
|
||||
|
||||
@@ -88,10 +85,12 @@ class CurrencyExchangeRateController extends Controller
|
||||
throw new FireflyException('Unknown destination currency.');
|
||||
}
|
||||
|
||||
/** @var Carbon $dateObj */
|
||||
$dateObj = Carbon::createFromFormat('Y-m-d', $request->get('date') ?? date('Y-m-d'));
|
||||
$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 +102,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');
|
||||
}
|
||||
|
||||
178
app/Api/V1/Controllers/ImportController.php
Normal file
178
app/Api/V1/Controllers/ImportController.php
Normal file
@@ -0,0 +1,178 @@
|
||||
<?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\GroupCollectorInterface;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\ImportJobTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
/**
|
||||
* Class ImportController
|
||||
*/
|
||||
class ImportController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var ImportJobRepositoryInterface Import job repository. */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* ImportController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function listAll(): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = $this->getManager();
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of accounts. Count it and split it.
|
||||
$collection = $this->repository->get();
|
||||
$count = $collection->count();
|
||||
$importJobs = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($importJobs, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.import.list') . $this->buildParams());
|
||||
|
||||
/** @var ImportJobTransformer $transformer */
|
||||
$transformer = app(ImportJobTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($importJobs, $transformer, 'import_jobs');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $importJob
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(ImportJob $importJob): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
/** @var ImportJobTransformer $transformer */
|
||||
$transformer = app(ImportJobTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($importJob, $transformer, 'import_jobs');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all transactions
|
||||
*
|
||||
* @param Request $request
|
||||
* @param ImportJob $importJob
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function transactions(Request $request, ImportJob $importJob): JsonResponse
|
||||
{
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$this->parameters->set('type', $type);
|
||||
|
||||
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$tag = $importJob->tag;
|
||||
$transactions = new Collection();
|
||||
$paginator = new LengthAwarePaginator($transactions, 0, $pageSize);
|
||||
$paginator->setPath(route('api.v1.import.transactions', [$importJob->key]) . $this->buildParams());
|
||||
|
||||
if (null !== $tag) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// filter on tag.
|
||||
->setTag($tag)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
// set page size:
|
||||
->setLimit($pageSize)
|
||||
// set page to retrieve
|
||||
->setPage($this->parameters->get('page'))
|
||||
// set types of transactions to return.
|
||||
->setTypes($types);
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
}
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,27 +25,28 @@ namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\LinkTypeRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\LinkType;
|
||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\LinkTypeTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
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 LinkTypeController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class LinkTypeController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var LinkTypeRepositoryInterface The link type repository */
|
||||
private $repository;
|
||||
|
||||
@@ -54,6 +55,8 @@ class LinkTypeController extends Controller
|
||||
|
||||
/**
|
||||
* LinkTypeController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -78,13 +81,14 @@ class LinkTypeController extends Controller
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(LinkType $linkType): JsonResponse
|
||||
{
|
||||
if (false === $linkType->editable) {
|
||||
throw new FireflyException(sprintf('You cannot delete this link type (#%d, "%s")', $linkType->id, $linkType->name));
|
||||
}
|
||||
$this->repository->destroy($linkType, null);
|
||||
$this->repository->destroy($linkType);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
@@ -92,15 +96,13 @@ class LinkTypeController extends Controller
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse]
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager = $this->getManager();
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of accounts. Count it and split it.
|
||||
@@ -112,9 +114,11 @@ class LinkTypeController extends Controller
|
||||
$paginator = new LengthAwarePaginator($linkTypes, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.link_types.index') . $this->buildParams());
|
||||
|
||||
// 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');
|
||||
@@ -124,22 +128,19 @@ class LinkTypeController extends Controller
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param LinkType $linkType
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, LinkType $linkType): JsonResponse
|
||||
public function show(LinkType $linkType): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$manager = $this->getManager();
|
||||
/** @var LinkTypeTransformer $transformer */
|
||||
$transformer = app(LinkTypeTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
// 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');
|
||||
$resource = new Item($linkType, $transformer, 'link_types');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
@@ -164,16 +165,76 @@ class LinkTypeController extends Controller
|
||||
$data = $request->getAll();
|
||||
// if currency ID is 0, find the currency by the code:
|
||||
$linkType = $this->repository->store($data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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 Request $request
|
||||
* @param LinkType $linkType
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
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 = $this->getManager();
|
||||
|
||||
// whatever is returned by the query, it must be part of these journals:
|
||||
$journalIds = $this->repository->getJournalIds($linkType);
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// filter on journal IDs.
|
||||
->setJournalIds($journalIds)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
// set page size:
|
||||
->setLimit($pageSize)
|
||||
// set page to retrieve
|
||||
->setPage($this->parameters->get('page'))
|
||||
// set types of transactions to return.
|
||||
->setTypes($types);
|
||||
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update object.
|
||||
*
|
||||
@@ -198,11 +259,12 @@ class LinkTypeController extends Controller
|
||||
|
||||
$data = $request->getAll();
|
||||
$this->repository->update($linkType, $data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
/** @var LinkTypeTransformer $transformer */
|
||||
$transformer = app(LinkTypeTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($linkType, new LinkTypeTransformer($this->parameters), 'link_types');
|
||||
$resource = new Item($linkType, $transformer, 'link_types');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -27,21 +27,18 @@ 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;
|
||||
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 PiggyBankController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class PiggyBankController extends Controller
|
||||
{
|
||||
@@ -51,6 +48,8 @@ class PiggyBankController extends Controller
|
||||
|
||||
/**
|
||||
* PiggyBankController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -75,6 +74,7 @@ class PiggyBankController extends Controller
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
@@ -86,16 +86,12 @@ class PiggyBankController extends Controller
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse]
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
$manager = $this->getManager();
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
@@ -108,9 +104,11 @@ class PiggyBankController extends Controller
|
||||
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.piggy_banks.index') . $this->buildParams());
|
||||
|
||||
// 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');
|
||||
@@ -120,22 +118,53 @@ class PiggyBankController extends Controller
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, PiggyBank $piggyBank): JsonResponse
|
||||
public function piggyBankEvents(PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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);
|
||||
|
||||
$resource = new Item($piggyBank, new PiggyBankTransformer($this->parameters), 'piggy_banks');
|
||||
// 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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @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');
|
||||
|
||||
@@ -153,11 +182,13 @@ class PiggyBankController extends Controller
|
||||
{
|
||||
$piggyBank = $this->repository->store($request->getAll());
|
||||
if (null !== $piggyBank) {
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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');
|
||||
}
|
||||
@@ -175,12 +206,20 @@ class PiggyBankController extends Controller
|
||||
*/
|
||||
public function update(PiggyBankRequest $request, PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
$piggyBank = $this->repository->update($piggyBank, $request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$data = $request->getAll();
|
||||
$piggyBank = $this->repository->update($piggyBank, $data);
|
||||
|
||||
$resource = new Item($piggyBank, new PiggyBankTransformer($this->parameters), 'piggy_banks');
|
||||
if ('' !== $data['current_amount']) {
|
||||
$this->repository->setCurrentAmount($piggyBank, $data['current_amount']);
|
||||
}
|
||||
|
||||
|
||||
$manager = $this->getManager();
|
||||
/** @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');
|
||||
|
||||
|
||||
@@ -24,16 +24,15 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\PreferenceRequest;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Transformers\PreferenceTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -41,22 +40,52 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
||||
*/
|
||||
class PreferenceController extends Controller
|
||||
{
|
||||
/**
|
||||
* LinkTypeController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
static function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser($user);
|
||||
|
||||
// an important fallback is that the frontPageAccount array gets refilled automatically
|
||||
// when it turns up empty.
|
||||
$frontPageAccounts = app('preferences')->getForUser($user, 'frontPageAccounts', [])->data;
|
||||
if (0 === count($frontPageAccounts)) {
|
||||
/** @var Collection $accounts */
|
||||
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
$accountIds = $accounts->pluck('id')->toArray();
|
||||
app('preferences')->setForUser($user, 'frontPageAccounts', $accountIds);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse]
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$available = [
|
||||
$user = auth()->user();
|
||||
$available = [
|
||||
'language', 'customFiscalYear', 'fiscalYearStart', 'currencyPreference',
|
||||
'transaction_journal_optional_fields', 'frontPageAccounts', 'viewRange',
|
||||
'listPageSize, twoFactorAuthEnabled',
|
||||
'listPageSize',
|
||||
];
|
||||
|
||||
$preferences = new Collection;
|
||||
foreach ($available as $name) {
|
||||
$pref = app('preferences')->getForUser($user, $name);
|
||||
@@ -65,39 +94,36 @@ class PreferenceController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager = $this->getManager();
|
||||
|
||||
// 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.
|
||||
* Return a single preference by name.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Preference $preference
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Preference $preference): JsonResponse
|
||||
public function show(Preference $preference): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager = $this->getManager();
|
||||
/** @var PreferenceTransformer $transformer */
|
||||
$transformer = app(PreferenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($preference, new PreferenceTransformer($this->parameters), 'preferences');
|
||||
$resource = new Item($preference, $transformer, 'preferences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +133,6 @@ class PreferenceController extends Controller
|
||||
* @param Preference $preference
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
public function update(PreferenceRequest $request, Preference $preference): JsonResponse
|
||||
{
|
||||
@@ -125,19 +150,17 @@ class PreferenceController extends Controller
|
||||
$newValue = (int)$data['data'];
|
||||
break;
|
||||
case 'customFiscalYear':
|
||||
case 'twoFactorAuthEnabled':
|
||||
$newValue = 1 === (int)$data['data'];
|
||||
break;
|
||||
}
|
||||
$result = app('preferences')->set($preference->name, $newValue);
|
||||
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager = $this->getManager();
|
||||
/** @var PreferenceTransformer $transformer */
|
||||
$transformer = app(PreferenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($result, new PreferenceTransformer($this->parameters), 'preferences');
|
||||
$resource = new Item($result, $transformer, 'preferences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -23,30 +23,38 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\RecurrenceRequest;
|
||||
use FireflyIII\Api\V1\Requests\RecurrenceStoreRequest;
|
||||
use FireflyIII\Api\V1\Requests\RecurrenceUpdateRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\Cronjobs\RecurringCronjob;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
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;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RecurrenceController
|
||||
*/
|
||||
class RecurrenceController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var RecurringRepositoryInterface The recurring transaction repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* RecurrenceController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -71,6 +79,7 @@ class RecurrenceController extends Controller
|
||||
* @param Recurrence $recurrence
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(Recurrence $recurrence): JsonResponse
|
||||
{
|
||||
@@ -82,15 +91,12 @@ class RecurrenceController extends Controller
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse]
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager = $this->getManager();
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
@@ -104,9 +110,11 @@ class RecurrenceController extends Controller
|
||||
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.recurrences.index') . $this->buildParams());
|
||||
|
||||
// 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');
|
||||
@@ -116,22 +124,20 @@ class RecurrenceController extends Controller
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Recurrence $recurrence
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Recurrence $recurrence): JsonResponse
|
||||
public function show(Recurrence $recurrence): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
$manager = $this->getManager();
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($recurrence, new RecurrenceTransformer($this->parameters), 'recurrences');
|
||||
$resource = new Item($recurrence, $transformer, 'recurrences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
@@ -141,38 +147,126 @@ class RecurrenceController extends Controller
|
||||
/**
|
||||
* Store new object.
|
||||
*
|
||||
* @param RecurrenceRequest $request
|
||||
* @param RecurrenceStoreRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function store(RecurrenceRequest $request): JsonResponse
|
||||
public function store(RecurrenceStoreRequest $request): JsonResponse
|
||||
{
|
||||
$recurrence = $this->repository->store($request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($recurrence, new RecurrenceTransformer($this->parameters), 'recurrences');
|
||||
$data = $request->getAll();
|
||||
$recurrence = $this->repository->store($data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @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
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
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 = $this->getManager();
|
||||
// whatever is returned by the query, it must be part of these journals:
|
||||
$journalIds = $this->repository->getJournalIds($recurrence);
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// filter on journal IDs.
|
||||
->setJournalIds($journalIds)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
// set page size:
|
||||
->setLimit($pageSize)
|
||||
// set page to retrieve
|
||||
->setPage($this->parameters->get('page'))
|
||||
// set types of transactions to return.
|
||||
->setTypes($types);
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
return response()->json([], 418); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
* Update single recurrence.
|
||||
*
|
||||
* @param RecurrenceRequest $request
|
||||
* @param Recurrence $recurrence
|
||||
* @param RecurrenceUpdateRequest $request
|
||||
* @param Recurrence $recurrence
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(RecurrenceRequest $request, Recurrence $recurrence): JsonResponse
|
||||
public function update(RecurrenceUpdateRequest $request, Recurrence $recurrence): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$category = $this->repository->update($recurrence, $data);
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$resource = new Item($category, new RecurrenceTransformer($this->parameters), 'recurrences');
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($category, $transformer, 'recurrences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -23,30 +23,42 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\RuleRequest;
|
||||
use FireflyIII\Api\V1\Requests\RuleStoreRequest;
|
||||
use FireflyIII\Api\V1\Requests\RuleTestRequest;
|
||||
use FireflyIII\Api\V1\Requests\RuleTriggerRequest;
|
||||
use FireflyIII\Api\V1\Requests\RuleUpdateRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\TransactionRules\Engine\RuleEngine;
|
||||
use FireflyIII\TransactionRules\TransactionMatcher;
|
||||
use FireflyIII\Transformers\RuleTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
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;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RuleController
|
||||
*
|
||||
*/
|
||||
class RuleController extends Controller
|
||||
{
|
||||
/** @var AccountRepositoryInterface Account repository */
|
||||
private $accountRepository;
|
||||
/** @var RuleRepositoryInterface The rule repository */
|
||||
private $ruleRepository;
|
||||
|
||||
/**
|
||||
* RuleController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -59,6 +71,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);
|
||||
}
|
||||
);
|
||||
@@ -70,6 +85,7 @@ class RuleController extends Controller
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(Rule $rule): JsonResponse
|
||||
{
|
||||
@@ -81,15 +97,12 @@ class RuleController extends Controller
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse]
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager = $this->getManager();
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
@@ -103,34 +116,75 @@ class RuleController extends Controller
|
||||
$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));
|
||||
$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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function moveDown(Rule $rule): JsonResponse
|
||||
{
|
||||
$this->ruleRepository->moveDown($rule);
|
||||
$rule = $this->ruleRepository->find($rule->id);
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @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 Rule $rule
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function moveUp(Rule $rule): JsonResponse
|
||||
{
|
||||
$this->ruleRepository->moveUp($rule);
|
||||
$rule = $this->ruleRepository->find($rule->id);
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Rule $rule
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Rule $rule): JsonResponse
|
||||
public function show(Rule $rule): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
$manager = $this->getManager();
|
||||
/** @var RuleTransformer $transformer */
|
||||
$transformer = app(RuleTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($rule, new RuleTransformer($this->parameters), 'rules');
|
||||
$resource = new Item($rule, $transformer, 'rules');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
@@ -139,40 +193,122 @@ class RuleController extends Controller
|
||||
/**
|
||||
* Store new object.
|
||||
*
|
||||
* @param RuleRequest $request
|
||||
* @param RuleStoreRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(RuleRequest $request): JsonResponse
|
||||
public function store(RuleStoreRequest $request): JsonResponse
|
||||
{
|
||||
$rule = $this->ruleRepository->store($request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
/** @var RuleTransformer $transformer */
|
||||
$transformer = app(RuleTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($rule, new RuleTransformer($this->parameters), 'rules');
|
||||
$resource = new Item($rule, $transformer, 'rules');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a rule.
|
||||
* @param RuleTestRequest $request
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @param RuleRequest $request
|
||||
* @param Rule $rule
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function testRule(RuleTestRequest $request, Rule $rule): JsonResponse
|
||||
{
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$parameters = $request->getTestParameters();
|
||||
/** @var Rule $rule */
|
||||
Log::debug(sprintf('Now testing rule #%d, "%s"', $rule->id, $rule->title));
|
||||
/** @var TransactionMatcher $matcher */
|
||||
$matcher = app(TransactionMatcher::class);
|
||||
// set all parameters:
|
||||
$matcher->setRule($rule);
|
||||
$matcher->setStartDate($parameters['start_date']);
|
||||
$matcher->setEndDate($parameters['end_date']);
|
||||
$matcher->setSearchLimit($parameters['search_limit']);
|
||||
$matcher->setTriggeredLimit($parameters['trigger_limit']);
|
||||
$matcher->setAccounts($parameters['accounts']);
|
||||
|
||||
$matchingTransactions = $matcher->findTransactionsByRule();
|
||||
$count = count($matchingTransactions);
|
||||
$transactions = array_slice($matchingTransactions, ($parameters['page'] - 1) * $pageSize, $pageSize);
|
||||
$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 = $this->getManager();
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::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 RuleTriggerRequest $request
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(RuleRequest $request, Rule $rule): JsonResponse
|
||||
public function triggerRule(RuleTriggerRequest $request, Rule $rule): JsonResponse
|
||||
{
|
||||
$rule = $this->ruleRepository->update($rule, $request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
// Get parameters specified by the user
|
||||
$parameters = $request->getTriggerParameters();
|
||||
|
||||
$resource = new Item($rule, new RuleTransformer($this->parameters), 'rules');
|
||||
/** @var RuleEngine $ruleEngine */
|
||||
$ruleEngine = app(RuleEngine::class);
|
||||
$ruleEngine->setUser(auth()->user());
|
||||
|
||||
$rules = [$rule->id];
|
||||
|
||||
$ruleEngine->setRulesToApply($rules);
|
||||
$ruleEngine->setTriggerMode(RuleEngine::TRIGGER_STORE);
|
||||
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setAccounts($parameters['accounts']);
|
||||
$collector->setRange($parameters['start_date'], $parameters['end_date']);
|
||||
$journals = $collector->getExtractedJournals();
|
||||
|
||||
/** @var array $journal */
|
||||
foreach ($journals as $journal) {
|
||||
Log::debug('Start of new journal.');
|
||||
$ruleEngine->processJournalArray($journal);
|
||||
Log::debug('Done with all rules for this group + done with journal.');
|
||||
}
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a rule.
|
||||
*
|
||||
* @param RuleUpdateRequest $request
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(RuleUpdateRequest $request, Rule $rule): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$rule = $this->ruleRepository->update($rule, $data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @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,31 +23,44 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Api\V1\Requests\RuleGroupRequest;
|
||||
use FireflyIII\Api\V1\Requests\RuleGroupTestRequest;
|
||||
use FireflyIII\Api\V1\Requests\RuleGroupTriggerRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
use FireflyIII\TransactionRules\Engine\RuleEngine;
|
||||
use FireflyIII\TransactionRules\TransactionMatcher;
|
||||
use FireflyIII\Transformers\RuleGroupTransformer;
|
||||
use FireflyIII\Transformers\RuleTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use Illuminate\Support\Collection;
|
||||
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 RuleGroupController
|
||||
*/
|
||||
class RuleGroupController extends Controller
|
||||
{
|
||||
/** @var AccountRepositoryInterface Account repository */
|
||||
private $accountRepository;
|
||||
/** @var RuleGroupRepositoryInterface The rule group repository */
|
||||
private $ruleGroupRepository;
|
||||
|
||||
/**
|
||||
* RuleGroupController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -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);
|
||||
}
|
||||
);
|
||||
@@ -71,6 +87,7 @@ class RuleGroupController extends Controller
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(RuleGroup $ruleGroup): JsonResponse
|
||||
{
|
||||
@@ -82,16 +99,12 @@ class RuleGroupController extends Controller
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse]
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
$manager = $this->getManager();
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
@@ -104,33 +117,104 @@ class RuleGroupController extends Controller
|
||||
$paginator = new LengthAwarePaginator($ruleGroups, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.rule_groups.index') . $this->buildParams());
|
||||
|
||||
// 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');
|
||||
}
|
||||
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(Request $request, RuleGroup $ruleGroup): JsonResponse
|
||||
public function moveDown(RuleGroup $ruleGroup): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
$this->ruleGroupRepository->moveDown($ruleGroup);
|
||||
$ruleGroup = $this->ruleGroupRepository->find($ruleGroup->id);
|
||||
$manager = $this->getManager();
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
/** @var RuleGroupTransformer $transformer */
|
||||
$transformer = app(RuleGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($ruleGroup, new RuleGroupTransformer($this->parameters), 'rule_groups');
|
||||
$resource = new Item($ruleGroup, $transformer, 'rule_groups');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function moveUp(RuleGroup $ruleGroup): JsonResponse
|
||||
{
|
||||
$this->ruleGroupRepository->moveUp($ruleGroup);
|
||||
$ruleGroup = $this->ruleGroupRepository->find($ruleGroup->id);
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @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 RuleGroup $group
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function rules(RuleGroup $group): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
// 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());
|
||||
|
||||
/** @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.
|
||||
*
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(RuleGroup $ruleGroup): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
/** @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');
|
||||
|
||||
@@ -146,16 +230,119 @@ class RuleGroupController extends Controller
|
||||
public function store(RuleGroupRequest $request): JsonResponse
|
||||
{
|
||||
$ruleGroup = $this->ruleGroupRepository->store($request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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 RuleGroupTestRequest $request
|
||||
* @param RuleGroup $group
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*
|
||||
*/
|
||||
public function testGroup(RuleGroupTestRequest $request, RuleGroup $group): JsonResponse
|
||||
{
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
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.');
|
||||
}
|
||||
$parameters = $request->getTestParameters();
|
||||
$matchingTransactions = [];
|
||||
|
||||
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($parameters['start_date']);
|
||||
$matcher->setEndDate($parameters['end_date']);
|
||||
$matcher->setSearchLimit($parameters['search_limit']);
|
||||
$matcher->setTriggeredLimit($parameters['trigger_limit']);
|
||||
$matcher->setAccounts($parameters['accounts']);
|
||||
|
||||
$result = $matcher->findTransactionsByRule();
|
||||
/** @noinspection AdditionOperationOnArraysInspection */
|
||||
$matchingTransactions = $result + $matchingTransactions;
|
||||
}
|
||||
|
||||
// make paginator out of results.
|
||||
$count = count($matchingTransactions);
|
||||
$transactions = array_slice($matchingTransactions, ($parameters['page'] - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($transactions, $count, $pageSize, $parameters['page']);
|
||||
$paginator->setPath(route('api.v1.rule_groups.test', [$group->id]) . $this->buildParams());
|
||||
|
||||
$manager = $this->getManager();
|
||||
$transformer = app(TransactionGroupTransformer::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 RuleGroupTriggerRequest $request
|
||||
* @param RuleGroup $group
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws Exception
|
||||
*/
|
||||
public function triggerGroup(RuleGroupTriggerRequest $request, RuleGroup $group): JsonResponse
|
||||
{
|
||||
$parameters = $request->getTriggerParameters();
|
||||
|
||||
/** @var Collection $collection */
|
||||
$collection = $this->ruleGroupRepository->getActiveRules($group);
|
||||
$rules = [];
|
||||
/** @var Rule $item */
|
||||
foreach ($collection as $item) {
|
||||
$rules[] = $item->id;
|
||||
}
|
||||
|
||||
// start looping.
|
||||
/** @var RuleEngine $ruleEngine */
|
||||
$ruleEngine = app(RuleEngine::class);
|
||||
$ruleEngine->setUser(auth()->user());
|
||||
$ruleEngine->setRulesToApply($rules);
|
||||
$ruleEngine->setTriggerMode(RuleEngine::TRIGGER_STORE);
|
||||
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setAccounts($parameters['accounts']);
|
||||
$collector->setRange($parameters['start_date'], $parameters['end_date']);
|
||||
$journals = $collector->getExtractedJournals();
|
||||
|
||||
/** @var array $journal */
|
||||
foreach ($journals as $journal) {
|
||||
Log::debug('Start of new journal.');
|
||||
$ruleEngine->processJournalArray($journal);
|
||||
Log::debug('Done with all rules for this group + done with journal.');
|
||||
}
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a rule group.
|
||||
*
|
||||
@@ -167,13 +354,14 @@ class RuleGroupController extends Controller
|
||||
public function update(RuleGroupRequest $request, RuleGroup $ruleGroup): JsonResponse
|
||||
{
|
||||
$ruleGroup = $this->ruleGroupRepository->update($ruleGroup, $request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
$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');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
444
app/Api/V1/Controllers/SummaryController.php
Normal file
444
app/Api/V1/Controllers/SummaryController.php
Normal file
@@ -0,0 +1,444 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SummaryController.php
|
||||
* Copyright (c) 2019 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 Carbon\Carbon;
|
||||
use Exception;
|
||||
use FireflyIII\Api\V1\Requests\DateRequest;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Helpers\Report\NetWorthInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class SummaryController
|
||||
*/
|
||||
class SummaryController extends Controller
|
||||
{
|
||||
/** @var AvailableBudgetRepositoryInterface */
|
||||
private $abRepository;
|
||||
/** @var AccountRepositoryInterface */
|
||||
private $accountRepository;
|
||||
/** @var BillRepositoryInterface */
|
||||
private $billRepository;
|
||||
/** @var BudgetRepositoryInterface */
|
||||
private $budgetRepository;
|
||||
/** @var CurrencyRepositoryInterface */
|
||||
private $currencyRepos;
|
||||
|
||||
/** @var OperationsRepositoryInterface */
|
||||
private $opsRepository;
|
||||
|
||||
/**
|
||||
* SummaryController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||
$this->billRepository = app(BillRepositoryInterface::class);
|
||||
$this->budgetRepository = app(BudgetRepositoryInterface::class);
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
$this->abRepository = app(AvailableBudgetRepositoryInterface::class);
|
||||
$this->opsRepository = app(OperationsRepositoryInterface::class);
|
||||
|
||||
$this->billRepository->setUser($user);
|
||||
$this->currencyRepos->setUser($user);
|
||||
$this->budgetRepository->setUser($user);
|
||||
$this->accountRepository->setUser($user);
|
||||
$this->abRepository->setUser($user);
|
||||
$this->opsRepository->setUser($user);
|
||||
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws Exception
|
||||
*/
|
||||
public function basic(DateRequest $request): JsonResponse
|
||||
{
|
||||
// parameters for boxes:
|
||||
$dates = $request->getAll();
|
||||
$start = $dates['start'];
|
||||
$end = $dates['end'];
|
||||
$code = $request->get('currency_code');
|
||||
|
||||
// balance information:
|
||||
$balanceData = $this->getBalanceInformation($start, $end);
|
||||
$billData = $this->getBillInformation($start, $end);
|
||||
$spentData = $this->getLeftToSpendInfo($start, $end);
|
||||
$networthData = $this->getNetWorthInfo($start, $end);
|
||||
$total = array_merge($balanceData, $billData, $spentData, $networthData);
|
||||
|
||||
// give new keys
|
||||
$return = [];
|
||||
foreach ($total as $entry) {
|
||||
if (null === $code || (null !== $code && $code === $entry['currency_code'])) {
|
||||
$return[$entry['key']] = $entry;
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json($return);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if date is outside session range.
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function notInDateRange(Carbon $date, Carbon $start, Carbon $end): bool // Validate a preference
|
||||
{
|
||||
$result = false;
|
||||
if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) {
|
||||
$result = true;
|
||||
}
|
||||
// start and end in the past? use $end
|
||||
if ($start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date)) {
|
||||
$result = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will scroll through the results of the spentInPeriodMc() array and return the correct info.
|
||||
*
|
||||
* @param array $spentInfo
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function findInSpentArray(array $spentInfo, TransactionCurrency $currency): string
|
||||
{
|
||||
foreach ($spentInfo as $array) {
|
||||
if ($array['currency_id'] === $currency->id) {
|
||||
return (string)$array['amount'];
|
||||
}
|
||||
}
|
||||
|
||||
return '0'; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getBalanceInformation(Carbon $start, Carbon $end): array
|
||||
{
|
||||
// prep some arrays:
|
||||
$incomes = [];
|
||||
$expenses = [];
|
||||
$sums = [];
|
||||
$return = [];
|
||||
|
||||
// collect income of user using the new group collector.
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setRange($start, $end)
|
||||
// set page to retrieve
|
||||
->setPage($this->parameters->get('page'))
|
||||
// set types of transactions to return.
|
||||
->setTypes([TransactionType::DEPOSIT]);
|
||||
|
||||
$set = $collector->getExtractedJournals();
|
||||
/** @var array $transactionJournal */
|
||||
foreach ($set as $transactionJournal) {
|
||||
|
||||
$currencyId = (int)$transactionJournal['currency_id'];
|
||||
$incomes[$currencyId] = $incomes[$currencyId] ?? '0';
|
||||
$incomes[$currencyId] = bcadd($incomes[$currencyId], bcmul($transactionJournal['amount'], '-1'));
|
||||
$sums[$currencyId] = $sums[$currencyId] ?? '0';
|
||||
$sums[$currencyId] = bcadd($sums[$currencyId], bcmul($transactionJournal['amount'], '-1'));
|
||||
}
|
||||
|
||||
// collect expenses of user using the new group collector.
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setRange($start, $end)
|
||||
// set page to retrieve
|
||||
->setPage($this->parameters->get('page'))
|
||||
// set types of transactions to return.
|
||||
->setTypes([TransactionType::WITHDRAWAL]);
|
||||
|
||||
|
||||
$set = $collector->getExtractedJournals();
|
||||
|
||||
/** @var array $transactionJournal */
|
||||
foreach ($set as $transactionJournal) {
|
||||
$currencyId = (int)$transactionJournal['currency_id'];
|
||||
$expenses[$currencyId] = $expenses[$currencyId] ?? '0';
|
||||
$expenses[$currencyId] = bcadd($expenses[$currencyId], $transactionJournal['amount']);
|
||||
$sums[$currencyId] = $sums[$currencyId] ?? '0';
|
||||
$sums[$currencyId] = bcadd($sums[$currencyId], $transactionJournal['amount']);
|
||||
}
|
||||
|
||||
// format amounts:
|
||||
$keys = array_keys($sums);
|
||||
foreach ($keys as $currencyId) {
|
||||
$currency = $this->currencyRepos->findNull($currencyId);
|
||||
if (null === $currency) {
|
||||
continue;
|
||||
}
|
||||
// create objects for big array.
|
||||
$return[] = [
|
||||
'key' => sprintf('balance-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => round($sums[$currencyId] ?? 0, $currency->decimal_places),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatAnything($currency, $sums[$currencyId] ?? '0', false),
|
||||
'local_icon' => 'balance-scale',
|
||||
'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false) .
|
||||
' + ' . app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false),
|
||||
];
|
||||
$return[] = [
|
||||
'key' => sprintf('spent-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => round($expenses[$currencyId] ?? 0, $currency->decimal_places),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false),
|
||||
'local_icon' => 'balance-scale',
|
||||
'sub_title' => '',
|
||||
];
|
||||
$return[] = [
|
||||
'key' => sprintf('earned-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => round($incomes[$currencyId] ?? 0, $currency->decimal_places),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false),
|
||||
'local_icon' => 'balance-scale',
|
||||
'sub_title' => '',
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getBillInformation(Carbon $start, Carbon $end): array
|
||||
{
|
||||
/*
|
||||
* Since both this method and the chart use the exact same data, we can suffice
|
||||
* with calling the one method in the bill repository that will get this amount.
|
||||
*/
|
||||
$paidAmount = $this->billRepository->getBillsPaidInRangePerCurrency($start, $end);
|
||||
$unpaidAmount = $this->billRepository->getBillsUnpaidInRangePerCurrency($start, $end);
|
||||
$return = [];
|
||||
foreach ($paidAmount as $currencyId => $amount) {
|
||||
$amount = bcmul($amount, '-1');
|
||||
$currency = $this->currencyRepos->findNull((int)$currencyId);
|
||||
if (null === $currency) {
|
||||
continue;
|
||||
}
|
||||
$return[] = [
|
||||
'key' => sprintf('bills-paid-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_bill_paid_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => round($amount, $currency->decimal_places),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatAnything($currency, $amount, false),
|
||||
'local_icon' => 'check',
|
||||
'sub_title' => '',
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($unpaidAmount as $currencyId => $amount) {
|
||||
$amount = bcmul($amount, '-1');
|
||||
$currency = $this->currencyRepos->findNull((int)$currencyId);
|
||||
if (null === $currency) {
|
||||
continue;
|
||||
}
|
||||
$return[] = [
|
||||
'key' => sprintf('bills-unpaid-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_bill_unpaid_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => round($amount, $currency->decimal_places),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatAnything($currency, $amount, false),
|
||||
'local_icon' => 'calendar-o',
|
||||
'sub_title' => '',
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getLeftToSpendInfo(Carbon $start, Carbon $end): array
|
||||
{
|
||||
$return = [];
|
||||
$today = new Carbon;
|
||||
$available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end);
|
||||
$budgets = $this->budgetRepository->getActiveBudgets();
|
||||
$spentInfo = $this->opsRepository->spentInPeriodMc($budgets, new Collection, $start, $end);
|
||||
foreach ($available as $currencyId => $amount) {
|
||||
$currency = $this->currencyRepos->findNull($currencyId);
|
||||
if (null === $currency) {
|
||||
continue;
|
||||
}
|
||||
$spentInCurrency = (string)$this->findInSpentArray($spentInfo, $currency);
|
||||
$leftToSpend = bcadd($amount, $spentInCurrency);
|
||||
|
||||
$days = $today->diffInDays($end) + 1;
|
||||
$perDay = '0';
|
||||
if (0 !== $days && bccomp($leftToSpend, '0') > -1) {
|
||||
$perDay = bcdiv($leftToSpend, (string)$days);
|
||||
}
|
||||
|
||||
$return[] = [
|
||||
'key' => sprintf('left-to-spend-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => round($leftToSpend, $currency->decimal_places),
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatAnything($currency, $leftToSpend, false),
|
||||
'local_icon' => 'money',
|
||||
'sub_title' => (string)trans('firefly.box_spend_per_day', ['amount' => app('amount')->formatAnything($currency, $perDay, false)]),
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getNetWorthInfo(Carbon $start, Carbon $end): array
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$date = Carbon::now()->startOfDay();
|
||||
|
||||
|
||||
// start and end in the future? use $end
|
||||
if ($this->notInDateRange($date, $start, $end)) {
|
||||
/** @var Carbon $date */
|
||||
$date = session('end', Carbon::now()->endOfMonth());
|
||||
}
|
||||
|
||||
/** @var NetWorthInterface $netWorthHelper */
|
||||
$netWorthHelper = app(NetWorthInterface::class);
|
||||
$netWorthHelper->setUser($user);
|
||||
$allAccounts = $this->accountRepository->getActiveAccountsByType([AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE]);
|
||||
|
||||
// filter list on preference of being included.
|
||||
$filtered = $allAccounts->filter(
|
||||
function (Account $account) {
|
||||
$includeNetWorth = $this->accountRepository->getMetaValue($account, 'include_net_worth');
|
||||
|
||||
return null === $includeNetWorth ? true : '1' === $includeNetWorth;
|
||||
}
|
||||
);
|
||||
|
||||
$netWorthSet = $netWorthHelper->getNetWorthByCurrency($filtered, $date);
|
||||
$return = [];
|
||||
foreach ($netWorthSet as $data) {
|
||||
/** @var TransactionCurrency $currency */
|
||||
$currency = $data['currency'];
|
||||
$amount = round($data['balance'], $currency->decimal_places);
|
||||
if (0.0 === $amount) {
|
||||
continue;
|
||||
}
|
||||
// return stuff
|
||||
$return[] = [
|
||||
'key' => sprintf('net-worth-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_net_worth_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => $amount,
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatAnything($currency, $data['balance'], false),
|
||||
'local_icon' => 'line-chart',
|
||||
'sub_title' => '',
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
}
|
||||
307
app/Api/V1/Controllers/TagController.php
Normal file
307
app/Api/V1/Controllers/TagController.php
Normal file
@@ -0,0 +1,307 @@
|
||||
<?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 Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Requests\DateRequest;
|
||||
use FireflyIII\Api\V1\Requests\TagRequest;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\TagTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
/**
|
||||
* Class TagController
|
||||
*/
|
||||
class TagController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
|
||||
/** @var TagRepositoryInterface The tag repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* TagController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
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);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function cloud(DateRequest $request): JsonResponse
|
||||
{
|
||||
// parameters for boxes:
|
||||
$dates = $request->getAll();
|
||||
$start = $dates['start'];
|
||||
$end = $dates['end'];
|
||||
|
||||
// get all tags:
|
||||
$tags = $this->repository->get();
|
||||
$cloud = $this->getTagCloud($tags, $start, $end);
|
||||
|
||||
return response()->json($cloud);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the resource.
|
||||
*
|
||||
* @param Tag $tag
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(Tag $tag): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($tag);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
// 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());
|
||||
|
||||
/** @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 Tag $tag
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Tag $tag): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
/** @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 = $this->getManager();
|
||||
/** @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
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
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 = $this->getManager();
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// filter on tag.
|
||||
->setTag($tag)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
// set page size:
|
||||
->setLimit($pageSize)
|
||||
// set page to retrieve
|
||||
->setPage($this->parameters->get('page'))
|
||||
// set types of transactions to return.
|
||||
->setTypes($types);
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = $this->getManager();
|
||||
/** @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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $cloud
|
||||
* @param float $min
|
||||
* @param float $max
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function analyseTagCloud(array $cloud, float $min, float $max): array
|
||||
{
|
||||
foreach (array_keys($cloud['tags']) as $index) {
|
||||
$cloud['tags'][$index]['relative'] = round($cloud['tags'][$index]['size'] / $max, 4);
|
||||
}
|
||||
$cloud['min'] = $min;
|
||||
$cloud['max'] = $max;
|
||||
|
||||
return $cloud;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $tags
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getTagCloud(Collection $tags, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$min = null;
|
||||
$max = 0;
|
||||
$cloud = [
|
||||
'tags' => [],
|
||||
];
|
||||
/** @var Tag $tag */
|
||||
foreach ($tags as $tag) {
|
||||
$earned = (float)$this->repository->earnedInPeriod($tag, $start, $end);
|
||||
$spent = (float)$this->repository->spentInPeriod($tag, $start, $end);
|
||||
$size = ($spent * -1) + $earned;
|
||||
$min = $min ?? $size;
|
||||
if ($size > 0) {
|
||||
$max = $size > $max ? $size : $max;
|
||||
$cloud['tags'][] = [
|
||||
'tag' => $tag->tag,
|
||||
'id' => $tag->id,
|
||||
'size' => $size,
|
||||
];
|
||||
}
|
||||
}
|
||||
$cloud = $this->analyseTagCloud($cloud, $min, $max);
|
||||
|
||||
return $cloud;
|
||||
}
|
||||
}
|
||||
@@ -24,37 +24,47 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\TransactionRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
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\Api\V1\Requests\TransactionStoreRequest;
|
||||
use FireflyIII\Api\V1\Requests\TransactionUpdateRequest;
|
||||
use FireflyIII\Events\StoredTransactionGroup;
|
||||
use FireflyIII\Events\UpdatedTransactionGroup;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Journal\JournalAPIRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankEventTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Log;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class TransactionController
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class TransactionController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
|
||||
/** @var TransactionGroupRepositoryInterface Group repository. */
|
||||
private $groupRepository;
|
||||
/** @var JournalAPIRepositoryInterface Journal API repos */
|
||||
private $journalAPIRepository;
|
||||
/** @var JournalRepositoryInterface The journal repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* TransactionController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -64,9 +74,12 @@ class TransactionController extends Controller
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var JournalRepositoryInterface repository */
|
||||
$this->repository = app(JournalRepositoryInterface::class);
|
||||
$this->repository = app(JournalRepositoryInterface::class);
|
||||
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
|
||||
$this->journalAPIRepository = app(JournalAPIRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->groupRepository->setUser($admin);
|
||||
$this->journalAPIRepository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -74,16 +87,52 @@ class TransactionController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \FireflyIII\Models\Transaction $transaction
|
||||
* @param TransactionJournal $transactionJournal
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(Transaction $transaction): JsonResponse
|
||||
public function attachments(TransactionJournal $transactionJournal): JsonResponse
|
||||
{
|
||||
$journal = $transaction->transactionJournal;
|
||||
$this->repository->destroy($journal);
|
||||
$manager = $this->getManager();
|
||||
$attachments = $this->journalAPIRepository->getAttachments($transactionJournal);
|
||||
|
||||
/** @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.
|
||||
*
|
||||
* @param TransactionGroup $transactionGroup
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(TransactionGroup $transactionGroup): JsonResponse
|
||||
{
|
||||
$this->repository->destroyGroup($transactionGroup);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param TransactionJournal $transactionJournal
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function deleteJournal(TransactionJournal $transactionJournal): JsonResponse
|
||||
{
|
||||
$this->repository->destroyJournal($transactionJournal);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
@@ -94,6 +143,7 @@ class TransactionController extends Controller
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
@@ -101,77 +151,95 @@ class TransactionController extends Controller
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$this->parameters->set('type', $type);
|
||||
|
||||
$types = $this->mapTypes($this->parameters->get('type'));
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||
$manager = $this->getManager();
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
/** @var TransactionCollectorInterface $collector */
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser($admin);
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setAllAssetAccounts();
|
||||
|
||||
if (\in_array(TransactionType::TRANSFER, $types, true)) {
|
||||
$collector->removeFilter(InternalTransferFilter::class);
|
||||
}
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
// set page size:
|
||||
->setLimit($pageSize)
|
||||
// set page to retrieve
|
||||
->setPage($this->parameters->get('page'))
|
||||
// set types of transactions to return.
|
||||
->setTypes($types);
|
||||
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedTransactions();
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $transactionJournal
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function piggyBankEvents(TransactionJournal $transactionJournal): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
$events = $this->journalAPIRepository->getPiggyBankEvents($transactionJournal);
|
||||
|
||||
/** @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
|
||||
* @param TransactionGroup $transactionGroup
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Transaction $transaction, string $include = null): JsonResponse
|
||||
public function show(TransactionGroup $transactionGroup): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// filter on transaction group.
|
||||
->setTransactionGroup($transactionGroup)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation();
|
||||
|
||||
// add include parameter:
|
||||
$include = $include ?? '';
|
||||
$include = $request->get('include') ?? $include;
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
// collect transactions using the journal collector
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser(auth()->user());
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
// filter on specific journals.
|
||||
$collector->setJournals(new Collection([$transaction->transactionJournal]));
|
||||
|
||||
// add filter to remove transactions:
|
||||
$transactionType = $transaction->transactionJournal->transactionType->type;
|
||||
if ($transactionType === TransactionType::WITHDRAWAL) {
|
||||
$collector->addFilter(PositiveAmountFilter::class);
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
if (null === $selectedGroup) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
if (!($transactionType === TransactionType::WITHDRAWAL)) {
|
||||
$collector->addFilter(NegativeAmountFilter::class);
|
||||
}
|
||||
|
||||
$transactions = $collector->getTransactions();
|
||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -179,45 +247,43 @@ class TransactionController extends Controller
|
||||
/**
|
||||
* Store a new transaction.
|
||||
*
|
||||
* @param TransactionRequest $request
|
||||
* @param TransactionStoreRequest $request
|
||||
*
|
||||
* @param JournalRepositoryInterface $repository
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(TransactionRequest $request, JournalRepositoryInterface $repository): JsonResponse
|
||||
public function store(TransactionStoreRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$data['user'] = auth()->user()->id;
|
||||
$journal = $repository->store($data);
|
||||
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
Log::channel('audit')
|
||||
->info('Store new transaction over API.', $data);
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
$transactionGroup = $this->groupRepository->store($data);
|
||||
|
||||
// collect transactions using the journal collector
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser(auth()->user());
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
// filter on specific journals.
|
||||
$collector->setJournals(new Collection([$journal]));
|
||||
event(new StoredTransactionGroup($transactionGroup));
|
||||
|
||||
// add filter to remove transactions:
|
||||
$transactionType = $journal->transactionType->type;
|
||||
if ($transactionType === TransactionType::WITHDRAWAL) {
|
||||
$collector->addFilter(PositiveAmountFilter::class);
|
||||
$manager = $this->getManager();
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// filter on transaction group.
|
||||
->setTransactionGroup($transactionGroup)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation();
|
||||
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
if (null === $selectedGroup) {
|
||||
throw new NotFoundHttpException(); // @codeCoverageIgnore
|
||||
}
|
||||
if (!($transactionType === TransactionType::WITHDRAWAL)) {
|
||||
$collector->addFilter(NegativeAmountFilter::class);
|
||||
}
|
||||
|
||||
$transactions = $collector->getTransactions();
|
||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
@@ -226,82 +292,42 @@ class TransactionController extends Controller
|
||||
/**
|
||||
* Update a transaction.
|
||||
*
|
||||
* @param TransactionRequest $request
|
||||
* @param JournalRepositoryInterface $repository
|
||||
* @param Transaction $transaction
|
||||
* @param TransactionUpdateRequest $request
|
||||
* @param TransactionGroup $transactionGroup
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(TransactionRequest $request, JournalRepositoryInterface $repository, Transaction $transaction): JsonResponse
|
||||
public function update(TransactionUpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$data['user'] = auth()->user()->id;
|
||||
$journal = $repository->update($transaction->transactionJournal, $data);
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
Log::debug('Now in update routine.');
|
||||
$data = $request->getAll();
|
||||
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
event(new UpdatedTransactionGroup($transactionGroup));
|
||||
|
||||
// needs a lot of extra data to match the journal collector. Or just expand that one.
|
||||
// collect transactions using the journal collector
|
||||
$collector = app(TransactionCollectorInterface::class);
|
||||
$collector->setUser(auth()->user());
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
// filter on specific journals.
|
||||
$collector->setJournals(new Collection([$journal]));
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// filter on transaction group.
|
||||
->setTransactionGroup($transactionGroup)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation();
|
||||
|
||||
// add filter to remove transactions:
|
||||
$transactionType = $journal->transactionType->type;
|
||||
if ($transactionType === TransactionType::WITHDRAWAL) {
|
||||
$collector->addFilter(PositiveAmountFilter::class);
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
if (null === $selectedGroup) {
|
||||
throw new NotFoundHttpException(); // @codeCoverageIgnore
|
||||
}
|
||||
if (!($transactionType === TransactionType::WITHDRAWAL)) {
|
||||
$collector->addFilter(NegativeAmountFilter::class);
|
||||
}
|
||||
|
||||
$transactions = $collector->getTransactions();
|
||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($selectedGroup, $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,36 +23,37 @@ 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\Transformers\JournalLinkTransformer;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\TransactionLinkTransformer;
|
||||
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 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 */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* JournalLinkController constructor.
|
||||
* TransactionLinkController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -79,6 +80,7 @@ class JournalLinkController extends Controller
|
||||
* @param TransactionJournalLink $link
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(TransactionJournalLink $link): JsonResponse
|
||||
{
|
||||
@@ -92,34 +94,34 @@ class JournalLinkController extends Controller
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse]
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
$manager = $this->getManager();
|
||||
// read type from URI
|
||||
$name = $request->get('name') ?? null;
|
||||
$name = $request->get('name');
|
||||
|
||||
// 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');
|
||||
@@ -129,22 +131,20 @@ class JournalLinkController extends Controller
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionJournalLink $journalLink
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, TransactionJournalLink $journalLink): JsonResponse
|
||||
public function show(TransactionJournalLink $journalLink): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$manager = $this->getManager();
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
/** @var TransactionLinkTransformer $transformer */
|
||||
$transformer = app(TransactionLinkTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'journal_links');
|
||||
$resource = new Item($journalLink, $transformer, 'transaction_links');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
@@ -153,19 +153,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);
|
||||
|
||||
$manager = $this->getManager();
|
||||
$data = $request->getAll();
|
||||
$inward = $this->journalRepository->findNull($data['inward_id'] ?? 0);
|
||||
$outward = $this->journalRepository->findNull($data['outward_id'] ?? 0);
|
||||
@@ -175,30 +170,28 @@ class JournalLinkController extends Controller
|
||||
$data['direction'] = 'inward';
|
||||
|
||||
$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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = $this->getManager();
|
||||
$data = $request->getAll();
|
||||
$data['inward'] = $this->journalRepository->findNull($data['inward_id'] ?? 0);
|
||||
$data['outward'] = $this->journalRepository->findNull($data['outward_id'] ?? 0);
|
||||
@@ -208,7 +201,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');
|
||||
|
||||
@@ -24,25 +24,22 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\UserRequest;
|
||||
use FireflyIII\Api\V1\Requests\UserStoreRequest;
|
||||
use FireflyIII\Api\V1\Requests\UserUpdateRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Transformers\UserTransformer;
|
||||
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 UserController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class UserController extends Controller
|
||||
{
|
||||
@@ -52,6 +49,8 @@ class UserController extends Controller
|
||||
|
||||
/**
|
||||
* UserController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -69,16 +68,17 @@ class UserController extends Controller
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \FireflyIII\User $user
|
||||
* @param User $user
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(User $user): JsonResponse
|
||||
{
|
||||
/** @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);
|
||||
@@ -89,19 +89,14 @@ class UserController extends Controller
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
// user preferences
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// make manager
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$manager = $this->getManager();
|
||||
|
||||
// build collection
|
||||
$collection = $this->repository->all();
|
||||
@@ -113,7 +108,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');
|
||||
@@ -122,24 +121,21 @@ class UserController extends Controller
|
||||
/**
|
||||
* Show a single user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param User $user
|
||||
* @param User $user
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, User $user): JsonResponse
|
||||
public function show(User $user): JsonResponse
|
||||
{
|
||||
// make manager
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$manager = $this->getManager();
|
||||
// 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');
|
||||
}
|
||||
@@ -147,26 +143,23 @@ class UserController extends Controller
|
||||
/**
|
||||
* Store a new user.
|
||||
*
|
||||
* @param UserRequest $request
|
||||
* @param UserStoreRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(UserRequest $request): JsonResponse
|
||||
public function store(UserStoreRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$user = $this->repository->store($data);
|
||||
|
||||
// make manager
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
$data = $request->getAll();
|
||||
$user = $this->repository->store($data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
// 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');
|
||||
}
|
||||
@@ -174,27 +167,22 @@ class UserController extends Controller
|
||||
/**
|
||||
* Update a user.
|
||||
*
|
||||
* @param UserRequest $request
|
||||
* @param User $user
|
||||
* @param UserUpdateRequest $request
|
||||
* @param User $user
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(UserRequest $request, User $user): JsonResponse
|
||||
public function update(UserUpdateRequest $request, User $user): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$user = $this->repository->update($user, $data);
|
||||
|
||||
// make manager
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
$data = $request->getAll();
|
||||
$user = $this->repository->update($user, $data);
|
||||
$manager = $this->getManager();
|
||||
// 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');
|
||||
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AccountRequest.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;
|
||||
/**
|
||||
* Class AccountRequest
|
||||
*/
|
||||
class AccountRequest 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 = [
|
||||
'name' => $this->string('name'),
|
||||
'active' => $this->boolean('active'),
|
||||
'include_net_worth' => $this->boolean('include_net_worth'),
|
||||
'accountType' => $this->string('type'),
|
||||
'account_type_id' => null,
|
||||
'currency_id' => $this->integer('currency_id'),
|
||||
'currency_code' => $this->string('currency_code'),
|
||||
'virtualBalance' => $this->string('virtual_balance'),
|
||||
'iban' => $this->string('iban'),
|
||||
'BIC' => $this->string('bic'),
|
||||
'accountNumber' => $this->string('account_number'),
|
||||
'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'),
|
||||
'notes' => $this->string('notes'),
|
||||
'interest' => $this->string('interest'),
|
||||
'interest_period' => $this->string('interest_period'),
|
||||
];
|
||||
// new fields for liabilities
|
||||
// 'liability_type' => $this->string('liability_type'),
|
||||
// 'liability_start_date' => $this->date('liability_start_date'),
|
||||
|
||||
|
||||
//];
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$accountRoles = implode(',', config('firefly.accountRoles'));
|
||||
$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',
|
||||
'include_net_worth' => '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',
|
||||
// required fields for liabilities:
|
||||
'liability_type' => 'required_if:type,liability|in:loan,debt,mortgage,credit card',
|
||||
'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',
|
||||
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
$account = $this->route()->parameter('account');
|
||||
$rules['name'] .= ':' . $account->id;
|
||||
$rules['account_number'] .= ':' . $account->id;
|
||||
$rules['type'] = 'in:' . $types;
|
||||
break;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
84
app/Api/V1/Requests/AccountStoreRequest.php
Normal file
84
app/Api/V1/Requests/AccountStoreRequest.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AccountStoreRequest.php
|
||||
* Copyright (c) 2019 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\Rules\IsBoolean;
|
||||
|
||||
/**
|
||||
* Class AccountStoreRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AccountStoreRequest extends Request
|
||||
{
|
||||
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$accountRoles = implode(',', config('firefly.accountRoles'));
|
||||
$types = implode(',', array_keys(config('firefly.subTitlesByIdentifier')));
|
||||
$ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes')));
|
||||
$rules = [
|
||||
'name' => 'required|min:1|uniqueAccountForUser',
|
||||
'type' => 'required|' . sprintf('in:%s', $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' => sprintf('in:%s|required_if:type,asset', $accountRoles),
|
||||
'credit_card_type' => sprintf('in:%s|required_if:account_role,ccAsset', $ccPaymentTypes),
|
||||
'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',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
131
app/Api/V1/Requests/AccountUpdateRequest.php
Normal file
131
app/Api/V1/Requests/AccountUpdateRequest.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AccountUpdateRequest.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\Rules\IsBoolean;
|
||||
|
||||
/**
|
||||
* Class AccountUpdateRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AccountUpdateRequest extends Request
|
||||
{
|
||||
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getUpdateData(): array
|
||||
{
|
||||
$active = null;
|
||||
$includeNetWorth = null;
|
||||
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->nullableString('name'),
|
||||
'active' => $active,
|
||||
'include_net_worth' => $includeNetWorth,
|
||||
'account_type' => $this->nullableString('type'),
|
||||
'account_type_id' => null,
|
||||
'currency_id' => $this->nullableInteger('currency_id'),
|
||||
'currency_code' => $this->nullableString('currency_code'),
|
||||
'virtual_balance' => $this->nullableString('virtual_balance'),
|
||||
'iban' => $this->nullableString('iban'),
|
||||
'BIC' => $this->nullableString('bic'),
|
||||
'account_number' => $this->nullableString('account_number'),
|
||||
'account_role' => $this->nullableString('account_role'),
|
||||
'opening_balance' => $this->nullableString('opening_balance'),
|
||||
'opening_balance_date' => $this->date('opening_balance_date'),
|
||||
'cc_type' => $this->nullableString('credit_card_type'),
|
||||
'cc_Monthly_payment_date' => $this->nullableString('monthly_payment_date'),
|
||||
'notes' => $this->nullableString('notes'),
|
||||
'interest' => $this->nullableString('interest'),
|
||||
'interest_period' => $this->nullableString('interest_period'),
|
||||
];
|
||||
|
||||
if ('liability' === $data['account_type']) {
|
||||
$data['opening_balance'] = bcmul($this->nullableString('liability_amount'), '-1');
|
||||
$data['opening_balance_date'] = $this->date('liability_start_date');
|
||||
$data['account_type'] = $this->nullableString('liability_type');
|
||||
$data['account_type_id'] = null;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$account = $this->route()->parameter('account');
|
||||
$accountRoles = implode(',', config('firefly.accountRoles'));
|
||||
$types = implode(',', array_keys(config('firefly.subTitlesByIdentifier')));
|
||||
$ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes')));
|
||||
$rules = [
|
||||
'name' => sprintf('min:1|uniqueAccountForUser:%d', $account->id),
|
||||
'type' => sprintf('in:%s', $types),
|
||||
'iban' => 'iban|nullable',
|
||||
'bic' => 'bic|nullable',
|
||||
'account_number' => sprintf('between:1,255|nullable|uniqueAccountNumberForUser:%d', $account->id),
|
||||
'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' => sprintf('in:%s|required_if:type,asset', $accountRoles),
|
||||
'credit_card_type' => sprintf('in:%s|required_if:account_role,ccAsset', $ccPaymentTypes),
|
||||
'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',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/**
|
||||
* AttachmentRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
* AttachmentStoreRequest.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@@ -29,9 +29,11 @@ use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Rules\IsValidAttachmentModel;
|
||||
|
||||
/**
|
||||
* Class AttachmentRequest
|
||||
* Class AttachmentStoreRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AttachmentRequest extends Request
|
||||
class AttachmentStoreRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
@@ -68,30 +70,21 @@ class AttachmentRequest extends Request
|
||||
public function rules(): array
|
||||
{
|
||||
$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),
|
||||
]
|
||||
);
|
||||
$model = $this->string('model');
|
||||
$rules = [
|
||||
|
||||
return [
|
||||
'filename' => 'required|between:1,255',
|
||||
'title' => 'between:1,255',
|
||||
'notes' => 'between:1,65000',
|
||||
'model' => sprintf('required|in:%s', $models),
|
||||
'model_id' => ['required', 'numeric', new IsValidAttachmentModel($model)],
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
unset($rules['model'], $rules['model_id']);
|
||||
$rules['filename'] = 'between:1,255';
|
||||
break;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
73
app/Api/V1/Requests/AttachmentUpdateRequest.php
Normal file
73
app/Api/V1/Requests/AttachmentUpdateRequest.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* AttachmentUpdateRequest.php
|
||||
* Copyright (c) 2019 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;
|
||||
|
||||
/**
|
||||
* ClassAttachmentUpdateRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AttachmentUpdateRequest 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 [
|
||||
'filename' => $this->string('filename'),
|
||||
'title' => $this->string('title'),
|
||||
'notes' => $this->string('notes'),
|
||||
'model' => $this->string('model'),
|
||||
'model_id' => $this->integer('model_id'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'filename' => 'between:1,255',
|
||||
'title' => 'between:1,255',
|
||||
'notes' => 'between:1,65000',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,8 @@ namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
/**
|
||||
* Class AvailableBudgetRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AvailableBudgetRequest extends Request
|
||||
{
|
||||
@@ -50,8 +52,8 @@ class AvailableBudgetRequest extends Request
|
||||
'currency_id' => $this->integer('currency_id'),
|
||||
'currency_code' => $this->string('currency_code'),
|
||||
'amount' => $this->string('amount'),
|
||||
'start_date' => $this->date('start_date'),
|
||||
'end_date' => $this->date('end_date'),
|
||||
'start' => $this->date('start'),
|
||||
'end' => $this->date('end'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -63,11 +65,11 @@ class AvailableBudgetRequest extends Request
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'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',
|
||||
'amount' => 'required|numeric|more:0',
|
||||
'start_date' => 'required|date|before:end_date',
|
||||
'end_date' => 'required|date|after:start_date',
|
||||
'start' => 'required|date|before:end',
|
||||
'end' => 'required|date|after:start',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
|
||||
@@ -24,10 +24,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
* Class BillRequest
|
||||
*
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class BillRequest extends Request
|
||||
{
|
||||
@@ -50,6 +55,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 +69,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'),
|
||||
];
|
||||
|
||||
@@ -71,6 +80,7 @@ class BillRequest extends Request
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
@@ -78,13 +88,12 @@ 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',
|
||||
'active' => [new IsBoolean],
|
||||
'notes' => 'between:1,65536',
|
||||
];
|
||||
switch ($this->method()) {
|
||||
@@ -103,14 +112,14 @@ class BillRequest extends Request
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
static function (Validator $validator) {
|
||||
$data = $validator->getData();
|
||||
$min = (float)($data['amount_min'] ?? 0);
|
||||
$max = (float)($data['amount_max'] ?? 0);
|
||||
|
||||
@@ -23,9 +23,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
|
||||
/**
|
||||
* Class BudgetLimitRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class BudgetLimitRequest extends Request
|
||||
{
|
||||
@@ -48,10 +50,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 +67,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 +82,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,9 +24,13 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
|
||||
/**
|
||||
* Class BudgetRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class BudgetRequest extends Request
|
||||
{
|
||||
@@ -48,9 +52,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 +73,7 @@ class BudgetRequest extends Request
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name',
|
||||
'active' => 'required|boolean',
|
||||
'active' => [new IsBoolean],
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
|
||||
@@ -27,6 +27,9 @@ use FireflyIII\Models\Category;
|
||||
|
||||
/**
|
||||
* Class CategoryRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class CategoryRequest extends Request
|
||||
{
|
||||
@@ -49,8 +52,7 @@ class CategoryRequest extends Request
|
||||
public function getAll(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
'active' => $this->boolean('active'),
|
||||
'name' => $this->string('name'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -62,8 +64,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:
|
||||
|
||||
85
app/Api/V1/Requests/ConfigurationRequest.php
Normal file
85
app/Api/V1/Requests/ConfigurationRequest.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ConfigurationRequest.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\Rules\IsBoolean;
|
||||
|
||||
/**
|
||||
* Class ConfigurationRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ConfigurationRequest 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
|
||||
{
|
||||
$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
|
||||
{
|
||||
$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,9 +23,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
|
||||
|
||||
/**
|
||||
* Class CurrencyRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class CurrencyRequest extends Request
|
||||
{
|
||||
@@ -47,12 +52,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,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -66,9 +81,11 @@ class CurrencyRequest extends Request
|
||||
$rules = [
|
||||
'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',
|
||||
'symbol' => 'required|between:1,8|unique:transaction_currencies,symbol',
|
||||
'decimal_places' => 'between:0,20|numeric|min:0|max:20',
|
||||
'enabled' => [new IsBoolean()],
|
||||
'default' => [new IsBoolean()],
|
||||
|
||||
];
|
||||
|
||||
switch ($this->method()) {
|
||||
@@ -76,10 +93,10 @@ 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;
|
||||
$rules['code'] = 'required|between:3,3|unique:transaction_currencies,code,' . $currency->id;
|
||||
$rules['symbol'] = 'required|between:1,8|unique:transaction_currencies,symbol,' . $currency->id;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ReconciliationUpdateRequest.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* DateRequest.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@@ -18,54 +19,53 @@
|
||||
* 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\Http\Requests;
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
|
||||
/**
|
||||
* Class ReconciliationUpdateRequest.
|
||||
* Request class for end points that require date parameters.
|
||||
*
|
||||
* Class DateRequest
|
||||
*/
|
||||
class ReconciliationUpdateRequest extends Request
|
||||
class DateRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Verify the request.
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow logged in users
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns and validates the data required to update a reconciliation.
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getJournalData(): array
|
||||
public function getAll(): array
|
||||
{
|
||||
$data = [
|
||||
'tags' => explode(',', $this->string('tags')),
|
||||
'amount' => $this->string('amount'),
|
||||
'category' => $this->string('category'),
|
||||
return [
|
||||
'start' => $this->date('start'),
|
||||
'end' => $this->date('end'),
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rules for this request.
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'amount' => 'numeric|required',
|
||||
'category' => 'between:1,255|nullable',
|
||||
return [
|
||||
'start' => 'required|date',
|
||||
'end' => 'required|date|after:start',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,9 @@ use Illuminate\Validation\Rule;
|
||||
/**
|
||||
*
|
||||
* Class LinkTypeRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class LinkTypeRequest extends Request
|
||||
{
|
||||
|
||||
@@ -25,10 +25,15 @@ namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Rules\IsAssetAccountId;
|
||||
use FireflyIII\Rules\LessThanPiggyTarget;
|
||||
use FireflyIII\Rules\ZeroOrMore;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class PiggyBankRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class PiggyBankRequest extends Request
|
||||
{
|
||||
@@ -55,9 +60,9 @@ class PiggyBankRequest extends Request
|
||||
'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'),
|
||||
'notes' => $this->string('notes'),
|
||||
'startdate' => $this->date('start_date'),
|
||||
'targetdate' => $this->date('target_date'),
|
||||
'notes' => $this->string('notes'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -70,11 +75,9 @@ class PiggyBankRequest extends Request
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required|between:1,255|uniquePiggyBankForUser',
|
||||
'account_id' => ['required', 'belongsToUser:accounts', new IsAssetAccountId],
|
||||
'target_amount' => 'required|numeric|more:0',
|
||||
'current_amount' => 'numeric|more:0|lte:target_amount',
|
||||
'current_amount' => ['numeric', new ZeroOrMore, 'lte:target_amount'],
|
||||
'start_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable|after:start_date',
|
||||
'notes' => 'max:65000',
|
||||
];
|
||||
|
||||
@@ -84,8 +87,11 @@ class PiggyBankRequest extends Request
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
/** @var PiggyBank $piggyBank */
|
||||
$piggyBank = $this->route()->parameter('piggyBank');
|
||||
$rules['name'] = 'required|between:1,255|uniquePiggyBankForUser:' . $piggyBank->id;
|
||||
$piggyBank = $this->route()->parameter('piggyBank');
|
||||
$rules['name'] = 'between:1,255|uniquePiggyBankForUser:' . $piggyBank->id;
|
||||
$rules['account_id'] = ['belongsToUser:accounts', new IsAssetAccountId];
|
||||
$rules['target_amount'] = 'numeric|more:0';
|
||||
$rules['current_amount'] = ['numeric', new ZeroOrMore, new LessThanPiggyTarget];
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace FireflyIII\Api\V1\Requests;
|
||||
/**
|
||||
*
|
||||
* Class PreferenceRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class PreferenceRequest extends Request
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/**
|
||||
* RecurrenceRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
* RecurrenceStoreRequest.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@@ -25,14 +25,15 @@ 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;
|
||||
|
||||
/**
|
||||
* Class RecurrenceRequest
|
||||
* Class RecurrenceStoreRequest
|
||||
*/
|
||||
class RecurrenceRequest extends Request
|
||||
class RecurrenceStoreRequest extends Request
|
||||
{
|
||||
use RecurrenceValidation, TransactionValidation;
|
||||
|
||||
@@ -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,13 +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'),
|
||||
],
|
||||
'meta' => [
|
||||
'piggy_bank_id' => $this->integer('piggy_bank_id'),
|
||||
'piggy_bank_name' => $this->string('piggy_bank_name'),
|
||||
'tags' => explode(',', $this->string('tags')),
|
||||
'apply_rules' => $applyRules,
|
||||
'active' => $active,
|
||||
],
|
||||
'transactions' => $this->getTransactionData(),
|
||||
'repetitions' => $this->getRepetitionData(),
|
||||
@@ -90,37 +94,44 @@ class RecurrenceRequest extends Request
|
||||
'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')),
|
||||
'first_date' => 'required|date',
|
||||
'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],
|
||||
'transactions.*.category_name' => 'between:1,255|nullable',
|
||||
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser],
|
||||
'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',
|
||||
|
||||
// new and updated fields:
|
||||
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser],
|
||||
'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.*.piggy_bank_id' => ['numeric', 'mustExist:piggy_banks,id', new BelongsUser],
|
||||
'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser],
|
||||
'transactions.*.tags' => 'between:1,64000',
|
||||
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -128,7 +139,7 @@ class RecurrenceRequest extends Request
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
$this->validateOneTransaction($validator);
|
||||
$this->validateOneRecurrenceTransaction($validator);
|
||||
$this->validateOneRepetition($validator);
|
||||
$this->validateRecurrenceRepetition($validator);
|
||||
$this->validateRepetitionMoment($validator);
|
||||
@@ -138,7 +149,6 @@ class RecurrenceRequest extends Request
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the repetition data as it is found in the submitted data.
|
||||
*
|
||||
@@ -150,6 +160,9 @@ class RecurrenceRequest extends Request
|
||||
// repetition data:
|
||||
/** @var array $repetitions */
|
||||
$repetitions = $this->get('repetitions');
|
||||
if (null === $repetitions) {
|
||||
return [];
|
||||
}
|
||||
/** @var array $repetition */
|
||||
foreach ($repetitions as $repetition) {
|
||||
$return[] = [
|
||||
@@ -168,8 +181,6 @@ class RecurrenceRequest extends Request
|
||||
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
|
||||
*
|
||||
* @return array
|
||||
* @SuppressWarnings(PHPMD.NPathComplexity)
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
@@ -177,6 +188,9 @@ class RecurrenceRequest extends Request
|
||||
// transaction data:
|
||||
/** @var array $transactions */
|
||||
$transactions = $this->get('transactions');
|
||||
if (null === $transactions) {
|
||||
return [];
|
||||
}
|
||||
/** @var array $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$return[] = [
|
||||
@@ -186,15 +200,21 @@ class RecurrenceRequest extends Request
|
||||
'foreign_amount' => $transaction['foreign_amount'] ?? null,
|
||||
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
|
||||
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
|
||||
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
|
||||
'budget_name' => $transaction['budget_name'] ?? null,
|
||||
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
|
||||
'category_name' => $transaction['category_name'] ?? null,
|
||||
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
|
||||
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
|
||||
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
|
||||
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
|
||||
'description' => $transaction['description'],
|
||||
'type' => $this->string('type'),
|
||||
|
||||
// new and updated fields:
|
||||
'piggy_bank_id' => isset($transaction['piggy_bank_id']) ? (int)$transaction['piggy_bank_id'] : null,
|
||||
'piggy_bank_name' => $transaction['piggy_bank_name'] ?? null,
|
||||
'tags' => $transaction['tags'] ?? [],
|
||||
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
|
||||
'budget_name' => $transaction['budget_name'] ?? null,
|
||||
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
|
||||
'category_name' => $transaction['category_name'] ?? null,
|
||||
];
|
||||
}
|
||||
|
||||
225
app/Api/V1/Requests/RecurrenceUpdateRequest.php
Normal file
225
app/Api/V1/Requests/RecurrenceUpdateRequest.php
Normal file
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
/**
|
||||
* RecurrenceUpdateRequest.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\Recurrence;
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Validation\RecurrenceValidation;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
* Class RecurrenceUpdateRequest
|
||||
*/
|
||||
class RecurrenceUpdateRequest extends Request
|
||||
{
|
||||
use RecurrenceValidation, TransactionValidation;
|
||||
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$active = null;
|
||||
$applyRules = null;
|
||||
if (null !== $this->get('active')) {
|
||||
$active = $this->boolean('active');
|
||||
}
|
||||
if (null !== $this->get('apply_rules')) {
|
||||
$applyRules = $this->boolean('apply_rules');
|
||||
}
|
||||
$return = [
|
||||
'recurrence' => [
|
||||
'type' => $this->nullableString('type'),
|
||||
'title' => $this->nullableString('title'),
|
||||
'description' => $this->nullableString('description'),
|
||||
'first_date' => $this->date('first_date'),
|
||||
'notes' => $this->nullableString('notes'),
|
||||
'repeat_until' => $this->date('repeat_until'),
|
||||
'nr_of_repetitions' => $this->nullableInteger('nr_of_repetitions'),
|
||||
'apply_rules' => $applyRules,
|
||||
'active' => $active,
|
||||
],
|
||||
'transactions' => $this->getTransactionData(),
|
||||
'repetitions' => $this->getRepetitionData(),
|
||||
];
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
/** @var Recurrence $recurrence */
|
||||
$recurrence = $this->route()->parameter('recurrence');
|
||||
|
||||
return [
|
||||
'type' => 'in:withdrawal,transfer,deposit',
|
||||
'title' => sprintf('between:1,255|uniqueObjectForUser:recurrences,title,%d', $recurrence->id),
|
||||
'description' => 'between:1,65000',
|
||||
'first_date' => 'date',
|
||||
'apply_rules' => [new IsBoolean],
|
||||
'active' => [new IsBoolean],
|
||||
'repeat_until' => 'date',
|
||||
'nr_of_repetitions' => 'numeric|between:1,31',
|
||||
'repetitions.*.type' => '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.*.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.*.source_id' => ['numeric', 'nullable', new BelongsUser],
|
||||
'transactions.*.source_name' => 'between:1,255|nullable',
|
||||
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser],
|
||||
'transactions.*.destination_name' => 'between:1,255|nullable',
|
||||
|
||||
// new and updated fields:
|
||||
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser],
|
||||
'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.*.piggy_bank_id' => ['numeric', 'mustExist:piggy_banks,id', new BelongsUser],
|
||||
'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser],
|
||||
'transactions.*.tags' => 'between:1,64000',
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
$this->validateOneRecurrenceTransactionUpdate($validator);
|
||||
$this->validateOneRepetitionUpdate($validator);
|
||||
$this->validateRecurrenceRepetition($validator);
|
||||
$this->validateRepetitionMoment($validator);
|
||||
$this->validateForeignCurrencyInformation($validator);
|
||||
$this->valUpdateAccountInfo($validator);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the repetition data as it is found in the submitted data.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
private function getRepetitionData(): ?array
|
||||
{
|
||||
$return = [];
|
||||
// repetition data:
|
||||
/** @var array $repetitions */
|
||||
$repetitions = $this->get('repetitions');
|
||||
if (null === $repetitions) {
|
||||
return null;
|
||||
}
|
||||
/** @var array $repetition */
|
||||
foreach ($repetitions as $repetition) {
|
||||
$return[] = [
|
||||
'type' => $repetition['type'],
|
||||
'moment' => $repetition['moment'],
|
||||
'skip' => (int)$repetition['skip'],
|
||||
'weekend' => (int)$repetition['weekend'],
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
|
||||
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
private function getTransactionData(): ?array
|
||||
{
|
||||
$return = [];
|
||||
// transaction data:
|
||||
/** @var array $transactions */
|
||||
$transactions = $this->get('transactions');
|
||||
if (null === $transactions) {
|
||||
return null;
|
||||
}
|
||||
/** @var array $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$return[] = [
|
||||
'amount' => $transaction['amount'],
|
||||
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
|
||||
'currency_code' => $transaction['currency_code'] ?? null,
|
||||
'foreign_amount' => $transaction['foreign_amount'] ?? null,
|
||||
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
|
||||
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
|
||||
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
|
||||
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
|
||||
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
|
||||
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
|
||||
'description' => $transaction['description'],
|
||||
'type' => $this->string('type'),
|
||||
|
||||
// new and updated fields:
|
||||
'piggy_bank_id' => isset($transaction['piggy_bank_id']) ? (int)$transaction['piggy_bank_id'] : null,
|
||||
'piggy_bank_name' => $transaction['piggy_bank_name'] ?? null,
|
||||
'tags' => $transaction['tags'] ?? [],
|
||||
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
|
||||
'budget_name' => $transaction['budget_name'] ?? null,
|
||||
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
|
||||
'category_name' => $transaction['category_name'] ?? null,
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
@@ -31,9 +31,52 @@ use FireflyIII\Http\Requests\Request as FireflyIIIRequest;
|
||||
*
|
||||
* Technically speaking this class does not have to be extended like this but who knows what the future brings.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.NumberOfChildren)
|
||||
*/
|
||||
class Request extends FireflyIIIRequest
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAllAccountData(): 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' => $active,
|
||||
'include_net_worth' => $includeNetWorth,
|
||||
'account_type' => $this->string('type'),
|
||||
'account_type_id' => null,
|
||||
'currency_id' => $this->integer('currency_id'),
|
||||
'currency_code' => $this->string('currency_code'),
|
||||
'virtual_balance' => $this->string('virtual_balance'),
|
||||
'iban' => $this->string('iban'),
|
||||
'BIC' => $this->string('bic'),
|
||||
'account_number' => $this->string('account_number'),
|
||||
'account_role' => $this->string('account_role'),
|
||||
'opening_balance' => $this->string('opening_balance'),
|
||||
'opening_balance_date' => $this->date('opening_balance_date'),
|
||||
'cc_type' => $this->string('credit_card_type'),
|
||||
'cc_Monthly_payment_date' => $this->string('monthly_payment_date'),
|
||||
'notes' => $this->string('notes'),
|
||||
'interest' => $this->string('interest'),
|
||||
'interest_period' => $this->string('interest_period'),
|
||||
];
|
||||
|
||||
if ('liability' === $data['account_type']) {
|
||||
$data['opening_balance'] = bcmul($this->string('liability_amount'), '-1');
|
||||
$data['opening_balance_date'] = $this->date('liability_start_date');
|
||||
$data['account_type'] = $this->string('liability_type');
|
||||
$data['account_type_id'] = null;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,13 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* Class RuleGroupRequest
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class RuleGroupRequest extends Request
|
||||
{
|
||||
@@ -50,10 +52,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 +75,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:
|
||||
|
||||
150
app/Api/V1/Requests/RuleGroupTestRequest.php
Normal file
150
app/Api/V1/Requests/RuleGroupTestRequest.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RuleGroupTestRequest.php
|
||||
* Copyright (c) 2019 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 Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RuleGroupTestRequest
|
||||
*/
|
||||
class RuleGroupTestRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTestParameters(): array
|
||||
{
|
||||
$return = [
|
||||
'page' => $this->getPage(),
|
||||
'start_date' => $this->getDate('start_date'),
|
||||
'end_date' => $this->getDate('end_date'),
|
||||
'search_limit' => $this->getSearchLimit(),
|
||||
'trigger_limit' => $this->getTriggerLimit(),
|
||||
'accounts' => $this->getAccounts(),
|
||||
];
|
||||
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
private function getAccounts(): Collection
|
||||
{
|
||||
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts'));
|
||||
$accounts = new Collection;
|
||||
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
|
||||
foreach ($accountList as $accountId) {
|
||||
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
|
||||
$account = $accountRepository->findNull((int)$accountId);
|
||||
if ($this->validAccount($account)) {
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
|
||||
$accounts->push($account);
|
||||
}
|
||||
}
|
||||
|
||||
return $accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
private function getDate(string $field): ?Carbon
|
||||
{
|
||||
/** @var Carbon $result */
|
||||
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private function getPage(): int
|
||||
{
|
||||
return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private function getSearchLimit(): int
|
||||
{
|
||||
return 0 === (int)$this->query('search_limit') ? (int)config('firefly.test-triggers.limit') : (int)$this->query('search_limit');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private function getTriggerLimit(): int
|
||||
{
|
||||
return 0 === (int)$this->query('triggered_limit') ? (int)config('firefly.test-triggers.range') : (int)$this->query('triggered_limit');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account|null $account
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function validAccount(?Account $account): bool
|
||||
{
|
||||
return null !== $account && AccountType::ASSET === $account->accountType->type;
|
||||
}
|
||||
|
||||
}
|
||||
125
app/Api/V1/Requests/RuleGroupTriggerRequest.php
Normal file
125
app/Api/V1/Requests/RuleGroupTriggerRequest.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RuleGroupTriggerRequest.php
|
||||
* Copyright (c) 2019 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 Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RuleGroupTriggerRequest
|
||||
*/
|
||||
class RuleGroupTriggerRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTriggerParameters(): array
|
||||
{
|
||||
$return = [
|
||||
'start_date' => $this->getDate('start_date'),
|
||||
'end_date' => $this->getDate('end_date'),
|
||||
'accounts' => $this->getAccounts(),
|
||||
];
|
||||
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'start_date' => 'required|date',
|
||||
'end_date' => 'required|date|after:start_date',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
private function getAccounts(): Collection
|
||||
{
|
||||
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts'));
|
||||
$accounts = new Collection;
|
||||
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
|
||||
foreach ($accountList as $accountId) {
|
||||
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
|
||||
$account = $accountRepository->findNull((int)$accountId);
|
||||
if ($this->validAccount($account)) {
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
|
||||
$accounts->push($account);
|
||||
}
|
||||
}
|
||||
|
||||
return $accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
private function getDate(string $field): ?Carbon
|
||||
{
|
||||
/** @var Carbon $result */
|
||||
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account|null $account
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function validAccount(?Account $account): bool
|
||||
{
|
||||
return null !== $account && AccountType::ASSET === $account->accountType->type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* RuleRequest.php
|
||||
* RuleStoreRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
@@ -23,13 +23,16 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use Illuminate\Validation\Validator;
|
||||
use function is_array;
|
||||
|
||||
|
||||
/**
|
||||
* Class RuleRequest
|
||||
* Class RuleStoreRequest
|
||||
*
|
||||
*/
|
||||
class RuleRequest extends Request
|
||||
class RuleStoreRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
@@ -49,17 +52,30 @@ 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' => $this->getRuleTriggers(),
|
||||
'rule_actions' => $this->getRuleActions(),
|
||||
'strict' => $strict,
|
||||
'stop_processing' => $stopProcessing,
|
||||
'active' => $active,
|
||||
'triggers' => $this->getRuleTriggers(),
|
||||
'actions' => $this->getRuleActions(),
|
||||
];
|
||||
|
||||
return $data;
|
||||
@@ -75,24 +91,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_actions.*.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;
|
||||
@@ -101,7 +119,7 @@ class RuleRequest extends Request
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -122,10 +140,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'));
|
||||
}
|
||||
}
|
||||
@@ -137,10 +155,10 @@ 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 trigger
|
||||
if (0 === count($triggers)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
|
||||
}
|
||||
}
|
||||
@@ -150,14 +168,15 @@ class RuleRequest extends Request
|
||||
*/
|
||||
private function getRuleActions(): array
|
||||
{
|
||||
$actions = $this->get('rule_actions');
|
||||
$actions = $this->get('actions');
|
||||
$return = [];
|
||||
if (\is_array($actions)) {
|
||||
if (is_array($actions)) {
|
||||
foreach ($actions as $action) {
|
||||
$return[] = [
|
||||
'name' => $action['name'],
|
||||
'type' => $action['type'],
|
||||
'value' => $action['value'],
|
||||
'stop_processing' => 1 === (int)($action['stop-processing'] ?? '0'),
|
||||
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
|
||||
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -170,14 +189,15 @@ class RuleRequest extends Request
|
||||
*/
|
||||
private function getRuleTriggers(): array
|
||||
{
|
||||
$triggers = $this->get('rule_triggers');
|
||||
$triggers = $this->get('triggers');
|
||||
$return = [];
|
||||
if (\is_array($triggers)) {
|
||||
if (is_array($triggers)) {
|
||||
foreach ($triggers as $trigger) {
|
||||
$return[] = [
|
||||
'name' => $trigger['name'],
|
||||
'type' => $trigger['type'],
|
||||
'value' => $trigger['value'],
|
||||
'stop_processing' => 1 === (int)($trigger['stop-processing'] ?? '0'),
|
||||
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'false')),
|
||||
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
150
app/Api/V1/Requests/RuleTestRequest.php
Normal file
150
app/Api/V1/Requests/RuleTestRequest.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RuleTestRequest.php
|
||||
* Copyright (c) 2019 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 Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RuleTestRequest
|
||||
*/
|
||||
class RuleTestRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTestParameters(): array
|
||||
{
|
||||
$return = [
|
||||
'page' => $this->getPage(),
|
||||
'start_date' => $this->getDate('start_date'),
|
||||
'end_date' => $this->getDate('end_date'),
|
||||
'search_limit' => $this->getSearchLimit(),
|
||||
'trigger_limit' => $this->getTriggerLimit(),
|
||||
'accounts' => $this->getAccounts(),
|
||||
];
|
||||
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
private function getAccounts(): Collection
|
||||
{
|
||||
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts'));
|
||||
$accounts = new Collection;
|
||||
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
|
||||
foreach ($accountList as $accountId) {
|
||||
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
|
||||
$account = $accountRepository->findNull((int)$accountId);
|
||||
if ($this->validAccount($account)) {
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
|
||||
$accounts->push($account);
|
||||
}
|
||||
}
|
||||
|
||||
return $accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
private function getDate(string $field): ?Carbon
|
||||
{
|
||||
/** @var Carbon $result */
|
||||
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private function getPage(): int
|
||||
{
|
||||
return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private function getSearchLimit(): int
|
||||
{
|
||||
return 0 === (int)$this->query('search_limit') ? (int)config('firefly.test-triggers.limit') : (int)$this->query('search_limit');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private function getTriggerLimit(): int
|
||||
{
|
||||
return 0 === (int)$this->query('triggered_limit') ? (int)config('firefly.test-triggers.range') : (int)$this->query('triggered_limit');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account|null $account
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function validAccount(?Account $account): bool
|
||||
{
|
||||
return null !== $account && AccountType::ASSET === $account->accountType->type;
|
||||
}
|
||||
|
||||
}
|
||||
124
app/Api/V1/Requests/RuleTriggerRequest.php
Normal file
124
app/Api/V1/Requests/RuleTriggerRequest.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RuleTriggerRequest.php
|
||||
* Copyright (c) 2019 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 Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RuleTriggerRequest
|
||||
*/
|
||||
class RuleTriggerRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTriggerParameters(): array
|
||||
{
|
||||
$return = [
|
||||
'start_date' => $this->getDate('start_date'),
|
||||
'end_date' => $this->getDate('end_date'),
|
||||
'accounts' => $this->getAccounts(),
|
||||
];
|
||||
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'start_date' => 'required|date',
|
||||
'end_date' => 'required|date|after:start_date',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
private function getAccounts(): Collection
|
||||
{
|
||||
$accountList = '' === (string)$this->query('accounts') ? [] : explode(',', $this->query('accounts'));
|
||||
$accounts = new Collection;
|
||||
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
|
||||
foreach ($accountList as $accountId) {
|
||||
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
|
||||
$account = $accountRepository->findNull((int)$accountId);
|
||||
if ($this->validAccount($account)) {
|
||||
/** @noinspection NullPointerExceptionInspection */
|
||||
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
|
||||
$accounts->push($account);
|
||||
}
|
||||
}
|
||||
|
||||
return $accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
private function getDate(string $field): ?Carbon
|
||||
{
|
||||
/** @var Carbon $result */
|
||||
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account|null $account
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function validAccount(?Account $account): bool
|
||||
{
|
||||
return null !== $account && AccountType::ASSET === $account->accountType->type;
|
||||
}
|
||||
|
||||
}
|
||||
214
app/Api/V1/Requests/RuleUpdateRequest.php
Normal file
214
app/Api/V1/Requests/RuleUpdateRequest.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
/**
|
||||
* RuleUpdateRequest.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\Rules\IsBoolean;
|
||||
use Illuminate\Validation\Validator;
|
||||
use function is_array;
|
||||
|
||||
|
||||
/**
|
||||
* Class RuleUpdateRequest
|
||||
*
|
||||
*/
|
||||
class RuleUpdateRequest 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
|
||||
{
|
||||
$strict = null;
|
||||
$active = null;
|
||||
$stopProcessing = null;
|
||||
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->nullableString('title'),
|
||||
'description' => $this->nullableString('description'),
|
||||
'rule_group_id' => $this->nullableInteger('rule_group_id'),
|
||||
'rule_group_title' => $this->nullableString('rule_group_title'),
|
||||
'trigger' => $this->nullableString('trigger'),
|
||||
'strict' => $strict,
|
||||
'stop_processing' => $stopProcessing,
|
||||
'active' => $active,
|
||||
'triggers' => $this->getRuleTriggers(),
|
||||
'actions' => $this->getRuleActions(),
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$validTriggers = array_keys(config('firefly.rule-triggers'));
|
||||
$validActions = array_keys(config('firefly.rule-actions'));
|
||||
$rule = $this->route()->parameter('rule');
|
||||
|
||||
// some triggers and actions require text:
|
||||
$contextTriggers = implode(',', config('firefly.context-rule-triggers'));
|
||||
$contextActions = implode(',', config('firefly.context-rule-actions'));
|
||||
$rules = [
|
||||
'title' => sprintf('between:1,100|uniqueObjectForUser:rules,title,%d', $rule->id),
|
||||
'description' => 'between:1,5000|nullable',
|
||||
'rule_group_id' => 'belongsToUser:rule_groups',
|
||||
'rule_group_title' => 'nullable|between:1,255|belongsToUser:rule_groups,title',
|
||||
'trigger' => '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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
$this->atLeastOneTrigger($validator);
|
||||
$this->atLeastOneAction($validator);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no repetitions in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function atLeastOneAction(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$actions = $data['actions'] ?? null;
|
||||
// need at least one action
|
||||
if (is_array($actions) && 0 === count($actions)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no repetitions in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function atLeastOneTrigger(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$triggers = $data['triggers'] ?? null;
|
||||
// need at least one trigger
|
||||
if (is_array($triggers) && 0 === count($triggers)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null
|
||||
*/
|
||||
private function getRuleActions(): ?array
|
||||
{
|
||||
if (!$this->has('actions')) {
|
||||
return null;
|
||||
}
|
||||
$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|null
|
||||
*/
|
||||
private function getRuleTriggers(): ?array
|
||||
{
|
||||
if (!$this->has('triggers')) {
|
||||
return null;
|
||||
}
|
||||
$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;
|
||||
}
|
||||
}
|
||||
97
app/Api/V1/Requests/TagRequest.php
Normal file
97
app/Api/V1/Requests/TagRequest.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?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
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
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:-180|max:180|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;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* JournalLinkRequest.php
|
||||
* TransactionLinkRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
@@ -25,13 +25,14 @@ namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class JournalLinkRequest
|
||||
* Class TransactionLinkRequest
|
||||
*/
|
||||
class JournalLinkRequest extends Request
|
||||
class TransactionLinkRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
@@ -71,8 +72,8 @@ class JournalLinkRequest extends Request
|
||||
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',
|
||||
'outward_id' => 'required|belongsToUser:transaction_journals,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',
|
||||
];
|
||||
}
|
||||
@@ -80,7 +81,7 @@ class JournalLinkRequest extends Request
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -98,13 +99,15 @@ class JournalLinkRequest extends Request
|
||||
*/
|
||||
private function validateExistingLink(Validator $validator): void
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
/** @var LinkTypeRepositoryInterface $repository */
|
||||
$repository = app(LinkTypeRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$repository->setUser($user);
|
||||
|
||||
/** @var JournalRepositoryInterface $journalRepos */
|
||||
$journalRepos = app(JournalRepositoryInterface::class);
|
||||
$journalRepos->setUser(auth()->user());
|
||||
$journalRepos->setUser($user);
|
||||
|
||||
$data = $validator->getData();
|
||||
$inwardId = (int)($data['inward_id'] ?? 0);
|
||||
@@ -124,8 +127,12 @@ class JournalLinkRequest extends Request
|
||||
}
|
||||
|
||||
if ($repository->findLink($inward, $outward)) {
|
||||
$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.');
|
||||
// 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.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,196 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* TransactionRequest.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\Rules\BelongsUser;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
|
||||
/**
|
||||
* Class TransactionRequest
|
||||
*/
|
||||
class TransactionRequest extends Request
|
||||
{
|
||||
use TransactionValidation;
|
||||
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data. Is pretty complex because of all the ??-statements.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.NPathComplexity)
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$data = [
|
||||
'type' => $this->string('type'),
|
||||
'date' => $this->date('date'),
|
||||
'description' => $this->string('description'),
|
||||
'piggy_bank_id' => $this->integer('piggy_bank_id'),
|
||||
'piggy_bank_name' => $this->string('piggy_bank_name'),
|
||||
'bill_id' => $this->integer('bill_id'),
|
||||
'bill_name' => $this->string('bill_name'),
|
||||
'tags' => explode(',', $this->string('tags')),
|
||||
'interest_date' => $this->date('interest_date'),
|
||||
'book_date' => $this->date('book_date'),
|
||||
'process_date' => $this->date('process_date'),
|
||||
'due_date' => $this->date('due_date'),
|
||||
'payment_date' => $this->date('payment_date'),
|
||||
'invoice_date' => $this->date('invoice_date'),
|
||||
'internal_reference' => $this->string('internal_reference'),
|
||||
'notes' => $this->string('notes'),
|
||||
'transactions' => $this->getTransactionData(),
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
// basic fields for journal:
|
||||
'type' => 'required|in:withdrawal,deposit,transfer',
|
||||
'date' => 'required|date',
|
||||
'description' => 'between:1,255',
|
||||
'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],
|
||||
'bill_name' => ['between:1,255', 'nullable', new BelongsUser],
|
||||
'tags' => 'between:1,255',
|
||||
|
||||
// then, custom fields for journal
|
||||
'interest_date' => 'date|nullable',
|
||||
'book_date' => 'date|nullable',
|
||||
'process_date' => 'date|nullable',
|
||||
'due_date' => 'date|nullable',
|
||||
'payment_date' => 'date|nullable',
|
||||
'invoice_date' => 'date|nullable',
|
||||
'internal_reference' => 'min:1,max:255|nullable',
|
||||
'notes' => 'min:1,max:50000|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.*.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',
|
||||
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser],
|
||||
'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.*.source_id' => ['numeric', 'nullable', new BelongsUser],
|
||||
'transactions.*.source_name' => 'between:1,255|nullable',
|
||||
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser],
|
||||
'transactions.*.destination_name' => 'between:1,255|nullable',
|
||||
];
|
||||
|
||||
if ('PUT' === $this->method()) {
|
||||
unset($rules['type'], $rules['piggy_bank_id'], $rules['piggy_bank_name']);
|
||||
}
|
||||
|
||||
return $rules;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
$this->validateOneTransaction($validator);
|
||||
$this->validateDescriptions($validator);
|
||||
$this->validateJournalDescription($validator);
|
||||
$this->validateSplitDescriptions($validator);
|
||||
$this->validateForeignCurrencyInformation($validator);
|
||||
$this->validateAccountInformation($validator);
|
||||
$this->validateSplitAccounts($validator);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get transaction data.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.NPathComplexity)
|
||||
* @return array
|
||||
*/
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
$return = [];
|
||||
foreach ($this->get('transactions') as $index => $transaction) {
|
||||
$return[] = [
|
||||
'description' => $transaction['description'] ?? null,
|
||||
'amount' => $transaction['amount'],
|
||||
'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null,
|
||||
'currency_code' => $transaction['currency_code'] ?? null,
|
||||
'foreign_amount' => $transaction['foreign_amount'] ?? null,
|
||||
'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null,
|
||||
'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null,
|
||||
'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null,
|
||||
'budget_name' => $transaction['budget_name'] ?? null,
|
||||
'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null,
|
||||
'category_name' => $transaction['category_name'] ?? null,
|
||||
'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null,
|
||||
'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null,
|
||||
'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null,
|
||||
'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null,
|
||||
'reconciled' => $transaction['reconciled'] ?? false,
|
||||
'identifier' => $index,
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
278
app/Api/V1/Requests/TransactionStoreRequest.php
Normal file
278
app/Api/V1/Requests/TransactionStoreRequest.php
Normal file
@@ -0,0 +1,278 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* TransactionStoreRequest.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\Rules\BelongsUser;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsDateOrTime;
|
||||
use FireflyIII\Support\NullArrayObject;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
|
||||
/**
|
||||
* Class TransactionStoreRequest
|
||||
*/
|
||||
class TransactionStoreRequest extends Request
|
||||
{
|
||||
use TransactionValidation;
|
||||
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data. Is pretty complex because of all the ??-statements.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$data = [
|
||||
'group_title' => $this->string('group_title'),
|
||||
'transactions' => $this->getTransactionData(),
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
// basic fields for group:
|
||||
'group_title' => 'between:1,255',
|
||||
|
||||
// transaction rules (in array for splits):
|
||||
'transactions.*.type' => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation',
|
||||
'transactions.*.date' => ['required', new IsDateOrTime],
|
||||
'transactions.*.order' => 'numeric|min:0',
|
||||
|
||||
// currency info
|
||||
'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',
|
||||
|
||||
// amount
|
||||
'transactions.*.amount' => 'required|numeric|more:0',
|
||||
'transactions.*.foreign_amount' => 'numeric|more:0',
|
||||
|
||||
// description
|
||||
'transactions.*.description' => 'nullable|between:1,255',
|
||||
|
||||
// source of transaction
|
||||
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser],
|
||||
'transactions.*.source_name' => 'between:1,255|nullable',
|
||||
|
||||
// destination of transaction
|
||||
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser],
|
||||
'transactions.*.destination_name' => 'between:1,255|nullable',
|
||||
|
||||
// budget, category, bill and piggy
|
||||
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser],
|
||||
'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.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser],
|
||||
'transactions.*.bill_name' => ['between:1,255', 'nullable', new BelongsUser],
|
||||
'transactions.*.piggy_bank_id' => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser],
|
||||
'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser],
|
||||
|
||||
// other interesting fields
|
||||
'transactions.*.reconciled' => [new IsBoolean],
|
||||
'transactions.*.notes' => 'min:1,max:50000|nullable',
|
||||
'transactions.*.tags' => 'between:1,255',
|
||||
|
||||
// meta info fields
|
||||
'transactions.*.internal_reference' => 'min:1,max:255|nullable',
|
||||
'transactions.*.external_id' => 'min:1,max:255|nullable',
|
||||
'transactions.*.recurrence_id' => 'min:1,max:255|nullable',
|
||||
'transactions.*.bunq_payment_id' => 'min:1,max:255|nullable',
|
||||
|
||||
// SEPA fields:
|
||||
'transactions.*.sepa_cc' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_ct_op' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_ct_id' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_db' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_country' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_ep' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_ci' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_batch_id' => 'min:1,max:255|nullable',
|
||||
|
||||
// dates
|
||||
'transactions.*.interest_date' => 'date|nullable',
|
||||
'transactions.*.book_date' => 'date|nullable',
|
||||
'transactions.*.process_date' => 'date|nullable',
|
||||
'transactions.*.due_date' => 'date|nullable',
|
||||
'transactions.*.payment_date' => 'date|nullable',
|
||||
'transactions.*.invoice_date' => 'date|nullable',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
// must submit at least one transaction.
|
||||
$this->validateOneTransaction($validator);
|
||||
|
||||
// all journals must have a description
|
||||
$this->validateDescriptions($validator);
|
||||
|
||||
// all transaction types must be equal:
|
||||
$this->validateTransactionTypes($validator);
|
||||
|
||||
// validate foreign currency info
|
||||
$this->validateForeignCurrencyInformation($validator);
|
||||
|
||||
// validate all account info
|
||||
$this->validateAccountInformation($validator);
|
||||
|
||||
// validate source/destination is equal, depending on the transaction journal type.
|
||||
$this->validateEqualAccounts($validator);
|
||||
|
||||
// the group must have a description if > 1 journal.
|
||||
$this->validateGroupDescription($validator);
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get transaction data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
$return = [];
|
||||
/**
|
||||
* @var int $index
|
||||
* @var array $transaction
|
||||
*/
|
||||
foreach ($this->get('transactions') as $index => $transaction) {
|
||||
$object = new NullArrayObject($transaction);
|
||||
$return[] = [
|
||||
'type' => $this->stringFromValue($object['type']),
|
||||
'date' => $this->dateFromValue($object['date']),
|
||||
'order' => $this->integerFromValue((string)$object['order']),
|
||||
|
||||
'currency_id' => $this->integerFromValue($object['currency_id']),
|
||||
'currency_code' => $this->stringFromValue($object['currency_code']),
|
||||
|
||||
// foreign currency info:
|
||||
'foreign_currency_id' => $this->integerFromValue((string)$object['foreign_currency_id']),
|
||||
'foreign_currency_code' => $this->stringFromValue($object['foreign_currency_code']),
|
||||
|
||||
// amount and foreign amount. Cannot be 0.
|
||||
'amount' => $this->stringFromValue((string)$object['amount']),
|
||||
'foreign_amount' => $this->stringFromValue((string)$object['foreign_amount']),
|
||||
|
||||
// description.
|
||||
'description' => $this->stringFromValue($object['description']),
|
||||
|
||||
// source of transaction. If everything is null, assume cash account.
|
||||
'source_id' => $this->integerFromValue((string)$object['source_id']),
|
||||
'source_name' => $this->stringFromValue($object['source_name']),
|
||||
|
||||
// destination of transaction. If everything is null, assume cash account.
|
||||
'destination_id' => $this->integerFromValue((string)$object['destination_id']),
|
||||
'destination_name' => $this->stringFromValue($object['destination_name']),
|
||||
|
||||
// budget info
|
||||
'budget_id' => $this->integerFromValue((string)$object['budget_id']),
|
||||
'budget_name' => $this->stringFromValue($object['budget_name']),
|
||||
|
||||
// category info
|
||||
'category_id' => $this->integerFromValue((string)$object['category_id']),
|
||||
'category_name' => $this->stringFromValue($object['category_name']),
|
||||
|
||||
// journal bill reference. Optional. Will only work for withdrawals
|
||||
'bill_id' => $this->integerFromValue((string)$object['bill_id']),
|
||||
'bill_name' => $this->stringFromValue($object['bill_name']),
|
||||
|
||||
// piggy bank reference. Optional. Will only work for transfers
|
||||
'piggy_bank_id' => $this->integerFromValue((string)$object['piggy_bank_id']),
|
||||
'piggy_bank_name' => $this->stringFromValue($object['piggy_bank_name']),
|
||||
|
||||
// some other interesting properties
|
||||
'reconciled' => $this->convertBoolean((string)$object['reconciled']),
|
||||
'notes' => $this->stringFromValue($object['notes']),
|
||||
'tags' => $this->arrayFromValue($object['tags']),
|
||||
|
||||
// all custom fields:
|
||||
'internal_reference' => $this->stringFromValue($object['internal_reference']),
|
||||
'external_id' => $this->stringFromValue($object['external_id']),
|
||||
'original_source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')),
|
||||
'recurrence_id' => $this->integerFromValue($object['recurrence_id']),
|
||||
'bunq_payment_id' => $this->stringFromValue($object['bunq_payment_id']),
|
||||
|
||||
'sepa_cc' => $this->stringFromValue($object['sepa_cc']),
|
||||
'sepa_ct_op' => $this->stringFromValue($object['sepa_ct_op']),
|
||||
'sepa_ct_id' => $this->stringFromValue($object['sepa_ct_id']),
|
||||
'sepa_db' => $this->stringFromValue($object['sepa_db']),
|
||||
'sepa_country' => $this->stringFromValue($object['sepa_country']),
|
||||
'sepa_ep' => $this->stringFromValue($object['sepa_ep']),
|
||||
'sepa_ci' => $this->stringFromValue($object['sepa_ci']),
|
||||
'sepa_batch_id' => $this->stringFromValue($object['sepa_batch_id']),
|
||||
|
||||
|
||||
// custom date fields. Must be Carbon objects. Presence is optional.
|
||||
'interest_date' => $this->dateFromValue($object['interest_date']),
|
||||
'book_date' => $this->dateFromValue($object['book_date']),
|
||||
'process_date' => $this->dateFromValue($object['process_date']),
|
||||
'due_date' => $this->dateFromValue($object['due_date']),
|
||||
'payment_date' => $this->dateFromValue($object['payment_date']),
|
||||
'invoice_date' => $this->dateFromValue($object['invoice_date']),
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
323
app/Api/V1/Requests/TransactionUpdateRequest.php
Normal file
323
app/Api/V1/Requests/TransactionUpdateRequest.php
Normal file
@@ -0,0 +1,323 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* TransactionUpdateRequest.php
|
||||
* Copyright (c) 2019 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\TransactionGroup;
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsDateOrTime;
|
||||
use FireflyIII\Validation\TransactionValidation;
|
||||
use Illuminate\Validation\Validator;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class TransactionUpdateRequest
|
||||
*/
|
||||
class TransactionUpdateRequest extends Request
|
||||
{
|
||||
use TransactionValidation;
|
||||
|
||||
/** @var array Array values. */
|
||||
private $arrayFields;
|
||||
/** @var array Boolean values. */
|
||||
private $booleanFields;
|
||||
/** @var array Fields that contain date values. */
|
||||
private $dateFields;
|
||||
/** @var array Fields that contain integer values. */
|
||||
private $integerFields;
|
||||
/** @var array Fields that contain string values. */
|
||||
private $stringFields;
|
||||
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data. Is pretty complex because of all the ??-statements.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$this->integerFields = [
|
||||
'order',
|
||||
'currency_id',
|
||||
'foreign_currency_id',
|
||||
'transaction_journal_id',
|
||||
'source_id',
|
||||
'destination_id',
|
||||
'budget_id',
|
||||
'category_id',
|
||||
'bill_id',
|
||||
'recurrence_id',
|
||||
];
|
||||
|
||||
$this->dateFields = [
|
||||
'date',
|
||||
'interest_date',
|
||||
'book_date',
|
||||
'process_date',
|
||||
'due_date',
|
||||
'payment_date',
|
||||
'invoice_date',
|
||||
];
|
||||
|
||||
$this->stringFields = [
|
||||
'type',
|
||||
'currency_code',
|
||||
'foreign_currency_code',
|
||||
'amount',
|
||||
'foreign_amount',
|
||||
'description',
|
||||
'source_name',
|
||||
'destination_name',
|
||||
'budget_name',
|
||||
'category_name',
|
||||
'bill_name',
|
||||
'notes',
|
||||
'internal_reference',
|
||||
'external_id',
|
||||
'bunq_payment_id',
|
||||
'sepa_cc',
|
||||
'sepa_ct_op',
|
||||
'sepa_ct_id',
|
||||
'sepa_db',
|
||||
'sepa_country',
|
||||
'sepa_ep',
|
||||
'sepa_ci',
|
||||
'sepa_batch_id',
|
||||
];
|
||||
$this->booleanFields = [
|
||||
'reconciled',
|
||||
];
|
||||
|
||||
$this->arrayFields = [
|
||||
'tags',
|
||||
];
|
||||
|
||||
|
||||
$data = [
|
||||
'transactions' => $this->getTransactionData(),
|
||||
];
|
||||
if ($this->has('group_title')) {
|
||||
$data['group_title'] = $this->string('group_title');
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
// basic fields for group:
|
||||
'group_title' => 'between:1,255',
|
||||
|
||||
// transaction rules (in array for splits):
|
||||
'transactions.*.type' => 'in:withdrawal,deposit,transfer,opening-balance,reconciliation',
|
||||
'transactions.*.date' => [new IsDateOrTime],
|
||||
'transactions.*.order' => 'numeric|min:0',
|
||||
|
||||
// currency info
|
||||
'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',
|
||||
|
||||
// amount
|
||||
'transactions.*.amount' => 'numeric|more:0',
|
||||
'transactions.*.foreign_amount' => 'numeric|gte:0',
|
||||
|
||||
// description
|
||||
'transactions.*.description' => 'nullable|between:1,255',
|
||||
|
||||
// source of transaction
|
||||
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser],
|
||||
'transactions.*.source_name' => 'between:1,255|nullable',
|
||||
|
||||
// destination of transaction
|
||||
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser],
|
||||
'transactions.*.destination_name' => 'between:1,255|nullable',
|
||||
|
||||
// budget, category, bill and piggy
|
||||
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser],
|
||||
'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.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser],
|
||||
'transactions.*.bill_name' => ['between:1,255', 'nullable', new BelongsUser],
|
||||
|
||||
// other interesting fields
|
||||
'transactions.*.reconciled' => [new IsBoolean],
|
||||
'transactions.*.notes' => 'min:1,max:50000|nullable',
|
||||
'transactions.*.tags' => 'between:0,255',
|
||||
|
||||
// meta info fields
|
||||
'transactions.*.internal_reference' => 'min:1,max:255|nullable',
|
||||
'transactions.*.external_id' => 'min:1,max:255|nullable',
|
||||
'transactions.*.recurrence_id' => 'min:1,max:255|nullable',
|
||||
'transactions.*.bunq_payment_id' => 'min:1,max:255|nullable',
|
||||
|
||||
// SEPA fields:
|
||||
'transactions.*.sepa_cc' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_ct_op' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_ct_id' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_db' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_country' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_ep' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_ci' => 'min:1,max:255|nullable',
|
||||
'transactions.*.sepa_batch_id' => 'min:1,max:255|nullable',
|
||||
|
||||
// dates
|
||||
'transactions.*.interest_date' => 'date|nullable',
|
||||
'transactions.*.book_date' => 'date|nullable',
|
||||
'transactions.*.process_date' => 'date|nullable',
|
||||
'transactions.*.due_date' => 'date|nullable',
|
||||
'transactions.*.payment_date' => 'date|nullable',
|
||||
'transactions.*.invoice_date' => 'date|nullable',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
/** @var TransactionGroup $transactionGroup */
|
||||
$transactionGroup = $this->route()->parameter('transactionGroup');
|
||||
$validator->after(
|
||||
function (Validator $validator) use ($transactionGroup) {
|
||||
// must submit at least one transaction.
|
||||
$this->validateOneTransaction($validator);
|
||||
|
||||
// if more than one, verify that there are journal ID's present.
|
||||
$this->validateJournalIds($validator, $transactionGroup);
|
||||
|
||||
// all transaction types must be equal:
|
||||
$this->validateTransactionTypesForUpdate($validator);
|
||||
|
||||
// validate source/destination is equal, depending on the transaction journal type.
|
||||
$this->validateEqualAccountsForUpdate($validator, $transactionGroup);
|
||||
|
||||
// If type is set, source + destination info is mandatory.
|
||||
// Not going to do this. Not sure where the demand came from.
|
||||
|
||||
// validate that the currency fits the source and/or destination account.
|
||||
// validate all account info
|
||||
$this->validateAccountInformationUpdate($validator);
|
||||
|
||||
// The currency info must match the accounts involved.
|
||||
// Instead will ignore currency info as much as possible.
|
||||
|
||||
// TODO if the transaction_journal_id is empty, some fields are mandatory, like the amount!
|
||||
|
||||
// all journals must have a description
|
||||
//$this->validateDescriptions($validator);
|
||||
|
||||
// // validate foreign currency info
|
||||
// $this->validateForeignCurrencyInformation($validator);
|
||||
//
|
||||
|
||||
//
|
||||
// // make sure all splits have valid source + dest info
|
||||
// $this->validateSplitAccounts($validator);
|
||||
// the group must have a description if > 1 journal.
|
||||
// $this->validateGroupDescription($validator);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get transaction data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getTransactionData(): array
|
||||
{
|
||||
Log::debug('Now in getTransactionData()');
|
||||
$return = [];
|
||||
/**
|
||||
* @var int $index
|
||||
* @var array $transaction
|
||||
*/
|
||||
foreach ($this->get('transactions') as $index => $transaction) {
|
||||
// default response is to update nothing in the transaction:
|
||||
$current = [];
|
||||
|
||||
// for each field, add it to the array if a reference is present in the request:
|
||||
foreach ($this->integerFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->integerFromValue((string)$transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->stringFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->stringFromValue((string)$transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->dateFields as $fieldName) {
|
||||
Log::debug(sprintf('Now at date field %s', $fieldName));
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->dateFromValue((string)$transaction[$fieldName]);
|
||||
Log::debug(sprintf('New value: "%s"', (string)$transaction[$fieldName]));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->booleanFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->convertBoolean((string)$transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->arrayFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->arrayFromValue($transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
$return[] = $current;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* UserRequest.php
|
||||
* UserStoreRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
@@ -25,13 +25,14 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\User;
|
||||
|
||||
|
||||
/**
|
||||
* Class UserRequest
|
||||
* Class UserStoreRequest
|
||||
*/
|
||||
class UserRequest extends Request
|
||||
class UserStoreRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
@@ -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;
|
||||
@@ -80,22 +86,12 @@ class UserRequest extends Request
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'email' => 'required|email|unique:users,email,',
|
||||
'blocked' => 'required|boolean',
|
||||
return [
|
||||
'email' => 'required|email|unique:users,email',
|
||||
'blocked' => [new IsBoolean],
|
||||
'blocked_code' => 'in:email_changed',
|
||||
'role' => 'in:owner,demo',
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
$user = $this->route()->parameter('user');
|
||||
$rules['email'] = 'required|email|unique:users,email,' . $user->id;
|
||||
break;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
}
|
||||
100
app/Api/V1/Requests/UserUpdateRequest.php
Normal file
100
app/Api/V1/Requests/UserUpdateRequest.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* UserUpdateRequest.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\User\UserRepositoryInterface;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\User;
|
||||
|
||||
|
||||
/**
|
||||
* Class UserUpdateRequest
|
||||
*/
|
||||
class UserUpdateRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
$result = false;
|
||||
// Only allow authenticated users
|
||||
if (auth()->check()) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
/** @var UserRepositoryInterface $repository */
|
||||
$repository = app(UserRepositoryInterface::class);
|
||||
|
||||
if ($repository->hasRole($user, 'owner')) {
|
||||
$result = true; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$blocked = false;
|
||||
if (null !== $this->get('blocked')) {
|
||||
$blocked = $this->boolean('blocked');
|
||||
}
|
||||
$data = [
|
||||
'email' => $this->string('email'),
|
||||
'blocked' => $blocked,
|
||||
'blocked_code' => $this->string('blocked_code'),
|
||||
'role' => $this->string('role'),
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$user = $this->route()->parameter('user');
|
||||
$rules = [
|
||||
'email' => sprintf('email|unique:users,email,%d', $user->id),
|
||||
'blocked' => [new IsBoolean],
|
||||
'blocked_code' => 'in:email_changed',
|
||||
'role' => 'in:owner,demo,',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user