mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-22 20:16:22 +00:00
Compare commits
1037 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -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.
|
# 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,98 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "Now in entrypoint.sh for Firefly III"
|
||||||
|
|
||||||
# make sure the correct directories exists (suggested by @chrif):
|
# 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/app/public
|
||||||
mkdir -p $FIREFLY_PATH/storage/build
|
mkdir -p $FIREFLY_PATH/storage/build
|
||||||
mkdir -p $FIREFLY_PATH/storage/database
|
mkdir -p $FIREFLY_PATH/storage/database
|
||||||
mkdir -p $FIREFLY_PATH/storage/debugbar
|
mkdir -p $FIREFLY_PATH/storage/debugbar
|
||||||
mkdir -p $FIREFLY_PATH/storage/export
|
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/sessions
|
||||||
mkdir -p $FIREFLY_PATH/storage/framework/testing
|
mkdir -p $FIREFLY_PATH/storage/framework/testing
|
||||||
mkdir -p $FIREFLY_PATH/storage/framework/views
|
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/logs
|
||||||
mkdir -p $FIREFLY_PATH/storage/upload
|
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:
|
# make sure we own the volumes:
|
||||||
|
echo "Run chown on ${FIREFLY_PATH}/storage..."
|
||||||
chown -R www-data:www-data -R $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
|
chmod -R 775 $FIREFLY_PATH/storage
|
||||||
|
|
||||||
# remove any lingering files that may break upgrades:
|
# remove any lingering files that may break upgrades:
|
||||||
|
echo "Remove log file..."
|
||||||
rm -f $FIREFLY_PATH/storage/logs/laravel.log
|
rm -f $FIREFLY_PATH/storage/logs/laravel.log
|
||||||
|
|
||||||
cat .env.docker | envsubst > .env
|
echo "Dump auto load..."
|
||||||
composer dump-autoload
|
composer dump-autoload
|
||||||
|
echo "Discover packages..."
|
||||||
php artisan package:discover
|
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 12 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
|
||||||
|
|
||||||
|
# there are 13 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
|
||||||
|
|
||||||
|
# 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
|
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.
|
# If you're looking for performance improvements, you could install memcached.
|
||||||
CACHE_DRIVER=file
|
CACHE_DRIVER=file
|
||||||
SESSION_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 settings. Should not be necessary to change these.
|
||||||
COOKIE_PATH="/"
|
COOKIE_PATH="/"
|
||||||
COOKIE_DOMAIN=
|
COOKIE_DOMAIN=
|
||||||
@@ -74,11 +92,20 @@ SPARKPOST_SECRET=
|
|||||||
SEND_REGISTRATION_MAIL=true
|
SEND_REGISTRATION_MAIL=true
|
||||||
SEND_ERROR_MESSAGE=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.
|
# 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.
|
# Firefly III currently supports two provider for live Currency Exchange Rates:
|
||||||
# Please note that this will only work for paid fixer.io accounts because they severly limited
|
# "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.
|
# the free API up to the point where you might as well offer nothing.
|
||||||
FIXER_API_KEY=
|
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.
|
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
||||||
USE_ENCRYPTION=true
|
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.
|
# Leave the following configuration vars as is.
|
||||||
# Unless you like to tinker and know what you're doing.
|
# Unless you like to tinker and know what you're doing.
|
||||||
APP_NAME=FireflyIII
|
APP_NAME=FireflyIII
|
||||||
|
ADLDAP_CONNECTION=default
|
||||||
BROADCAST_DRIVER=log
|
BROADCAST_DRIVER=log
|
||||||
QUEUE_DRIVER=sync
|
QUEUE_DRIVER=sync
|
||||||
REDIS_HOST=127.0.0.1
|
REDIS_HOST=127.0.0.1
|
||||||
@@ -108,5 +180,4 @@ IS_DOCKER=false
|
|||||||
IS_SANDSTORM=false
|
IS_SANDSTORM=false
|
||||||
IS_HEROKU=true
|
IS_HEROKU=true
|
||||||
BUNQ_USE_SANDBOX=false
|
BUNQ_USE_SANDBOX=false
|
||||||
MAILGUN_DOMAIN=
|
FFIII_LAYOUT=v1
|
||||||
MAILGUN_SECRET=
|
|
||||||
14
.deploy/heroku/.locales
Normal file
14
.deploy/heroku/.locales
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
en_US
|
||||||
|
es_ES
|
||||||
|
de_DE
|
||||||
|
fr_FR
|
||||||
|
ro_RO
|
||||||
|
it_IT
|
||||||
|
nl_NL
|
||||||
|
pl_PL
|
||||||
|
pt_BR
|
||||||
|
ru_RU
|
||||||
|
nb_NO
|
||||||
|
cs_CZ
|
||||||
|
id_ID
|
||||||
|
hu_HU
|
||||||
@@ -44,17 +44,17 @@ spec:
|
|||||||
- image: firefly-local
|
- image: firefly-local
|
||||||
name: firefly-local
|
name: firefly-local
|
||||||
env:
|
env:
|
||||||
- name: FF_APP_ENV
|
- name: APP_ENV
|
||||||
value: "local"
|
value: "local"
|
||||||
- name: FF_APP_KEY
|
- name: APP_KEY
|
||||||
value: "S0m3R@nd0mString0f32Ch@rsEx@ct1y"
|
value: "S0m3R@nd0mString0f32Ch@rsEx@ct1y"
|
||||||
- name: FF_DB_HOST
|
- name: DB_HOST
|
||||||
value: "172.17.0.9"
|
value: "172.17.0.9"
|
||||||
- name: FF_DB_NAME
|
- name: DB_NAME
|
||||||
value: "firefly_db"
|
value: "firefly_db"
|
||||||
- name: FF_DB_USER
|
- name: DB_USER
|
||||||
value: "firefly_db"
|
value: "firefly_db"
|
||||||
- name: FF_DB_PASSWORD
|
- name: DB_PASSWORD
|
||||||
value: "password"
|
value: "password"
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- mountPath: "/var/www/firefly-iii/storage/export"
|
- mountPath: "/var/www/firefly-iii/storage/export"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
APP_ENV=local
|
APP_ENV=local
|
||||||
|
|
||||||
# Set to true if you want to see debug information in error screens.
|
# 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
|
# This should be your email address
|
||||||
SITE_OWNER=sandstorm@example.com
|
SITE_OWNER=sandstorm@example.com
|
||||||
@@ -49,6 +49,19 @@ DB_PASSWORD=firefly
|
|||||||
CACHE_DRIVER=file
|
CACHE_DRIVER=file
|
||||||
SESSION_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 settings. Should not be necessary to change these.
|
||||||
COOKIE_PATH="/"
|
COOKIE_PATH="/"
|
||||||
COOKIE_DOMAIN=
|
COOKIE_DOMAIN=
|
||||||
@@ -74,11 +87,20 @@ SPARKPOST_SECRET=
|
|||||||
SEND_REGISTRATION_MAIL=true
|
SEND_REGISTRATION_MAIL=true
|
||||||
SEND_ERROR_MESSAGE=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.
|
# 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.
|
# Firefly III currently supports two provider for live Currency Exchange Rates:
|
||||||
# Please note that this will only work for paid fixer.io accounts because they severly limited
|
# "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.
|
# the free API up to the point where you might as well offer nothing.
|
||||||
FIXER_API_KEY=
|
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.
|
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
||||||
USE_ENCRYPTION=true
|
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.
|
# Leave the following configuration vars as is.
|
||||||
# Unless you like to tinker and know what you're doing.
|
# Unless you like to tinker and know what you're doing.
|
||||||
APP_NAME=FireflyIII
|
APP_NAME=FireflyIII
|
||||||
|
ADLDAP_CONNECTION=default
|
||||||
BROADCAST_DRIVER=log
|
BROADCAST_DRIVER=log
|
||||||
QUEUE_DRIVER=sync
|
QUEUE_DRIVER=sync
|
||||||
REDIS_HOST=127.0.0.1
|
REDIS_HOST=127.0.0.1
|
||||||
@@ -108,5 +175,4 @@ IS_DOCKER=false
|
|||||||
IS_SANDSTORM=true
|
IS_SANDSTORM=true
|
||||||
IS_HEROKU=false
|
IS_HEROKU=false
|
||||||
BUNQ_USE_SANDBOX=false
|
BUNQ_USE_SANDBOX=false
|
||||||
MAILGUN_DOMAIN=
|
FFIII_LAYOUT=v1
|
||||||
MAILGUN_SECRET=
|
|
||||||
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=
|
|
||||||
91
.env.example
91
.env.example
@@ -8,8 +8,8 @@ APP_DEBUG=false
|
|||||||
# This should be your email address
|
# This should be your email address
|
||||||
SITE_OWNER=mail@example.com
|
SITE_OWNER=mail@example.com
|
||||||
|
|
||||||
# The encryption key for your database and sessions. Keep this very secure.
|
# The encryption key for your sessions. Keep this very secure.
|
||||||
# If you generate a new one all existing data must be considered LOST.
|
# 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
|
# Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it
|
||||||
APP_KEY=SomeRandomStringOf32CharsExactly
|
APP_KEY=SomeRandomStringOf32CharsExactly
|
||||||
|
|
||||||
@@ -22,6 +22,7 @@ TZ=Europe/Amsterdam
|
|||||||
APP_URL=http://localhost
|
APP_URL=http://localhost
|
||||||
|
|
||||||
# TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy.
|
# 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=
|
TRUSTED_PROXIES=
|
||||||
|
|
||||||
# The log channel defines where your log entries go to.
|
# The log channel defines where your log entries go to.
|
||||||
@@ -39,16 +40,37 @@ APP_LOG_LEVEL=notice
|
|||||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
# 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
|
# For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html
|
||||||
DB_CONNECTION=mysql
|
DB_CONNECTION=mysql
|
||||||
|
# If you use DOCKER COMPOSE, change this variable to "firefly_iii_db"
|
||||||
DB_HOST=127.0.0.1
|
DB_HOST=127.0.0.1
|
||||||
DB_PORT=3306
|
DB_PORT=3306
|
||||||
DB_DATABASE=homestead
|
DB_DATABASE=homestead
|
||||||
DB_USERNAME=homestead
|
DB_USERNAME=homestead
|
||||||
DB_PASSWORD=secret
|
DB_PASSWORD=secret
|
||||||
|
|
||||||
|
# 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.
|
# If you're looking for performance improvements, you could install memcached.
|
||||||
CACHE_DRIVER=file
|
CACHE_DRIVER=file
|
||||||
SESSION_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 settings. Should not be necessary to change these.
|
||||||
COOKIE_PATH="/"
|
COOKIE_PATH="/"
|
||||||
COOKIE_DOMAIN=
|
COOKIE_DOMAIN=
|
||||||
@@ -74,24 +96,75 @@ SPARKPOST_SECRET=
|
|||||||
SEND_REGISTRATION_MAIL=true
|
SEND_REGISTRATION_MAIL=true
|
||||||
SEND_ERROR_MESSAGE=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.
|
# 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.
|
# Firefly III currently supports two provider for live Currency Exchange Rates:
|
||||||
# Please note that this will only work for paid fixer.io accounts because they severly limited
|
# "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.
|
# 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.
|
# 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.
|
# Firefly III has two options for user authentication. "eloquent" is the default,
|
||||||
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
# and "ldap" for LDAP servers.
|
||||||
USE_ENCRYPTION=true
|
# 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.
|
# Leave the following configuration vars as is.
|
||||||
# Unless you like to tinker and know what you're doing.
|
# Unless you like to tinker and know what you're doing.
|
||||||
APP_NAME=FireflyIII
|
APP_NAME=FireflyIII
|
||||||
|
ADLDAP_CONNECTION=default
|
||||||
BROADCAST_DRIVER=log
|
BROADCAST_DRIVER=log
|
||||||
QUEUE_DRIVER=sync
|
QUEUE_DRIVER=sync
|
||||||
REDIS_HOST=127.0.0.1
|
REDIS_HOST=127.0.0.1
|
||||||
@@ -105,8 +178,8 @@ PUSHER_ID=
|
|||||||
DEMO_USERNAME=
|
DEMO_USERNAME=
|
||||||
DEMO_PASSWORD=
|
DEMO_PASSWORD=
|
||||||
IS_DOCKER=false
|
IS_DOCKER=false
|
||||||
|
USE_ENCRYPTION=false
|
||||||
IS_SANDSTORM=false
|
IS_SANDSTORM=false
|
||||||
IS_HEROKU=false
|
IS_HEROKU=false
|
||||||
BUNQ_USE_SANDBOX=false
|
BUNQ_USE_SANDBOX=false
|
||||||
MAILGUN_DOMAIN=
|
FFIII_LAYOUT=v1
|
||||||
MAILGUN_SECRET=
|
|
||||||
|
|||||||
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=info
|
|
||||||
|
|
||||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
|
||||||
# For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html
|
|
||||||
DB_CONNECTION=sqlite
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# If you're looking for performance improvements, you could install memcached.
|
|
||||||
CACHE_DRIVER=file
|
|
||||||
SESSION_DRIVER=file
|
|
||||||
|
|
||||||
# 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**
|
**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**
|
**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**
|
**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**
|
**Bonus points**
|
||||||
Earn bonus points by:
|
<!-- Earn bonus points by:
|
||||||
|
|
||||||
- Post a stacktrace from your log files
|
- 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
|
I am running Firefly III version x.x.x
|
||||||
|
|
||||||
**Description**
|
**Description**
|
||||||
|
<!-- (if relevant of course) -->
|
||||||
|
|
||||||
|
|
||||||
**Steps to reproduce**
|
|
||||||
(if relevant of course)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**Extra info**
|
**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**
|
**Bonus points**
|
||||||
Earn bonus points by:
|
<!-- Earn bonus points by:
|
||||||
|
|
||||||
- Add a screenshot
|
- 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**
|
**Description**
|
||||||
|
<!--
|
||||||
Please describe your feature request:
|
Please describe your feature request:
|
||||||
|
|
||||||
- I would like Firefly III to do X.
|
- I would like Firefly III to do ABC.
|
||||||
- What if you would add feature Y?
|
- What if you would add feature XYZ?
|
||||||
- Firefly III doesn't do Z.
|
- Firefly III doesn't do DEF.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
**Solution**
|
**Solution**
|
||||||
Describe what your feature would add to Firefly III.
|
<!-- Describe what your feature would add to Firefly III. -->
|
||||||
|
|
||||||
**What are alternatives?**
|
**What are alternatives?**
|
||||||
Please describe what alternatives currently exist.
|
<!-- Please describe what alternatives currently exist. -->
|
||||||
|
|
||||||
**Additional context**
|
**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:
|
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:"
|
||||||
7
.github/stale.yml
vendored
7
.github/stale.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
# Configuration for probot-stale - https://github.com/probot/stale
|
# Configuration for probot-stale - https://github.com/probot/stale
|
||||||
|
|
||||||
# Number of days of inactivity before an Issue or Pull Request becomes 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.
|
# 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.
|
# 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
|
- enhancement
|
||||||
- feature
|
- feature
|
||||||
- bug
|
- bug
|
||||||
|
- possible-bug
|
||||||
|
- "possible bug"
|
||||||
|
- announcement
|
||||||
|
|
||||||
# Set to true to ignore issues in a project (defaults to false)
|
# Set to true to ignore issues in a project (defaults to false)
|
||||||
exemptProjects: false
|
exemptProjects: false
|
||||||
@@ -53,4 +56,4 @@ limitPerRun: 30
|
|||||||
|
|
||||||
# issues:
|
# issues:
|
||||||
# exemptLabels:
|
# exemptLabels:
|
||||||
# - confirmed
|
# - confirmed
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ set -euo pipefail
|
|||||||
echo "In build.sh"
|
echo "In build.sh"
|
||||||
|
|
||||||
cd /opt/app
|
cd /opt/app
|
||||||
cp .env.sandstorm .env
|
cp .deploy/sandstorm/.env.sandstorm .env
|
||||||
|
|
||||||
if [ -f /opt/app/composer.json ] ; then
|
if [ -f /opt/app/composer.json ] ; then
|
||||||
if [ ! -f composer.phar ] ; then
|
if [ ! -f composer.phar ] ; then
|
||||||
|
|||||||
@@ -1,3 +1,316 @@
|
|||||||
|
# 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.
|
||||||
|
- #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
|
# 4.7.6.2
|
||||||
- Docker file builds again.
|
- Docker file builds again.
|
||||||
- Fix CSS of OAuth2 authorization view.
|
- Fix CSS of OAuth2 authorization view.
|
||||||
@@ -44,11 +357,12 @@
|
|||||||
- [Issue 1639](https://github.com/firefly-iii/firefly-iii/issues/1639) Firefly III trusts the Heroku load balancer, fixing deployment on Heroku.
|
- [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 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.
|
- [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.
|
- Fix bug in Spectre import.
|
||||||
- Heroku would not make you owner.
|
- Heroku would not make you owner.
|
||||||
- Add `.htaccess` files to all public directories.
|
- Add `.htaccess` files to all public directories.
|
||||||
- New secure headers will make Firefly III slightly more secure.
|
- 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
|
# 4.7.5.3
|
||||||
- [Issue 1527](https://github.com/firefly-iii/firefly-iii/issues/1527), fixed views for transactions without a budget.
|
- [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/mysql
|
||||||
mkdir -p /var/log/nginx
|
mkdir -p /var/log/nginx
|
||||||
# Wipe /var/run, since pidfiles and socket files from previous launches should go away
|
# 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
|
rm -rf /var/run
|
||||||
mkdir -p /var/run
|
mkdir -p /var/run
|
||||||
rm -rf /var/tmp
|
rm -rf /var/tmp
|
||||||
@@ -25,9 +25,9 @@ mkdir -p /var/storage/build
|
|||||||
mkdir -p /var/storage/database
|
mkdir -p /var/storage/database
|
||||||
mkdir -p /var/storage/debugbar
|
mkdir -p /var/storage/debugbar
|
||||||
mkdir -p /var/storage/export
|
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/sessions
|
||||||
mkdir -p /var/storage/framework/views
|
mkdir -p /var/storage/framework/views/v1
|
||||||
mkdir -p /var/storage/logs
|
mkdir -p /var/storage/logs
|
||||||
mkdir -p /var/storage/upload
|
mkdir -p /var/storage/upload
|
||||||
|
|
||||||
@@ -37,15 +37,15 @@ HOME=/etc/mysql /usr/bin/mysql_install_db --force
|
|||||||
# Spawn mysqld, php
|
# Spawn mysqld, php
|
||||||
HOME=/etc/mysql /usr/sbin/mysqld &
|
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
|
# Wait until mysql and php have bound their sockets, indicating readiness
|
||||||
while [ ! -e /var/run/mysqld/mysqld.sock ] ; do
|
while [ ! -e /var/run/mysqld/mysqld.sock ] ; do
|
||||||
echo "waiting for mysql to be available at /var/run/mysqld/mysqld.sock"
|
echo "waiting for mysql to be available at /var/run/mysqld/mysqld.sock"
|
||||||
sleep .5
|
sleep .5
|
||||||
done
|
done
|
||||||
while [ ! -e /var/run/php7.1-fpm.sock ] ; do
|
while [ ! -e /var/run/php7.2-fpm.sock ] ; do
|
||||||
echo "waiting for php7.1-fpm to be available at /var/run/php7.1-fpm.sock"
|
echo "waiting for php7.2-fpm to be available at /var/run/php7.2-fpm.sock"
|
||||||
sleep .5
|
sleep .5
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -58,9 +58,5 @@ echo "Migrating..."
|
|||||||
php /opt/app/artisan migrate --seed --force
|
php /opt/app/artisan migrate --seed --force
|
||||||
echo "Done!"
|
echo "Done!"
|
||||||
|
|
||||||
echo "Clear cache.."
|
|
||||||
php /opt/app/artisan cache:clear
|
|
||||||
echo "Done"
|
|
||||||
|
|
||||||
# Start nginx.
|
# Start nginx.
|
||||||
/usr/sbin/nginx -c /opt/app/.sandstorm/service-config/nginx.conf -g "daemon off;"
|
/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 = (
|
manifest = (
|
||||||
appTitle = (defaultText = "Firefly III"),
|
appTitle = (defaultText = "Firefly III"),
|
||||||
appVersion = 16,
|
appVersion = 34,
|
||||||
appMarketingVersion = (defaultText = "4.7.6.2"),
|
appMarketingVersion = (defaultText = "4.8.0.2"),
|
||||||
|
|
||||||
actions = [
|
actions = [
|
||||||
# Define your "new document" handlers here.
|
# 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
|
# not have been detected as a dependency during `spk dev`. If you list
|
||||||
# a directory here, its entire contents will be included recursively.
|
# a directory here, its entire contents will be included recursively.
|
||||||
|
|
||||||
#bridgeConfig = (
|
bridgeConfig = (
|
||||||
# # Used for integrating permissions and roles into the Sandstorm shell
|
# # Used for integrating permissions and roles into the Sandstorm shell
|
||||||
# # and for sandstorm-http-bridge to pass to your app.
|
# # and for sandstorm-http-bridge to pass to your app.
|
||||||
# # Uncomment this block and adjust the permissions and roles to make
|
# # 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
|
# # 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
|
# # 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
|
# # comes in to your app's API, sandstorm-http-bridge will prefix the request's path with
|
||||||
# # this string, if specified.
|
# # this string, if specified.
|
||||||
#),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const myCommand :Spk.Manifest.Command = (
|
const myCommand :Spk.Manifest.Command = (
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ http {
|
|||||||
}
|
}
|
||||||
location ~ \.php$ {
|
location ~ \.php$ {
|
||||||
try_files $uri =404;
|
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_index index.php;
|
||||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
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
|
apt-get install -y python-software-properties software-properties-common
|
||||||
|
|
||||||
# install all languages
|
# 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/# 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/# 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
|
sed -i 's/# it_IT.UTF-8 UTF-8/it_IT.UTF-8 UTF-8/g' /etc/locale.gen
|
||||||
@@ -20,13 +22,16 @@ 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/# 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/# 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/# 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
|
||||||
|
|
||||||
dpkg-reconfigure --frontend=noninteractive locales
|
dpkg-reconfigure --frontend=noninteractive locales
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# actually add repository
|
# actually add repository
|
||||||
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E9C74FEEA2098A6E
|
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E9C74FEEA2098A6E
|
||||||
add-apt-repository "deb http://packages.dotdeb.org jessie all"
|
add-apt-repository "deb http://packages.dotdeb.org jessie all"
|
||||||
@@ -38,37 +43,37 @@ echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sou
|
|||||||
|
|
||||||
# install packages.
|
# install packages.
|
||||||
apt-get update
|
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 nginx stop
|
||||||
service php7.1-fpm stop
|
service php7.2-fpm stop
|
||||||
service mysql stop
|
service mysql stop
|
||||||
systemctl disable nginx
|
systemctl disable nginx
|
||||||
systemctl disable php7.1-fpm
|
systemctl disable php7.2-fpm
|
||||||
systemctl disable mysql
|
systemctl disable mysql
|
||||||
|
|
||||||
# make php.ini display errors:
|
# 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='' \
|
sed --in-place='' \
|
||||||
--expression='s/^listen.owner = www-data/;listen.owner = www-data/' \
|
--expression='s/^listen.owner = www-data/;listen.owner = www-data/' \
|
||||||
--expression='s/^listen.group = www-data/;listen.group = www-data/' \
|
--expression='s/^listen.group = www-data/;listen.group = www-data/' \
|
||||||
/etc/php/7.1/fpm/pool.d/www.conf
|
/etc/php/7.2/fpm/pool.d/www.conf
|
||||||
# patch /etc/php/7.1/fpm/php-fpm.conf to not have a pidfile
|
# patch /etc/php/7.2/fpm/php-fpm.conf to not have a pidfile
|
||||||
sed --in-place='' \
|
sed --in-place='' \
|
||||||
--expression='s/^pid =/;pid =/' \
|
--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:
|
# move sock file to better dir:
|
||||||
sed --in-place='' \
|
sed --in-place='' \
|
||||||
--expression='s/^listen = \/run\/php\/php7.1-fpm.sock/listen = \/var\/run\/php7.1-fpm.sock/' \
|
--expression='s/^listen = \/run\/php\/php7.2-fpm.sock/listen = \/var\/run\/php7.2-fpm.sock/' \
|
||||||
/etc/php/7.1/fpm/pool.d/www.conf
|
/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
|
# so we can pass in SANDSTORM=1 to apps
|
||||||
sed --in-place='' \
|
sed --in-place='' \
|
||||||
--expression='s/^;clear_env = no/clear_env=no/' \
|
--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
|
# 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
|
# for secure-file-priv see https://github.com/sandstorm-io/vagrant-spk/issues/195
|
||||||
sed --in-place='' \
|
sed --in-place='' \
|
||||||
|
|||||||
44
.travis.yml
44
.travis.yml
@@ -1,29 +1,29 @@
|
|||||||
language: php
|
sudo: required
|
||||||
php:
|
language: bash
|
||||||
- 7.1.18
|
env:
|
||||||
|
- VERSION=4.8.0.2
|
||||||
|
|
||||||
cache:
|
dist: xenial
|
||||||
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
|
|
||||||
|
|
||||||
# safelist
|
# safelist
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- develop
|
- develop
|
||||||
- master
|
- 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
|
||||||
|
|||||||
130
Dockerfile
130
Dockerfile
@@ -1,111 +1,45 @@
|
|||||||
FROM php:7.1-apache
|
FROM php:7.2-apache
|
||||||
|
ENV FIREFLY_PATH=/var/www/firefly-iii COMPOSER_ALLOW_SUPERUSER=1
|
||||||
# If building on a RPi, use --build-arg cores=3 to use all cores when compiling
|
LABEL version="1.5" maintainer="thegrumpydictator@gmail.com"
|
||||||
# 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
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Create volumes
|
# Create volumes
|
||||||
VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload
|
VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload
|
||||||
|
|
||||||
# Enable default site (Firefly III)
|
# Install stuff Firefly III runs with & depends on: php extensions, locales, dev headers and composer
|
||||||
COPY ./.deploy/docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf
|
RUN apt-get update && apt-get install -y locales unzip && apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Make sure we own Firefly III directory
|
ADD https://raw.githubusercontent.com/mlocati/docker-php-extension-installer/master/install-php-extensions /usr/local/bin/
|
||||||
RUN chown -R www-data:www-data /var/www && chmod -R 775 $FIREFLY_PATH/storage
|
|
||||||
|
|
||||||
# Copy in Firefly Source
|
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
|
||||||
|
|
||||||
|
# configure PHP
|
||||||
|
RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini && \
|
||||||
|
sed -i 's/max_execution_time = 30/max_execution_time = 600/' /usr/local/etc/php/php.ini && \
|
||||||
|
sed -i 's/memory_limit = 128M/memory_limit = 512M/' /usr/local/etc/php/php.ini
|
||||||
|
|
||||||
|
# Copy in Firefly III source
|
||||||
WORKDIR $FIREFLY_PATH
|
WORKDIR $FIREFLY_PATH
|
||||||
ADD . $FIREFLY_PATH
|
ADD . $FIREFLY_PATH
|
||||||
|
|
||||||
# Fix the link to curl:
|
# Ensure correct app directory permission, then `composer install`
|
||||||
RUN rm -rf /usr/local/lib/libcurl.so.4 && ln -s /usr/lib/x86_64-linux-gnu/libcurl.so.4.4.0 /usr/local/lib/libcurl.so.4
|
RUN chown -R www-data:www-data /var/www && \
|
||||||
|
chmod -R 775 $FIREFLY_PATH/storage && \
|
||||||
|
composer install --prefer-dist --no-dev --no-scripts --no-suggest
|
||||||
|
|
||||||
# Run composer
|
# copy ca certs to correct location
|
||||||
ENV COMPOSER_ALLOW_SUPERUSER 1
|
COPY ./.deploy/docker/cacert.pem /usr/local/ssl/cert.pem
|
||||||
RUN composer install --prefer-dist --no-dev --no-scripts --no-suggest
|
|
||||||
|
# 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 port 80
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|||||||
49
Dockerfile.amd64
Normal file
49
Dockerfile.amd64
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
FROM php:7.2-apache
|
||||||
|
ARG ARCH
|
||||||
|
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
|
||||||
|
|
||||||
|
# configure PHP
|
||||||
|
RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini && \
|
||||||
|
sed -i 's/max_execution_time = 30/max_execution_time = 600/' /usr/local/etc/php/php.ini && \
|
||||||
|
sed -i 's/memory_limit = 128M/memory_limit = 512M/' /usr/local/etc/php/php.ini
|
||||||
|
|
||||||
|
# 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"]
|
||||||
45
Dockerfile.arm
Normal file
45
Dockerfile.arm
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"]
|
||||||
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": [
|
"buildpacks": [
|
||||||
{
|
{
|
||||||
"url": "heroku/php"
|
"url": "heroku/php"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/heroku/heroku-buildpack-locale"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"env": {
|
"env": {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns basic information about this installation.
|
* Returns basic information about this installation.
|
||||||
*
|
* @codeCoverageIgnore
|
||||||
* Class AboutController.
|
* Class AboutController.
|
||||||
*/
|
*/
|
||||||
class AboutController extends Controller
|
class AboutController extends Controller
|
||||||
@@ -51,8 +51,10 @@ class AboutController extends Controller
|
|||||||
$phpVersion = str_replace($search, $replace, PHP_VERSION);
|
$phpVersion = str_replace($search, $replace, PHP_VERSION);
|
||||||
$phpOs = str_replace($search, $replace, PHP_OS);
|
$phpOs = str_replace($search, $replace, PHP_OS);
|
||||||
$currentDriver = DB::getDriverName();
|
$currentDriver = DB::getDriverName();
|
||||||
|
|
||||||
|
|
||||||
$data
|
$data
|
||||||
= [
|
= [
|
||||||
'version' => config('firefly.version'),
|
'version' => config('firefly.version'),
|
||||||
'api_version' => config('firefly.api_version'),
|
'api_version' => config('firefly.api_version'),
|
||||||
'php_version' => $phpVersion,
|
'php_version' => $phpVersion,
|
||||||
@@ -60,14 +62,13 @@ class AboutController extends Controller
|
|||||||
'driver' => $currentDriver,
|
'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.
|
* Returns information about the user.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function user(Request $request): JsonResponse
|
public function user(Request $request): JsonResponse
|
||||||
@@ -75,7 +76,12 @@ class AboutController extends Controller
|
|||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
$resource = new Item(auth()->user(), new UserTransformer($this->parameters), 'users');
|
|
||||||
|
/** @var UserTransformer $transformer */
|
||||||
|
$transformer = app(UserTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item(auth()->user(), $transformer, 'users');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,16 +23,21 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Controllers;
|
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\Account;
|
||||||
use FireflyIII\Models\AccountType;
|
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
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\AccountTransformer;
|
||||||
|
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||||
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
use League\Fractal\Manager;
|
use League\Fractal\Manager;
|
||||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||||
use League\Fractal\Resource\Collection as FractalCollection;
|
use League\Fractal\Resource\Collection as FractalCollection;
|
||||||
@@ -42,17 +47,18 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
|||||||
/**
|
/**
|
||||||
* Class AccountController.
|
* Class AccountController.
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
*
|
||||||
*/
|
*/
|
||||||
class AccountController extends Controller
|
class AccountController extends Controller
|
||||||
{
|
{
|
||||||
/** @var CurrencyRepositoryInterface The currency repository */
|
use AccountFilter, TransactionFilter;
|
||||||
private $currencyRepository;
|
|
||||||
/** @var AccountRepositoryInterface The account repository */
|
/** @var AccountRepositoryInterface The account repository */
|
||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AccountController constructor.
|
* AccountController constructor.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -65,9 +71,6 @@ class AccountController extends Controller
|
|||||||
$this->repository = app(AccountRepositoryInterface::class);
|
$this->repository = app(AccountRepositoryInterface::class);
|
||||||
$this->repository->setUser($user);
|
$this->repository->setUser($user);
|
||||||
|
|
||||||
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
|
||||||
$this->currencyRepository->setUser($user);
|
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -76,8 +79,9 @@ class AccountController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Remove the specified resource from storage.
|
* Remove the specified resource from storage.
|
||||||
*
|
*
|
||||||
* @param \FireflyIII\Models\Account $account
|
* @param Account $account
|
||||||
*
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function delete(Account $account): JsonResponse
|
public function delete(Account $account): JsonResponse
|
||||||
@@ -92,6 +96,7 @@ class AccountController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
@@ -105,7 +110,7 @@ class AccountController extends Controller
|
|||||||
$this->parameters->set('type', $type);
|
$this->parameters->set('type', $type);
|
||||||
|
|
||||||
// types to get, page size:
|
// 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;
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
// get list of accounts. Count it and split it.
|
// get list of accounts. Count it and split it.
|
||||||
@@ -119,31 +124,78 @@ class AccountController extends Controller
|
|||||||
|
|
||||||
// present to user.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all piggies.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param Account $account
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function piggyBanks(Request $request, Account $account): JsonResponse
|
||||||
|
{
|
||||||
|
// create some objects:
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
|
||||||
|
// types to get, page size:
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
|
// get list of budgets. Count it and split it.
|
||||||
|
$collection = $this->repository->getPiggyBanks($account);
|
||||||
|
$count = $collection->count();
|
||||||
|
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
|
||||||
|
// make paginator:
|
||||||
|
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
$paginator->setPath(route('api.v1.accounts.piggy_banks', [$account->id]) . $this->buildParams());
|
||||||
|
|
||||||
|
// present to user.
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var PiggyBankTransformer $transformer */
|
||||||
|
$transformer = app(PiggyBankTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy_banks');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show single instance.
|
* Show single instance.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, Account $account): JsonResponse
|
public function show(Request $request, Account $account): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
|
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -151,24 +203,79 @@ class AccountController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Store a new instance.
|
* 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();
|
$data = $request->getAllAccountData();
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
$account = $this->repository->store($data);
|
$account = $this->repository->store($data);
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($account, new AccountTransformer($this->parameters), 'accounts');
|
/** @var AccountTransformer $transformer */
|
||||||
|
$transformer = app(AccountTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($account, $transformer, 'accounts');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show all 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 = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @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');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -176,76 +283,25 @@ class AccountController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Update account.
|
* Update account.
|
||||||
*
|
*
|
||||||
* @param AccountRequest $request
|
* @param AccountUpdateRequest $request
|
||||||
* @param Account $account
|
* @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();
|
$data = $request->getAllAccountData();
|
||||||
// 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['type'] = config('firefly.shortNamesByFullName.' . $account->accountType->type);
|
$data['type'] = config('firefly.shortNamesByFullName.' . $account->accountType->type);
|
||||||
$this->repository->update($account, $data);
|
$this->repository->update($account, $data);
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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');
|
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;
|
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\Exceptions\FireflyException;
|
||||||
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||||
use FireflyIII\Models\Attachment;
|
use FireflyIII\Models\Attachment;
|
||||||
@@ -39,11 +40,12 @@ use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
|||||||
use League\Fractal\Resource\Collection as FractalCollection;
|
use League\Fractal\Resource\Collection as FractalCollection;
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
use League\Fractal\Serializer\JsonApiSerializer;
|
use League\Fractal\Serializer\JsonApiSerializer;
|
||||||
|
use function strlen;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class AttachmentController.
|
* Class AttachmentController.
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
*
|
||||||
*/
|
*/
|
||||||
class AttachmentController extends Controller
|
class AttachmentController extends Controller
|
||||||
{
|
{
|
||||||
@@ -52,6 +54,7 @@ class AttachmentController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* AccountController constructor.
|
* AccountController constructor.
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -70,7 +73,7 @@ class AttachmentController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the specified resource from storage.
|
* Remove the specified resource from storage.
|
||||||
*
|
* @codeCoverageIgnore
|
||||||
* @param Attachment $attachment
|
* @param Attachment $attachment
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
@@ -86,9 +89,9 @@ class AttachmentController extends Controller
|
|||||||
* Download an attachment.
|
* Download an attachment.
|
||||||
*
|
*
|
||||||
* @param Attachment $attachment
|
* @param Attachment $attachment
|
||||||
*
|
* @codeCoverageIgnore
|
||||||
* @return LaravelResponse
|
* @return LaravelResponse
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function download(Attachment $attachment): LaravelResponse
|
public function download(Attachment $attachment): LaravelResponse
|
||||||
{
|
{
|
||||||
@@ -100,7 +103,7 @@ class AttachmentController extends Controller
|
|||||||
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
|
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
|
||||||
|
|
||||||
/** @var LaravelResponse $response */
|
/** @var LaravelResponse $response */
|
||||||
$response = response($content, 200);
|
$response = response($content);
|
||||||
$response
|
$response
|
||||||
->header('Content-Description', 'File Transfer')
|
->header('Content-Description', 'File Transfer')
|
||||||
->header('Content-Type', 'application/octet-stream')
|
->header('Content-Type', 'application/octet-stream')
|
||||||
@@ -110,7 +113,7 @@ class AttachmentController extends Controller
|
|||||||
->header('Expires', '0')
|
->header('Expires', '0')
|
||||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||||
->header('Pragma', 'public')
|
->header('Pragma', 'public')
|
||||||
->header('Content-Length', \strlen($content));
|
->header('Content-Length', strlen($content));
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
@@ -121,7 +124,7 @@ class AttachmentController extends Controller
|
|||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
* @codeCoverageIgnore
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
@@ -144,7 +147,12 @@ class AttachmentController extends Controller
|
|||||||
|
|
||||||
// present to user.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
@@ -153,22 +161,21 @@ class AttachmentController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Display the specified resource.
|
* Display the specified resource.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Attachment $attachment
|
* @param Attachment $attachment
|
||||||
*
|
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, Attachment $attachment): JsonResponse
|
public function show(Request $request, Attachment $attachment): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
|
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
$resource = new Item($attachment, new AttachmentTransformer($this->parameters), 'attachments');
|
|
||||||
|
/** @var AttachmentTransformer $transformer */
|
||||||
|
$transformer = app(AttachmentTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($attachment, $transformer, 'attachments');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -176,19 +183,24 @@ class AttachmentController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Store a newly created resource in storage.
|
* Store a newly created resource in storage.
|
||||||
*
|
*
|
||||||
* @param AttachmentRequest $request
|
* @param AttachmentStoreRequest $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function store(AttachmentRequest $request): JsonResponse
|
public function store(AttachmentStoreRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$attachment = $this->repository->store($data);
|
$attachment = $this->repository->store($data);
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
$resource = new Item($attachment, new AttachmentTransformer($this->parameters), 'attachments');
|
|
||||||
|
/** @var AttachmentTransformer $transformer */
|
||||||
|
$transformer = app(AttachmentTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($attachment, $transformer, 'attachments');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -196,12 +208,12 @@ class AttachmentController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Update the specified resource in storage.
|
* Update the specified resource in storage.
|
||||||
*
|
*
|
||||||
* @param AttachmentRequest $request
|
* @param AttachmentUpdateRequest $request
|
||||||
* @param Attachment $attachment
|
* @param Attachment $attachment
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function update(AttachmentRequest $request, Attachment $attachment): JsonResponse
|
public function update(AttachmentUpdateRequest $request, Attachment $attachment): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$this->repository->update($attachment, $data);
|
$this->repository->update($attachment, $data);
|
||||||
@@ -209,15 +221,19 @@ class AttachmentController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($attachment, new AttachmentTransformer($this->parameters), 'attachments');
|
/** @var AttachmentTransformer $transformer */
|
||||||
|
$transformer = app(AttachmentTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($attachment, $transformer, 'attachments');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upload an attachment.
|
* Upload an attachment.
|
||||||
*
|
* @codeCoverageIgnore
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Attachment $attachment
|
* @param Attachment $attachment
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Api\V1\Controllers;
|
namespace FireflyIII\Api\V1\Controllers;
|
||||||
|
|
||||||
use FireflyIII\Api\V1\Requests\AvailableBudgetRequest;
|
use FireflyIII\Api\V1\Requests\AvailableBudgetRequest;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Factory\TransactionCurrencyFactory;
|
||||||
use FireflyIII\Models\AvailableBudget;
|
use FireflyIII\Models\AvailableBudget;
|
||||||
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
|
||||||
use FireflyIII\Transformers\AvailableBudgetTransformer;
|
use FireflyIII\Transformers\AvailableBudgetTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
@@ -42,17 +42,17 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
|||||||
/**
|
/**
|
||||||
* Class AvailableBudgetController.
|
* Class AvailableBudgetController.
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
*
|
||||||
*/
|
*/
|
||||||
class AvailableBudgetController extends Controller
|
class AvailableBudgetController extends Controller
|
||||||
{
|
{
|
||||||
/** @var CurrencyRepositoryInterface The currency repository */
|
|
||||||
private $currencyRepository;
|
|
||||||
/** @var BudgetRepositoryInterface The budget repository */
|
/** @var BudgetRepositoryInterface The budget repository */
|
||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AccountController constructor.
|
* AvailableBudgetController constructor.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -60,9 +60,8 @@ class AvailableBudgetController extends Controller
|
|||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$this->repository = app(BudgetRepositoryInterface::class);
|
$this->repository = app(BudgetRepositoryInterface::class);
|
||||||
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
|
||||||
$this->repository->setUser($user);
|
$this->repository->setUser($user);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
@@ -75,6 +74,8 @@ class AvailableBudgetController extends Controller
|
|||||||
*
|
*
|
||||||
* @param AvailableBudget $availableBudget
|
* @param AvailableBudget $availableBudget
|
||||||
*
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function delete(AvailableBudget $availableBudget): JsonResponse
|
public function delete(AvailableBudget $availableBudget): JsonResponse
|
||||||
@@ -90,6 +91,7 @@ class AvailableBudgetController extends Controller
|
|||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -100,8 +102,11 @@ class AvailableBudgetController extends Controller
|
|||||||
// types to get, page size:
|
// types to get, page size:
|
||||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
|
$start = $this->parameters->get('start');
|
||||||
|
$end = $this->parameters->get('end');
|
||||||
|
|
||||||
// get list of available budgets. Count it and split it.
|
// get list of available budgets. Count it and split it.
|
||||||
$collection = $this->repository->getAvailableBudgets();
|
$collection = $this->repository->getAvailableBudgetsByDate($start, $end);
|
||||||
$count = $collection->count();
|
$count = $collection->count();
|
||||||
$availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
$availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
|
||||||
@@ -111,7 +116,12 @@ class AvailableBudgetController extends Controller
|
|||||||
|
|
||||||
// present to user.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
@@ -120,23 +130,23 @@ class AvailableBudgetController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Display the specified resource.
|
* Display the specified resource.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param AvailableBudget $availableBudget
|
* @param AvailableBudget $availableBudget
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, AvailableBudget $availableBudget): JsonResponse
|
public function show(Request $request, AvailableBudget $availableBudget): JsonResponse
|
||||||
{
|
{
|
||||||
|
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
|
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
$resource = new Item($availableBudget, new AvailableBudgetTransformer($this->parameters), 'available_budgets');
|
|
||||||
|
/** @var AvailableBudgetTransformer $transformer */
|
||||||
|
$transformer = app(AvailableBudgetTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($availableBudget, $transformer, 'available_budgets');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -147,47 +157,69 @@ class AvailableBudgetController extends Controller
|
|||||||
* @param AvailableBudgetRequest $request
|
* @param AvailableBudgetRequest $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
*/
|
||||||
public function store(AvailableBudgetRequest $request): JsonResponse
|
public function store(AvailableBudgetRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$currency = $this->currencyRepository->findNull($data['currency_id']);
|
/** @var TransactionCurrencyFactory $factory */
|
||||||
|
$factory = app(TransactionCurrencyFactory::class);
|
||||||
|
$currency = $factory->find($data['currency_id'], $data['currency_code']);
|
||||||
|
|
||||||
if (null === $currency) {
|
if (null === $currency) {
|
||||||
$currency = $this->currencyRepository->findByCodeNull($data['currency_code']);
|
$currency = app('amount')->getDefaultCurrency();
|
||||||
}
|
}
|
||||||
if (null === $currency) {
|
$availableBudget = $this->repository->setAvailableBudget($currency, $data['start'], $data['end'], $data['amount']);
|
||||||
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;
|
$manager = new Manager;
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($availableBudget, new AvailableBudgetTransformer($this->parameters), 'available_budgets');
|
/** @var AvailableBudgetTransformer $transformer */
|
||||||
|
$transformer = app(AvailableBudgetTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($availableBudget, $transformer, 'available_budgets');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the specified resource in storage.
|
* Update the specified resource in storage.
|
||||||
*
|
*
|
||||||
* @param AvailableBudgetRequest $request
|
* @param AvailableBudgetRequest $request
|
||||||
* @param AvailableBudget $availableBudget
|
* @param AvailableBudget $availableBudget
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function update(AvailableBudgetRequest $request, AvailableBudget $availableBudget): JsonResponse
|
public function update(AvailableBudgetRequest $request, AvailableBudget $availableBudget): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
|
|
||||||
|
/** @var TransactionCurrencyFactory $factory */
|
||||||
|
$factory = app(TransactionCurrencyFactory::class);
|
||||||
|
/** @var TransactionCurrency $currency */
|
||||||
|
$currency = $factory->find($data['currency_id'] ?? null, $data['currency_code'] ?? null);
|
||||||
|
|
||||||
|
if (null === $currency) {
|
||||||
|
// use default currency:
|
||||||
|
$currency = app('amount')->getDefaultCurrency();
|
||||||
|
}
|
||||||
|
$currency->enabled = true;
|
||||||
|
$currency->save();
|
||||||
|
unset($data['currency_code']);
|
||||||
|
$data['currency_id'] = $currency->id;
|
||||||
|
|
||||||
|
|
||||||
$this->repository->updateAvailableBudget($availableBudget, $data);
|
$this->repository->updateAvailableBudget($availableBudget, $data);
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($availableBudget, new AvailableBudgetTransformer($this->parameters), 'available_budgets');
|
/** @var AvailableBudgetTransformer $transformer */
|
||||||
|
$transformer = app(AvailableBudgetTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($availableBudget, $transformer, 'available_budgets');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,18 @@ namespace FireflyIII\Api\V1\Controllers;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Requests\BillRequest;
|
use FireflyIII\Api\V1\Requests\BillRequest;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Models\Bill;
|
use FireflyIII\Models\Bill;
|
||||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||||
|
use FireflyIII\Transformers\AttachmentTransformer;
|
||||||
use FireflyIII\Transformers\BillTransformer;
|
use FireflyIII\Transformers\BillTransformer;
|
||||||
|
use FireflyIII\Transformers\RuleTransformer;
|
||||||
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use League\Fractal\Manager;
|
use League\Fractal\Manager;
|
||||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||||
@@ -41,14 +47,19 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BillController.
|
* Class BillController.
|
||||||
|
*
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
class BillController extends Controller
|
class BillController extends Controller
|
||||||
{
|
{
|
||||||
|
use TransactionFilter;
|
||||||
/** @var BillRepositoryInterface The bill repository */
|
/** @var BillRepositoryInterface The bill repository */
|
||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BillController constructor.
|
* BillController constructor.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -68,11 +79,50 @@ class BillController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the specified resource from storage.
|
* Display a listing of the resource.
|
||||||
*
|
*
|
||||||
* @param Bill $bill
|
* @param Request $request
|
||||||
|
* @param Bill $bill
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function attachments(Request $request, Bill $bill): JsonResponse
|
||||||
|
{
|
||||||
|
$manager = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
$collection = $this->repository->getAttachments($bill);
|
||||||
|
|
||||||
|
$count = $collection->count();
|
||||||
|
$attachments = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
|
||||||
|
// make paginator:
|
||||||
|
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
$paginator->setPath(route('api.v1.bills.attachments', [$bill->id]) . $this->buildParams());
|
||||||
|
|
||||||
|
// present to user.
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var AttachmentTransformer $transformer */
|
||||||
|
$transformer = app(AttachmentTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new FractalCollection($attachments, $transformer, 'attachments');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param Bill $bill
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function delete(Bill $bill): JsonResponse
|
public function delete(Bill $bill): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -87,6 +137,7 @@ class BillController extends Controller
|
|||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -99,32 +150,78 @@ class BillController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new FractalCollection($bills, new BillTransformer($this->parameters), 'bills');
|
/** @var BillTransformer $transformer */
|
||||||
|
$transformer = app(BillTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new FractalCollection($bills, $transformer, 'bills');
|
||||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all of them.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param Bill $bill
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function rules(Request $request, Bill $bill): JsonResponse
|
||||||
|
{
|
||||||
|
// create some objects:
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
|
||||||
|
// types to get, page size:
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
|
// get list of budgets. Count it and split it.
|
||||||
|
$collection = $this->repository->getRulesForBill($bill);
|
||||||
|
$count = $collection->count();
|
||||||
|
$rules = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
|
||||||
|
// make paginator:
|
||||||
|
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
$paginator->setPath(route('api.v1.bills.rules', [$bill->id]) . $this->buildParams());
|
||||||
|
|
||||||
|
// present to user.
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var RuleTransformer $transformer */
|
||||||
|
$transformer = app(RuleTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
|
||||||
|
$resource = new FractalCollection($rules, $transformer, 'rules');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the specified bill.
|
* Show the specified bill.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Bill $bill
|
* @param Bill $bill
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, Bill $bill): JsonResponse
|
public function show(Request $request, Bill $bill): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($bill, new BillTransformer($this->parameters), 'bills');
|
/** @var BillTransformer $transformer */
|
||||||
|
$transformer = app(BillTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($bill, $transformer, 'bills');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -145,7 +242,11 @@ class BillController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($bill, new BillTransformer($this->parameters), 'bills');
|
/** @var BillTransformer $transformer */
|
||||||
|
$transformer = app(BillTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($bill, $transformer, 'bills');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -153,12 +254,71 @@ 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 = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @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.
|
* Update a bill.
|
||||||
*
|
*
|
||||||
* @param BillRequest $request
|
* @param BillRequest $request
|
||||||
* @param Bill $bill
|
* @param Bill $bill
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
@@ -170,7 +330,11 @@ class BillController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($bill, new BillTransformer($this->parameters), 'bills');
|
/** @var BillTransformer $transformer */
|
||||||
|
$transformer = app(BillTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($bill, $transformer, 'bills');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
|||||||
@@ -23,11 +23,17 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Controllers;
|
namespace FireflyIII\Api\V1\Controllers;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
|
||||||
use FireflyIII\Api\V1\Requests\BudgetRequest;
|
use FireflyIII\Api\V1\Requests\BudgetRequest;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||||
|
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||||
use FireflyIII\Transformers\BudgetTransformer;
|
use FireflyIII\Transformers\BudgetTransformer;
|
||||||
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -41,15 +47,18 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
|||||||
/**
|
/**
|
||||||
* Class BudgetController.
|
* Class BudgetController.
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
*
|
||||||
*/
|
*/
|
||||||
class BudgetController extends Controller
|
class BudgetController extends Controller
|
||||||
{
|
{
|
||||||
|
use TransactionFilter;
|
||||||
/** @var BudgetRepositoryInterface The budget repository */
|
/** @var BudgetRepositoryInterface The budget repository */
|
||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BudgetController constructor.
|
* BudgetController constructor.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -68,12 +77,46 @@ class BudgetController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
* @param Request $request
|
||||||
|
* @param Budget $budget
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function budgetLimits(Request $request, Budget $budget): JsonResponse
|
||||||
|
{
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
$this->parameters->set('budget_id', $budget->id);
|
||||||
|
$collection = $this->repository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end'));
|
||||||
|
$count = $collection->count();
|
||||||
|
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
$paginator->setPath(route('api.v1.budgets.budget_limits', [$budget->id]) . $this->buildParams());
|
||||||
|
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var BudgetLimitTransformer $transformer */
|
||||||
|
$transformer = app(BudgetLimitTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
|
||||||
|
$resource = new FractalCollection($budgetLimits, $transformer, 'budget_limits');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the specified resource from storage.
|
* Remove the specified resource from storage.
|
||||||
*
|
*
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function delete(Budget $budget): JsonResponse
|
public function delete(Budget $budget): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -88,6 +131,7 @@ class BudgetController extends Controller
|
|||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -109,32 +153,37 @@ class BudgetController extends Controller
|
|||||||
|
|
||||||
// present to user.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a budget.
|
* Show a budget.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, Budget $budget): JsonResponse
|
public function show(Request $request, Budget $budget): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($budget, new BudgetTransformer($this->parameters), 'budgets');
|
/** @var BudgetTransformer $transformer */
|
||||||
|
$transformer = app(BudgetTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($budget, $transformer, 'budgets');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -146,6 +195,7 @@ class BudgetController extends Controller
|
|||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function store(BudgetRequest $request): JsonResponse
|
public function store(BudgetRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -155,19 +205,114 @@ class BudgetController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($budget, new BudgetTransformer($this->parameters), 'budgets');
|
/** @var BudgetTransformer $transformer */
|
||||||
|
$transformer = app(BudgetTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($budget, $transformer, 'budgets');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
throw new FireflyException('Could not store new budget.'); // @codeCoverageIgnore
|
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->repository->storeBudgetLimit($data);
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var BudgetLimitTransformer $transformer */
|
||||||
|
$transformer = app(BudgetLimitTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($budgetLimit, $transformer, 'budget_limits');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show all transactions.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @param Budget $budget
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @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 = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @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.
|
* Update a budget.
|
||||||
*
|
*
|
||||||
* @param BudgetRequest $request
|
* @param BudgetRequest $request
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
@@ -179,7 +324,11 @@ class BudgetController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($budget, new BudgetTransformer($this->parameters), 'budgets');
|
/** @var BudgetTransformer $transformer */
|
||||||
|
$transformer = app(BudgetTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($budget, $transformer, 'budgets');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
|||||||
@@ -26,9 +26,12 @@ namespace FireflyIII\Api\V1\Controllers;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
|
use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Models\BudgetLimit;
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||||
use FireflyIII\Transformers\BudgetLimitTransformer;
|
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||||
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -40,19 +43,21 @@ use League\Fractal\Resource\Collection as FractalCollection;
|
|||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
use League\Fractal\Serializer\JsonApiSerializer;
|
use League\Fractal\Serializer\JsonApiSerializer;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BudgetLimitController.
|
* Class BudgetLimitController.
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
*
|
||||||
*/
|
*/
|
||||||
class BudgetLimitController extends Controller
|
class BudgetLimitController extends Controller
|
||||||
{
|
{
|
||||||
|
use TransactionFilter;
|
||||||
/** @var BudgetRepositoryInterface The budget repository */
|
/** @var BudgetRepositoryInterface The budget repository */
|
||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AccountController constructor.
|
* BudgetLimitController constructor.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -75,6 +80,7 @@ class BudgetLimitController extends Controller
|
|||||||
* @param BudgetLimit $budgetLimit
|
* @param BudgetLimit $budgetLimit
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function delete(BudgetLimit $budgetLimit): JsonResponse
|
public function delete(BudgetLimit $budgetLimit): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -89,6 +95,7 @@ class BudgetLimitController extends Controller
|
|||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -113,7 +120,12 @@ class BudgetLimitController extends Controller
|
|||||||
$paginator->setPath(route('api.v1.budget_limits.index') . $this->buildParams());
|
$paginator->setPath(route('api.v1.budget_limits.index') . $this->buildParams());
|
||||||
|
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
@@ -122,22 +134,23 @@ class BudgetLimitController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Display the specified resource.
|
* Display the specified resource.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param BudgetLimit $budgetLimit
|
* @param BudgetLimit $budgetLimit
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, BudgetLimit $budgetLimit): JsonResponse
|
public function show(Request $request, BudgetLimit $budgetLimit): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
|
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
$resource = new Item($budgetLimit, new BudgetLimitTransformer($this->parameters), 'budget_limits');
|
|
||||||
|
/** @var BudgetLimitTransformer $transformer */
|
||||||
|
$transformer = app(BudgetLimitTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($budgetLimit, $transformer, 'budget_limits');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -149,6 +162,7 @@ class BudgetLimitController extends Controller
|
|||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function store(BudgetLimitRequest $request): JsonResponse
|
public function store(BudgetLimitRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -163,7 +177,66 @@ class BudgetLimitController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($budgetLimit, new BudgetLimitTransformer($this->parameters), 'budget_limits');
|
/** @var BudgetLimitTransformer $transformer */
|
||||||
|
$transformer = app(BudgetLimitTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($budgetLimit, $transformer, 'budget_limits');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show all transactions.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param BudgetLimit $budgetLimit
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @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 = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @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');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -172,24 +245,24 @@ class BudgetLimitController extends Controller
|
|||||||
* Update the specified resource in storage.
|
* Update the specified resource in storage.
|
||||||
*
|
*
|
||||||
* @param BudgetLimitRequest $request
|
* @param BudgetLimitRequest $request
|
||||||
* @param BudgetLimit $budgetLimit
|
* @param BudgetLimit $budgetLimit
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function update(BudgetLimitRequest $request, BudgetLimit $budgetLimit): JsonResponse
|
public function update(BudgetLimitRequest $request, BudgetLimit $budgetLimit): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$budget = $this->repository->findNull($data['budget_id']);
|
$data['budget'] = $budgetLimit->budget;
|
||||||
if (null === $budget) {
|
|
||||||
$budget = $budgetLimit->budget;
|
|
||||||
}
|
|
||||||
$data['budget'] = $budget;
|
|
||||||
$budgetLimit = $this->repository->updateBudgetLimit($budgetLimit, $data);
|
$budgetLimit = $this->repository->updateBudgetLimit($budgetLimit, $data);
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($budgetLimit, new BudgetLimitTransformer($this->parameters), 'budget_limits');
|
/** @var BudgetLimitTransformer $transformer */
|
||||||
|
$transformer = app(BudgetLimitTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($budgetLimit, $transformer, 'budget_limits');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,12 @@ namespace FireflyIII\Api\V1\Controllers;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Requests\CategoryRequest;
|
use FireflyIII\Api\V1\Requests\CategoryRequest;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Models\Category;
|
use FireflyIII\Models\Category;
|
||||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||||
use FireflyIII\Transformers\CategoryTransformer;
|
use FireflyIII\Transformers\CategoryTransformer;
|
||||||
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -41,15 +44,18 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
|||||||
/**
|
/**
|
||||||
* Class CategoryController.
|
* Class CategoryController.
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
*
|
||||||
*/
|
*/
|
||||||
class CategoryController extends Controller
|
class CategoryController extends Controller
|
||||||
{
|
{
|
||||||
|
use TransactionFilter;
|
||||||
/** @var CategoryRepositoryInterface The category repository */
|
/** @var CategoryRepositoryInterface The category repository */
|
||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CategoryController constructor.
|
* CategoryController constructor.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -74,6 +80,7 @@ class CategoryController extends Controller
|
|||||||
* @param Category $category
|
* @param Category $category
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function delete(Category $category): JsonResponse
|
public function delete(Category $category): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -88,6 +95,7 @@ class CategoryController extends Controller
|
|||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -109,7 +117,13 @@ class CategoryController extends Controller
|
|||||||
|
|
||||||
// present to user.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
@@ -119,22 +133,23 @@ class CategoryController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Show the category.
|
* Show the category.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Category $category
|
* @param Category $category
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, Category $category): JsonResponse
|
public function show(Request $request, Category $category): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($category, new CategoryTransformer($this->parameters), 'categories');
|
/** @var CategoryTransformer $transformer */
|
||||||
|
$transformer = app(CategoryTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($category, $transformer, 'categories');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -155,19 +170,80 @@ class CategoryController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($category, new CategoryTransformer($this->parameters), 'categories');
|
/** @var CategoryTransformer $transformer */
|
||||||
|
$transformer = app(CategoryTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($category, $transformer, 'categories');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
throw new FireflyException('Could not store new category.'); // @codeCoverageIgnore
|
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 = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @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.
|
* Update the category.
|
||||||
*
|
*
|
||||||
* @param CategoryRequest $request
|
* @param CategoryRequest $request
|
||||||
* @param Category $category
|
* @param Category $category
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
@@ -179,7 +255,11 @@ class CategoryController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($category, new CategoryTransformer($this->parameters), 'categories');
|
/** @var CategoryTransformer $transformer */
|
||||||
|
$transformer = app(CategoryTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($category, $transformer, 'categories');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
|||||||
306
app/Api/V1/Controllers/Chart/AccountController.php
Normal file
306
app/Api/V1/Controllers/Chart/AccountController.php
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
<?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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
112
app/Api/V1/Controllers/Chart/AvailableBudgetController.php
Normal file
112
app/Api/V1/Controllers/Chart/AvailableBudgetController.php
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<?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\User;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class AvailableBudgetController
|
||||||
|
*/
|
||||||
|
class AvailableBudgetController extends Controller
|
||||||
|
{
|
||||||
|
/** @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->repository->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->repository->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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
210
app/Api/V1/Controllers/Chart/CategoryController.php
Normal file
210
app/Api/V1/Controllers/Chart/CategoryController.php
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
<?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\User;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CategoryController
|
||||||
|
*/
|
||||||
|
class CategoryController extends Controller
|
||||||
|
{
|
||||||
|
/** @var CategoryRepositoryInterface */
|
||||||
|
private $categoryRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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->categoryRepository->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 = [];
|
||||||
|
$spent = $this->categoryRepository->spentInPeriodPerCurrency(new Collection, new Collection, $start, $end);
|
||||||
|
$earned = $this->categoryRepository->earnedInPeriodPerCurrency(new Collection, new Collection, $start, $end);
|
||||||
|
$categories = [];
|
||||||
|
|
||||||
|
// earned:
|
||||||
|
foreach ($earned as $categoryId => $row) {
|
||||||
|
$categoryName = $row['name'];
|
||||||
|
foreach ($row['earned'] as $currencyId => $income) {
|
||||||
|
// find or make set for currency:
|
||||||
|
$key = sprintf('%s-e', $currencyId);
|
||||||
|
$decimalPlaces = $income['currency_decimal_places'];
|
||||||
|
if (!isset($tempData[$key])) {
|
||||||
|
$tempData[$key] = [
|
||||||
|
'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $income['currency_symbol']]),
|
||||||
|
'currency_id' => $income['currency_id'],
|
||||||
|
'currency_code' => $income['currency_code'],
|
||||||
|
'currency_symbol' => $income['currency_symbol'],
|
||||||
|
'currency_decimal_places' => $decimalPlaces,
|
||||||
|
'type' => 'bar', // line, area or bar
|
||||||
|
'yAxisID' => 0, // 0, 1, 2
|
||||||
|
'entries' => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$amount = round($income['earned'], $decimalPlaces);
|
||||||
|
$categories[$categoryName] = isset($categories[$categoryName]) ? $categories[$categoryName] + $amount : $amount;
|
||||||
|
$tempData[$key]['entries'][$categoryName]
|
||||||
|
= $amount;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// earned with no category:
|
||||||
|
$noCategory = $this->categoryRepository->earnedInPeriodPcWoCategory(new Collection, $start, $end);
|
||||||
|
foreach ($noCategory as $currencyId => $income) {
|
||||||
|
$categoryName = (string)trans('firefly.no_category');
|
||||||
|
// find or make set for currency:
|
||||||
|
$key = sprintf('%s-e', $currencyId);
|
||||||
|
$decimalPlaces = $income['currency_decimal_places'];
|
||||||
|
if (!isset($tempData[$key])) {
|
||||||
|
$tempData[$key] = [
|
||||||
|
'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $income['currency_symbol']]),
|
||||||
|
'currency_id' => $income['currency_id'],
|
||||||
|
'currency_code' => $income['currency_code'],
|
||||||
|
'currency_symbol' => $income['currency_symbol'],
|
||||||
|
'currency_decimal_places' => $decimalPlaces,
|
||||||
|
'type' => 'bar', // line, area or bar
|
||||||
|
'yAxisID' => 0, // 0, 1, 2
|
||||||
|
'entries' => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$amount = round($income['earned'], $decimalPlaces);
|
||||||
|
$categories[$categoryName] = isset($categories[$categoryName]) ? $categories[$categoryName] + $amount : $amount;
|
||||||
|
$tempData[$key]['entries'][$categoryName]
|
||||||
|
= $amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// spent
|
||||||
|
foreach ($spent as $categoryId => $row) {
|
||||||
|
$categoryName = $row['name'];
|
||||||
|
// create a new set if necessary, "spent (EUR)":
|
||||||
|
foreach ($row['spent'] as $currencyId => $expense) {
|
||||||
|
// find or make set for currency:
|
||||||
|
$key = sprintf('%s-s', $currencyId);
|
||||||
|
$decimalPlaces = $expense['currency_decimal_places'];
|
||||||
|
if (!isset($tempData[$key])) {
|
||||||
|
$tempData[$key] = [
|
||||||
|
'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $expense['currency_symbol']]),
|
||||||
|
'currency_id' => $expense['currency_id'],
|
||||||
|
'currency_code' => $expense['currency_code'],
|
||||||
|
'currency_symbol' => $expense['currency_symbol'],
|
||||||
|
'currency_decimal_places' => $decimalPlaces,
|
||||||
|
'type' => 'bar', // line, area or bar
|
||||||
|
'yAxisID' => 0, // 0, 1, 2
|
||||||
|
'entries' => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$amount = round($expense['spent'], $decimalPlaces);
|
||||||
|
$categories[$categoryName] = isset($categories[$categoryName]) ? $categories[$categoryName] + $amount : $amount;
|
||||||
|
$tempData[$key]['entries'][$categoryName]
|
||||||
|
= $amount;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// spent with no category
|
||||||
|
$noCategory = $this->categoryRepository->spentInPeriodPcWoCategory(new Collection, $start, $end);
|
||||||
|
foreach ($noCategory as $currencyId => $expense) {
|
||||||
|
$categoryName = (string)trans('firefly.no_category');
|
||||||
|
// find or make set for currency:
|
||||||
|
$key = sprintf('%s-s', $currencyId);
|
||||||
|
$decimalPlaces = $expense['currency_decimal_places'];
|
||||||
|
if (!isset($tempData[$key])) {
|
||||||
|
$tempData[$key] = [
|
||||||
|
'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $expense['currency_symbol']]),
|
||||||
|
'currency_id' => $expense['currency_id'],
|
||||||
|
'currency_code' => $expense['currency_code'],
|
||||||
|
'currency_symbol' => $expense['currency_symbol'],
|
||||||
|
'currency_decimal_places' => $decimalPlaces,
|
||||||
|
'type' => 'bar', // line, area or bar
|
||||||
|
'yAxisID' => 0, // 0, 1, 2
|
||||||
|
'entries' => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$amount = round($expense['spent'], $decimalPlaces);
|
||||||
|
$categories[$categoryName] = isset($categories[$categoryName]) ? $categories[$categoryName] + $amount : $amount;
|
||||||
|
$tempData[$key]['entries'][$categoryName]
|
||||||
|
= $amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
asort($categories);
|
||||||
|
$keys = array_keys($categories);
|
||||||
|
|
||||||
|
// re-sort every spent array and add 0 for missing entries.
|
||||||
|
foreach ($tempData as $index => $set) {
|
||||||
|
$oldSet = $set['entries'];
|
||||||
|
$newSet = [];
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
$value = $oldSet[$key] ?? 0;
|
||||||
|
$value = $value < 0 ? $value * -1 : $value;
|
||||||
|
$newSet[$key] = $value;
|
||||||
|
}
|
||||||
|
$tempData[$index]['entries'] = $newSet;
|
||||||
|
}
|
||||||
|
$chartData = array_values($tempData);
|
||||||
|
|
||||||
|
return response()->json($chartData);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,15 +23,16 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Controllers;
|
namespace FireflyIII\Api\V1\Controllers;
|
||||||
|
|
||||||
|
use FireflyIII\Api\V1\Requests\ConfigurationRequest;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\Configuration;
|
use FireflyIII\Models\Configuration;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ConfigurationController.
|
* Class ConfigurationController.
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
class ConfigurationController extends Controller
|
class ConfigurationController extends Controller
|
||||||
{
|
{
|
||||||
@@ -41,7 +42,8 @@ class ConfigurationController extends Controller
|
|||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BudgetController constructor.
|
* ConfigurationController constructor.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -54,7 +56,6 @@ class ConfigurationController extends Controller
|
|||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
|
|
||||||
if (!$this->repository->hasRole($admin, 'owner')) {
|
if (!$this->repository->hasRole($admin, 'owner')) {
|
||||||
/** @noinspection ExceptionsAnnotatingAndHandlingInspection */
|
|
||||||
throw new FireflyException('No access to method.'); // @codeCoverageIgnore
|
throw new FireflyException('No access to method.'); // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,47 +73,30 @@ class ConfigurationController extends Controller
|
|||||||
{
|
{
|
||||||
$configData = $this->getConfigData();
|
$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.
|
* Update the configuration.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param ConfigurationRequest $request
|
||||||
|
* @param string $name
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @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');
|
$data = $request->getAll();
|
||||||
$value = $request->get('value');
|
app('fireflyconfig')->set($name, $data['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);
|
|
||||||
$configData = $this->getConfigData();
|
$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.
|
* Get all config values.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
|
||||||
*/
|
*/
|
||||||
private function getConfigData(): array
|
private function getConfigData(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ use Symfony\Component\HttpFoundation\ParameterBag;
|
|||||||
* Class Controller.
|
* Class Controller.
|
||||||
*
|
*
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* @SuppressWarnings(PHPMD.NumberOfChildren)
|
*
|
||||||
*/
|
*/
|
||||||
class Controller extends BaseController
|
class Controller extends BaseController
|
||||||
{
|
{
|
||||||
@@ -61,7 +61,6 @@ class Controller extends BaseController
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
|
||||||
*/
|
*/
|
||||||
protected function buildParams(): string
|
protected function buildParams(): string
|
||||||
{
|
{
|
||||||
@@ -86,7 +85,6 @@ class Controller extends BaseController
|
|||||||
* Method to grab all parameters from the URI.
|
* Method to grab all parameters from the URI.
|
||||||
*
|
*
|
||||||
* @return ParameterBag
|
* @return ParameterBag
|
||||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
|
||||||
*/
|
*/
|
||||||
private function getParameters(): ParameterBag
|
private function getParameters(): ParameterBag
|
||||||
{
|
{
|
||||||
@@ -100,11 +98,11 @@ class Controller extends BaseController
|
|||||||
// some date fields:
|
// some date fields:
|
||||||
$dates = ['start', 'end', 'date'];
|
$dates = ['start', 'end', 'date'];
|
||||||
foreach ($dates as $field) {
|
foreach ($dates as $field) {
|
||||||
$date = request()->get($field);
|
$date = request()->query->get($field);
|
||||||
$obj = null;
|
$obj = null;
|
||||||
if (null !== $date) {
|
if (null !== $date) {
|
||||||
try {
|
try {
|
||||||
$obj = new Carbon($date);
|
$obj = Carbon::parse($date);
|
||||||
} catch (InvalidDateException $e) {
|
} catch (InvalidDateException $e) {
|
||||||
// don't care
|
// don't care
|
||||||
Log::error(sprintf('Invalid date exception in API controller: %s', $e->getMessage()));
|
Log::error(sprintf('Invalid date exception in API controller: %s', $e->getMessage()));
|
||||||
@@ -113,6 +111,15 @@ class Controller extends BaseController
|
|||||||
$bag->set($field, $obj);
|
$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;
|
return $bag;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,14 +26,37 @@ namespace FireflyIII\Api\V1\Controllers;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Requests\CurrencyRequest;
|
use FireflyIII\Api\V1\Requests\CurrencyRequest;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
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\Models\TransactionCurrency;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
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\CurrencyTransformer;
|
||||||
|
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||||
|
use FireflyIII\Transformers\RuleTransformer;
|
||||||
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
use League\Fractal\Manager;
|
use League\Fractal\Manager;
|
||||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||||
use League\Fractal\Resource\Collection as FractalCollection;
|
use League\Fractal\Resource\Collection as FractalCollection;
|
||||||
@@ -43,10 +66,11 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
|||||||
/**
|
/**
|
||||||
* Class CurrencyController.
|
* Class CurrencyController.
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
*
|
||||||
*/
|
*/
|
||||||
class CurrencyController extends Controller
|
class CurrencyController extends Controller
|
||||||
{
|
{
|
||||||
|
use AccountFilter, TransactionFilter;
|
||||||
/** @var CurrencyRepositoryInterface The currency repository */
|
/** @var CurrencyRepositoryInterface The currency repository */
|
||||||
private $repository;
|
private $repository;
|
||||||
/** @var UserRepositoryInterface The user repository */
|
/** @var UserRepositoryInterface The user repository */
|
||||||
@@ -54,6 +78,7 @@ class CurrencyController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* CurrencyRepository constructor.
|
* CurrencyRepository constructor.
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -73,13 +98,240 @@ 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
|
||||||
|
{
|
||||||
|
// create some objects:
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
|
||||||
|
// read type from URI
|
||||||
|
$type = $request->get('type') ?? 'all';
|
||||||
|
$this->parameters->set('type', $type);
|
||||||
|
|
||||||
|
// types to get, page size:
|
||||||
|
$types = $this->mapAccountTypes($this->parameters->get('type'));
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
|
// get list of accounts. Count it and split it.
|
||||||
|
/** @var AccountRepositoryInterface $accountRepository */
|
||||||
|
$accountRepository = app(AccountRepositoryInterface::class);
|
||||||
|
$unfiltered = $accountRepository->getAccountsByType($types);
|
||||||
|
|
||||||
|
// filter list on currency preference:
|
||||||
|
$collection = $unfiltered->filter(
|
||||||
|
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());
|
||||||
|
|
||||||
|
// present to user.
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var AccountTransformer $transformer */
|
||||||
|
$transformer = app(AccountTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
|
||||||
|
$resource = new FractalCollection($accounts, $transformer, 'accounts');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function availableBudgets(Request $request, TransactionCurrency $currency): JsonResponse
|
||||||
|
{
|
||||||
|
/** @var User $admin */
|
||||||
|
$admin = auth()->user();
|
||||||
|
|
||||||
|
// create some objects:
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
|
||||||
|
// types to get, page size:
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
|
// get list of available budgets. Count it and split it.
|
||||||
|
|
||||||
|
/** @var BudgetRepositoryInterface $repository */
|
||||||
|
$repository = app(BudgetRepositoryInterface::class);
|
||||||
|
$repository->setUser($admin);
|
||||||
|
$collection = $repository->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());
|
||||||
|
|
||||||
|
// present to user.
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var AvailableBudgetTransformer $transformer */
|
||||||
|
$transformer = app(AvailableBudgetTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new FractalCollection($availableBudgets, $transformer, 'available_budgets');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all bills
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function bills(Request $request, TransactionCurrency $currency): JsonResponse
|
||||||
|
{
|
||||||
|
// create some objects:
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
|
||||||
|
/** @var BillRepositoryInterface $repository */
|
||||||
|
$repository = app(BillRepositoryInterface::class);
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
$paginator = $repository->getPaginator($pageSize);
|
||||||
|
/** @var Collection $bills */
|
||||||
|
$unfiltered = $paginator->getCollection();
|
||||||
|
|
||||||
|
// filter and paginate list:
|
||||||
|
$collection = $unfiltered->filter(
|
||||||
|
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());
|
||||||
|
|
||||||
|
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var BillTransformer $transformer */
|
||||||
|
$transformer = app(BillTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new FractalCollection($bills, $transformer, 'bills');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all budget limits
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function budgetLimits(Request $request, TransactionCurrency $currency): JsonResponse
|
||||||
|
{
|
||||||
|
/** @var BudgetRepositoryInterface $repository */
|
||||||
|
$repository = app(BudgetRepositoryInterface::class);
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
$collection = $repository->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());
|
||||||
|
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var BudgetLimitTransformer $transformer */
|
||||||
|
$transformer = app(BudgetLimitTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new FractalCollection($budgetLimits, $transformer, 'budget_limits');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a list of known exchange rates
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function cer(Request $request, TransactionCurrency $currency): JsonResponse
|
||||||
|
{
|
||||||
|
// create some objects:
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
$collection = $this->repository->getExchangeRates($currency);
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
|
||||||
|
$count = $collection->count();
|
||||||
|
$exchangeRates = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
$paginator = new LengthAwarePaginator($exchangeRates, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
$paginator->setPath(route('api.v1.currencies.cer', [$currency->code]) . $this->buildParams());
|
||||||
|
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var CurrencyExchangeRateTransformer $transformer */
|
||||||
|
$transformer = app(CurrencyExchangeRateTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new FractalCollection($exchangeRates, $transformer, 'currency_exchange_rates');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the specified resource from storage.
|
* Remove the specified resource from storage.
|
||||||
*
|
*
|
||||||
* @param TransactionCurrency $currency
|
* @param TransactionCurrency $currency
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function delete(TransactionCurrency $currency): JsonResponse
|
public function delete(TransactionCurrency $currency): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -90,7 +342,7 @@ class CurrencyController extends Controller
|
|||||||
// access denied:
|
// access denied:
|
||||||
throw new FireflyException('No access to method, user is not owner.'); // @codeCoverageIgnore
|
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
|
throw new FireflyException('No access to method, currency is in use.'); // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
$this->repository->destroy($currency);
|
$this->repository->destroy($currency);
|
||||||
@@ -98,17 +350,80 @@ class CurrencyController extends Controller
|
|||||||
return response()->json([], 204);
|
return response()->json([], 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable a currency.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function disable(Request $request, TransactionCurrency $currency): JsonResponse
|
||||||
|
{
|
||||||
|
// must be unused.
|
||||||
|
if ($this->repository->currencyInUse($currency)) {
|
||||||
|
return response()->json([], 409);
|
||||||
|
}
|
||||||
|
$this->repository->disable($currency);
|
||||||
|
$manager = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||||
|
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
||||||
|
|
||||||
|
/** @var CurrencyTransformer $transformer */
|
||||||
|
$transformer = app(CurrencyTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($currency, $transformer, 'currencies');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable a currency.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function enable(Request $request, TransactionCurrency $currency): JsonResponse
|
||||||
|
{
|
||||||
|
$this->repository->enable($currency);
|
||||||
|
$manager = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||||
|
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
||||||
|
|
||||||
|
/** @var CurrencyTransformer $transformer */
|
||||||
|
$transformer = app(CurrencyTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($currency, $transformer, 'currencies');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
$collection = $this->repository->get();
|
$collection = $this->repository->getAll();
|
||||||
$count = $collection->count();
|
$count = $collection->count();
|
||||||
// slice them:
|
// slice them:
|
||||||
$currencies = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
$currencies = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
@@ -122,34 +437,184 @@ class CurrencyController extends Controller
|
|||||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||||
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the currency a default currency.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function makeDefault(Request $request, TransactionCurrency $currency): JsonResponse
|
||||||
|
{
|
||||||
|
$this->repository->enable($currency);
|
||||||
|
|
||||||
|
app('preferences')->set('currencyPreference', $currency->code);
|
||||||
|
app('preferences')->mark();
|
||||||
|
|
||||||
|
$manager = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
$this->parameters->set('defaultCurrency', $currency);
|
||||||
|
|
||||||
|
/** @var CurrencyTransformer $transformer */
|
||||||
|
$transformer = app(CurrencyTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($currency, $transformer, 'currencies');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all recurring transactions.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function recurrences(Request $request, TransactionCurrency $currency): JsonResponse
|
||||||
|
{
|
||||||
|
// create some objects:
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
|
||||||
|
// types to get, page size:
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
|
// get list of budgets. Count it and split it.
|
||||||
|
/** @var RecurringRepositoryInterface $repository */
|
||||||
|
$repository = app(RecurringRepositoryInterface::class);
|
||||||
|
$unfiltered = $repository->getAll();
|
||||||
|
|
||||||
|
// filter selection
|
||||||
|
$collection = $unfiltered->filter(
|
||||||
|
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());
|
||||||
|
|
||||||
|
// present to user.
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var RecurrenceTransformer $transformer */
|
||||||
|
$transformer = app(RecurrenceTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new FractalCollection($piggyBanks, $transformer, 'recurrences');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all of them.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function rules(Request $request, TransactionCurrency $currency): JsonResponse
|
||||||
|
{
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
|
// get list of budgets. Count it and split it.
|
||||||
|
/** @var RuleRepositoryInterface $repository */
|
||||||
|
$repository = app(RuleRepositoryInterface::class);
|
||||||
|
$unfiltered = $repository->getAll();
|
||||||
|
|
||||||
|
$collection = $unfiltered->filter(
|
||||||
|
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());
|
||||||
|
|
||||||
|
// present to user.
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var RuleTransformer $transformer */
|
||||||
|
$transformer = app(RuleTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new FractalCollection($rules, $transformer, 'rules');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a currency.
|
* Show a currency.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param TransactionCurrency $currency
|
* @param TransactionCurrency $currency
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, TransactionCurrency $currency): JsonResponse
|
public function show(Request $request, TransactionCurrency $currency): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||||
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
$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');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -177,7 +642,11 @@ class CurrencyController extends Controller
|
|||||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||||
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
$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');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -185,11 +654,68 @@ 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 = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @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.
|
* Update a currency.
|
||||||
*
|
*
|
||||||
* @param CurrencyRequest $request
|
* @param CurrencyRequest $request
|
||||||
* @param TransactionCurrency $currency
|
* @param TransactionCurrency $currency
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
@@ -211,7 +737,11 @@ class CurrencyController extends Controller
|
|||||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
|
||||||
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
$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');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CurrencyExchangeRateController
|
* Class CurrencyExchangeRateController
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
class CurrencyExchangeRateController extends Controller
|
class CurrencyExchangeRateController extends Controller
|
||||||
{
|
{
|
||||||
@@ -45,6 +46,7 @@ class CurrencyExchangeRateController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* CurrencyExchangeRateController constructor.
|
* CurrencyExchangeRateController constructor.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -88,10 +90,12 @@ class CurrencyExchangeRateController extends Controller
|
|||||||
throw new FireflyException('Unknown destination currency.');
|
throw new FireflyException('Unknown destination currency.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var Carbon $dateObj */
|
||||||
$dateObj = Carbon::createFromFormat('Y-m-d', $request->get('date') ?? date('Y-m-d'));
|
$dateObj = Carbon::createFromFormat('Y-m-d', $request->get('date') ?? date('Y-m-d'));
|
||||||
$this->parameters->set('from', $fromCurrency->code);
|
$this->parameters->set('from', $fromCurrency->code);
|
||||||
$this->parameters->set('to', $toCurrency->code);
|
$this->parameters->set('to', $toCurrency->code);
|
||||||
$this->parameters->set('date', $dateObj->format('Y-m-d'));
|
$this->parameters->set('date', $dateObj->format('Y-m-d'));
|
||||||
|
$this->parameters->set('amount', $request->get('amount'));
|
||||||
|
|
||||||
$rate = $this->repository->getExchangeRate($fromCurrency, $toCurrency, $dateObj);
|
$rate = $this->repository->getExchangeRate($fromCurrency, $toCurrency, $dateObj);
|
||||||
if (null === $rate) {
|
if (null === $rate) {
|
||||||
@@ -103,8 +107,10 @@ class CurrencyExchangeRateController extends Controller
|
|||||||
$service->setUser($admin);
|
$service->setUser($admin);
|
||||||
$rate = $service->getRate($fromCurrency, $toCurrency, $dateObj);
|
$rate = $service->getRate($fromCurrency, $toCurrency, $dateObj);
|
||||||
}
|
}
|
||||||
|
/** @var CurrencyExchangeRateTransformer $transformer */
|
||||||
$resource = new Item($rate, new CurrencyExchangeRateTransformer($this->parameters), 'currency_exchange_rates');
|
$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');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
|
|||||||
191
app/Api/V1/Controllers/ImportController.php
Normal file
191
app/Api/V1/Controllers/ImportController.php
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
<?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\Manager;
|
||||||
|
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||||
|
use League\Fractal\Resource\Collection as FractalCollection;
|
||||||
|
use League\Fractal\Resource\Item;
|
||||||
|
use League\Fractal\Serializer\JsonApiSerializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ImportController
|
||||||
|
*/
|
||||||
|
class ImportController extends Controller
|
||||||
|
{
|
||||||
|
use TransactionFilter;
|
||||||
|
/** @var ImportJobRepositoryInterface Import job repository. */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function listAll(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
// create some objects:
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
|
// get list of accounts. Count it and split it.
|
||||||
|
$collection = $this->repository->get();
|
||||||
|
$count = $collection->count();
|
||||||
|
$importJobs = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
|
||||||
|
// make paginator:
|
||||||
|
$paginator = new LengthAwarePaginator($importJobs, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
$paginator->setPath(route('api.v1.import.list') . $this->buildParams());
|
||||||
|
|
||||||
|
// present to user.
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var ImportJobTransformer $transformer */
|
||||||
|
$transformer = app(ImportJobTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new FractalCollection($importJobs, $transformer, 'import_jobs');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param ImportJob $importJob
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function show(Request $request, ImportJob $importJob): JsonResponse
|
||||||
|
{
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var ImportJobTransformer $transformer */
|
||||||
|
$transformer = app(ImportJobTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($importJob, $transformer, 'import_jobs');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show all transactions
|
||||||
|
*
|
||||||
|
* @param 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 = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
$tag = $importJob->tag;
|
||||||
|
$transactions = new Collection();
|
||||||
|
$paginator = new LengthAwarePaginator($transactions, 0, $pageSize);
|
||||||
|
$paginator->setPath(route('api.v1.import.transactions', [$importJob->key]) . $this->buildParams());
|
||||||
|
|
||||||
|
if (null !== $tag) {
|
||||||
|
/** @var User $admin */
|
||||||
|
$admin = auth()->user();
|
||||||
|
|
||||||
|
// 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,10 +25,13 @@ namespace FireflyIII\Api\V1\Controllers;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Requests\LinkTypeRequest;
|
use FireflyIII\Api\V1\Requests\LinkTypeRequest;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Models\LinkType;
|
use FireflyIII\Models\LinkType;
|
||||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||||
use FireflyIII\Transformers\LinkTypeTransformer;
|
use FireflyIII\Transformers\LinkTypeTransformer;
|
||||||
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -42,10 +45,11 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
|||||||
/**
|
/**
|
||||||
* Class LinkTypeController.
|
* Class LinkTypeController.
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
*
|
||||||
*/
|
*/
|
||||||
class LinkTypeController extends Controller
|
class LinkTypeController extends Controller
|
||||||
{
|
{
|
||||||
|
use TransactionFilter;
|
||||||
/** @var LinkTypeRepositoryInterface The link type repository */
|
/** @var LinkTypeRepositoryInterface The link type repository */
|
||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
@@ -54,6 +58,8 @@ class LinkTypeController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* LinkTypeController constructor.
|
* LinkTypeController constructor.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -78,13 +84,14 @@ class LinkTypeController extends Controller
|
|||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function delete(LinkType $linkType): JsonResponse
|
public function delete(LinkType $linkType): JsonResponse
|
||||||
{
|
{
|
||||||
if (false === $linkType->editable) {
|
if (false === $linkType->editable) {
|
||||||
throw new FireflyException(sprintf('You cannot delete this link type (#%d, "%s")', $linkType->id, $linkType->name));
|
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);
|
return response()->json([], 204);
|
||||||
}
|
}
|
||||||
@@ -94,7 +101,8 @@ class LinkTypeController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse]
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -114,7 +122,12 @@ class LinkTypeController extends Controller
|
|||||||
|
|
||||||
// present to user.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
@@ -124,22 +137,22 @@ class LinkTypeController extends Controller
|
|||||||
/**
|
/**
|
||||||
* List single resource.
|
* List single resource.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param LinkType $linkType
|
* @param LinkType $linkType
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, LinkType $linkType): JsonResponse
|
public function show(Request $request, LinkType $linkType): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
|
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
$resource = new Item($linkType, new LinkTypeTransformer($this->parameters), 'link_types');
|
/** @var LinkTypeTransformer $transformer */
|
||||||
|
$transformer = app(LinkTypeTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($linkType, $transformer, 'link_types');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
@@ -168,17 +181,81 @@ class LinkTypeController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($linkType, new LinkTypeTransformer($this->parameters), 'link_types');
|
/** @var LinkTypeTransformer $transformer */
|
||||||
|
$transformer = app(LinkTypeTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
$resource = new Item($linkType, $transformer, 'link_types');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
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 = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
// whatever is returned by the query, it must be part of these journals:
|
||||||
|
$journalIds = $this->repository->getJournalIds($linkType);
|
||||||
|
|
||||||
|
/** @var User $admin */
|
||||||
|
$admin = auth()->user();
|
||||||
|
|
||||||
|
// 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.
|
* Update object.
|
||||||
*
|
*
|
||||||
* @param LinkTypeRequest $request
|
* @param LinkTypeRequest $request
|
||||||
* @param LinkType $linkType
|
* @param LinkType $linkType
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
@@ -202,7 +279,11 @@ class LinkTypeController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($linkType, new LinkTypeTransformer($this->parameters), 'link_types');
|
/** @var LinkTypeTransformer $transformer */
|
||||||
|
$transformer = app(LinkTypeTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($linkType, $transformer, 'link_types');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ use FireflyIII\Api\V1\Requests\PiggyBankRequest;
|
|||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\PiggyBank;
|
use FireflyIII\Models\PiggyBank;
|
||||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||||
|
use FireflyIII\Transformers\PiggyBankEventTransformer;
|
||||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
@@ -41,7 +42,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
|||||||
/**
|
/**
|
||||||
* Class PiggyBankController.
|
* Class PiggyBankController.
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
*
|
||||||
*/
|
*/
|
||||||
class PiggyBankController extends Controller
|
class PiggyBankController extends Controller
|
||||||
{
|
{
|
||||||
@@ -51,6 +52,8 @@ class PiggyBankController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* PiggyBankController constructor.
|
* PiggyBankController constructor.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -75,6 +78,7 @@ class PiggyBankController extends Controller
|
|||||||
* @param PiggyBank $piggyBank
|
* @param PiggyBank $piggyBank
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function delete(PiggyBank $piggyBank): JsonResponse
|
public function delete(PiggyBank $piggyBank): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -88,7 +92,8 @@ class PiggyBankController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse]
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -110,7 +115,12 @@ class PiggyBankController extends Controller
|
|||||||
|
|
||||||
// present to user.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
@@ -120,22 +130,59 @@ class PiggyBankController extends Controller
|
|||||||
/**
|
/**
|
||||||
* List single resource.
|
* List single resource.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param PiggyBank $piggyBank
|
* @param PiggyBank $piggyBank
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function piggyBankEvents(Request $request, PiggyBank $piggyBank): JsonResponse
|
||||||
|
{
|
||||||
|
// types to get, page size:
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
$manager = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
$collection = $this->repository->getEvents($piggyBank);
|
||||||
|
$count = $collection->count();
|
||||||
|
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
|
||||||
|
// make paginator:
|
||||||
|
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
$paginator->setPath(route('api.v1.piggy_banks.events', [$piggyBank->id]) . $this->buildParams());
|
||||||
|
|
||||||
|
/** @var PiggyBankEventTransformer $transformer */
|
||||||
|
$transformer = app(PiggyBankEventTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new FractalCollection($events, $transformer, 'piggy_bank_events');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List single resource.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param PiggyBank $piggyBank
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, PiggyBank $piggyBank): JsonResponse
|
public function show(Request $request, PiggyBank $piggyBank): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($piggyBank, new PiggyBankTransformer($this->parameters), 'piggy_banks');
|
/** @var PiggyBankTransformer $transformer */
|
||||||
|
$transformer = app(PiggyBankTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($piggyBank, $transformer, 'piggy_banks');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
@@ -157,7 +204,11 @@ class PiggyBankController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($piggyBank, new PiggyBankTransformer($this->parameters), 'piggy_banks');
|
/** @var PiggyBankTransformer $transformer */
|
||||||
|
$transformer = app(PiggyBankTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($piggyBank, $transformer, 'piggy_banks');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -169,7 +220,7 @@ class PiggyBankController extends Controller
|
|||||||
* Update piggy bank.
|
* Update piggy bank.
|
||||||
*
|
*
|
||||||
* @param PiggyBankRequest $request
|
* @param PiggyBankRequest $request
|
||||||
* @param PiggyBank $piggyBank
|
* @param PiggyBank $piggyBank
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
@@ -180,7 +231,11 @@ class PiggyBankController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($piggyBank, new PiggyBankTransformer($this->parameters), 'piggy_banks');
|
/** @var PiggyBankTransformer $transformer */
|
||||||
|
$transformer = app(PiggyBankTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($piggyBank, $transformer, 'piggy_banks');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Api\V1\Controllers;
|
namespace FireflyIII\Api\V1\Controllers;
|
||||||
|
|
||||||
use FireflyIII\Api\V1\Requests\PreferenceRequest;
|
use FireflyIII\Api\V1\Requests\PreferenceRequest;
|
||||||
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\Preference;
|
use FireflyIII\Models\Preference;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Transformers\PreferenceTransformer;
|
use FireflyIII\Transformers\PreferenceTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
@@ -41,22 +43,54 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
|||||||
*/
|
*/
|
||||||
class PreferenceController extends Controller
|
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.
|
* List all of them.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse]
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$available = [
|
$available = [
|
||||||
'language', 'customFiscalYear', 'fiscalYearStart', 'currencyPreference',
|
'language', 'customFiscalYear', 'fiscalYearStart', 'currencyPreference',
|
||||||
'transaction_journal_optional_fields', 'frontPageAccounts', 'viewRange',
|
'transaction_journal_optional_fields', 'frontPageAccounts', 'viewRange',
|
||||||
'listPageSize, twoFactorAuthEnabled',
|
'listPageSize',
|
||||||
];
|
];
|
||||||
|
|
||||||
$preferences = new Collection;
|
$preferences = new Collection;
|
||||||
foreach ($available as $name) {
|
foreach ($available as $name) {
|
||||||
$pref = app('preferences')->getForUser($user, $name);
|
$pref = app('preferences')->getForUser($user, $name);
|
||||||
@@ -71,20 +105,25 @@ class PreferenceController extends Controller
|
|||||||
|
|
||||||
// present to user.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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');
|
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 Request $request
|
||||||
* @param Preference $preference
|
* @param Preference $preference
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, Preference $preference): JsonResponse
|
public function show(Request $request, Preference $preference): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -94,20 +133,22 @@ class PreferenceController extends Controller
|
|||||||
|
|
||||||
// present to user.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
$resource = new Item($preference, new PreferenceTransformer($this->parameters), 'preferences');
|
/** @var PreferenceTransformer $transformer */
|
||||||
|
$transformer = app(PreferenceTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($preference, $transformer, 'preferences');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a preference.
|
* Update a preference.
|
||||||
*
|
*
|
||||||
* @param PreferenceRequest $request
|
* @param PreferenceRequest $request
|
||||||
* @param Preference $preference
|
* @param Preference $preference
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
|
||||||
*/
|
*/
|
||||||
public function update(PreferenceRequest $request, Preference $preference): JsonResponse
|
public function update(PreferenceRequest $request, Preference $preference): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -125,7 +166,6 @@ class PreferenceController extends Controller
|
|||||||
$newValue = (int)$data['data'];
|
$newValue = (int)$data['data'];
|
||||||
break;
|
break;
|
||||||
case 'customFiscalYear':
|
case 'customFiscalYear':
|
||||||
case 'twoFactorAuthEnabled':
|
|
||||||
$newValue = 1 === (int)$data['data'];
|
$newValue = 1 === (int)$data['data'];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -137,7 +177,11 @@ class PreferenceController extends Controller
|
|||||||
|
|
||||||
// present to user.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
$resource = new Item($result, new PreferenceTransformer($this->parameters), 'preferences');
|
/** @var PreferenceTransformer $transformer */
|
||||||
|
$transformer = app(PreferenceTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($result, $transformer, 'preferences');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
|||||||
@@ -23,10 +23,16 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Controllers;
|
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\Models\Recurrence;
|
||||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Cronjobs\RecurringCronjob;
|
||||||
|
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||||
use FireflyIII\Transformers\RecurrenceTransformer;
|
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||||
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -36,17 +42,21 @@ use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
|||||||
use League\Fractal\Resource\Collection as FractalCollection;
|
use League\Fractal\Resource\Collection as FractalCollection;
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
use League\Fractal\Serializer\JsonApiSerializer;
|
use League\Fractal\Serializer\JsonApiSerializer;
|
||||||
|
use Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RecurrenceController
|
* Class RecurrenceController
|
||||||
*/
|
*/
|
||||||
class RecurrenceController extends Controller
|
class RecurrenceController extends Controller
|
||||||
{
|
{
|
||||||
|
use TransactionFilter;
|
||||||
/** @var RecurringRepositoryInterface The recurring transaction repository */
|
/** @var RecurringRepositoryInterface The recurring transaction repository */
|
||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RecurrenceController constructor.
|
* RecurrenceController constructor.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -71,6 +81,7 @@ class RecurrenceController extends Controller
|
|||||||
* @param Recurrence $recurrence
|
* @param Recurrence $recurrence
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function delete(Recurrence $recurrence): JsonResponse
|
public function delete(Recurrence $recurrence): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -84,7 +95,8 @@ class RecurrenceController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse]
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -106,7 +118,12 @@ class RecurrenceController extends Controller
|
|||||||
|
|
||||||
// present to user.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
@@ -116,22 +133,23 @@ class RecurrenceController extends Controller
|
|||||||
/**
|
/**
|
||||||
* List single resource.
|
* List single resource.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Recurrence $recurrence
|
* @param Recurrence $recurrence
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, Recurrence $recurrence): JsonResponse
|
public function show(Request $request, Recurrence $recurrence): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($recurrence, new RecurrenceTransformer($this->parameters), 'recurrences');
|
/** @var RecurrenceTransformer $transformer */
|
||||||
|
$transformer = app(RecurrenceTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($recurrence, $transformer, 'recurrences');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
@@ -141,38 +159,130 @@ class RecurrenceController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Store new object.
|
* Store new object.
|
||||||
*
|
*
|
||||||
* @param RecurrenceRequest $request
|
* @param RecurrenceStoreRequest $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function store(RecurrenceRequest $request): JsonResponse
|
public function store(RecurrenceStoreRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$recurrence = $this->repository->store($request->getAll());
|
$recurrence = $this->repository->store($request->getAllRecurrenceData());
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
$resource = new Item($recurrence, new RecurrenceTransformer($this->parameters), 'recurrences');
|
|
||||||
|
/** @var RecurrenceTransformer $transformer */
|
||||||
|
$transformer = app(RecurrenceTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($recurrence, $transformer, 'recurrences');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
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 = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
// whatever is returned by the query, it must be part of these journals:
|
||||||
|
$journalIds = $this->repository->getJournalIds($recurrence);
|
||||||
|
|
||||||
|
/** @var User $admin */
|
||||||
|
$admin = auth()->user();
|
||||||
|
|
||||||
|
// 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.
|
* Update single recurrence.
|
||||||
*
|
*
|
||||||
* @param RecurrenceRequest $request
|
* @param RecurrenceUpdateRequest $request
|
||||||
* @param Recurrence $recurrence
|
* @param Recurrence $recurrence
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function update(RecurrenceRequest $request, Recurrence $recurrence): JsonResponse
|
public function update(RecurrenceUpdateRequest $request, Recurrence $recurrence): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getAll();
|
$data = $request->getAllRecurrenceData();
|
||||||
$category = $this->repository->update($recurrence, $data);
|
$category = $this->repository->update($recurrence, $data);
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
/** @var RecurrenceTransformer $transformer */
|
||||||
|
$transformer = app(RecurrenceTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
$resource = new Item($category, new RecurrenceTransformer($this->parameters), 'recurrences');
|
$resource = new Item($category, $transformer, 'recurrences');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
|||||||
@@ -24,9 +24,17 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Api\V1\Controllers;
|
namespace FireflyIII\Api\V1\Controllers;
|
||||||
|
|
||||||
use FireflyIII\Api\V1\Requests\RuleRequest;
|
use FireflyIII\Api\V1\Requests\RuleRequest;
|
||||||
|
use FireflyIII\Api\V1\Requests\RuleTestRequest;
|
||||||
|
use FireflyIII\Api\V1\Requests\RuleTriggerRequest;
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Models\Rule;
|
use FireflyIII\Models\Rule;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||||
|
use FireflyIII\TransactionRules\Engine\RuleEngine;
|
||||||
|
use FireflyIII\TransactionRules\TransactionMatcher;
|
||||||
use FireflyIII\Transformers\RuleTransformer;
|
use FireflyIII\Transformers\RuleTransformer;
|
||||||
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -36,17 +44,22 @@ use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
|||||||
use League\Fractal\Resource\Collection as FractalCollection;
|
use League\Fractal\Resource\Collection as FractalCollection;
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
use League\Fractal\Serializer\JsonApiSerializer;
|
use League\Fractal\Serializer\JsonApiSerializer;
|
||||||
|
use Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RuleController
|
* Class RuleController
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
class RuleController extends Controller
|
class RuleController extends Controller
|
||||||
{
|
{
|
||||||
|
/** @var AccountRepositoryInterface Account repository */
|
||||||
|
private $accountRepository;
|
||||||
/** @var RuleRepositoryInterface The rule repository */
|
/** @var RuleRepositoryInterface The rule repository */
|
||||||
private $ruleRepository;
|
private $ruleRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RuleController constructor.
|
* RuleController constructor.
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -59,6 +72,9 @@ class RuleController extends Controller
|
|||||||
$this->ruleRepository = app(RuleRepositoryInterface::class);
|
$this->ruleRepository = app(RuleRepositoryInterface::class);
|
||||||
$this->ruleRepository->setUser($user);
|
$this->ruleRepository->setUser($user);
|
||||||
|
|
||||||
|
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||||
|
$this->accountRepository->setUser($user);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -70,6 +86,7 @@ class RuleController extends Controller
|
|||||||
* @param Rule $rule
|
* @param Rule $rule
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function delete(Rule $rule): JsonResponse
|
public function delete(Rule $rule): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -83,7 +100,8 @@ class RuleController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse]
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -105,7 +123,12 @@ class RuleController extends Controller
|
|||||||
|
|
||||||
// present to user.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
@@ -116,21 +139,22 @@ class RuleController extends Controller
|
|||||||
* List single resource.
|
* List single resource.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Rule $rule
|
* @param Rule $rule
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, Rule $rule): JsonResponse
|
public function show(Request $request, Rule $rule): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($rule, new RuleTransformer($this->parameters), 'rules');
|
/** @var RuleTransformer $transformer */
|
||||||
|
$transformer = app(RuleTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($rule, $transformer, 'rules');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
@@ -150,27 +174,163 @@ class RuleController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($rule, new RuleTransformer($this->parameters), 'rules');
|
/** @var RuleTransformer $transformer */
|
||||||
|
$transformer = app(RuleTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($rule, $transformer, 'rules');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param RuleTestRequest $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 = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @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 triggerRule(RuleTriggerRequest $request, Rule $rule): JsonResponse
|
||||||
|
{
|
||||||
|
// Get parameters specified by the user
|
||||||
|
$parameters = $request->getTriggerParameters();
|
||||||
|
|
||||||
|
/** @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.
|
* Update a rule.
|
||||||
*
|
*
|
||||||
* @param RuleRequest $request
|
* @param RuleRequest $request
|
||||||
* @param Rule $rule
|
* @param Rule $rule
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function update(RuleRequest $request, Rule $rule): JsonResponse
|
public function update(RuleRequest $request, Rule $rule): JsonResponse
|
||||||
{
|
{
|
||||||
$rule = $this->ruleRepository->update($rule, $request->getAll());
|
$rule = $this->ruleRepository->update($rule, $request->getAll());
|
||||||
|
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($rule, new RuleTransformer($this->parameters), 'rules');
|
/** @var RuleTransformer $transformer */
|
||||||
|
$transformer = app(RuleTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($rule, $transformer, 'rules');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param Rule $rule
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function moveDown(Request $request, Rule $rule): JsonResponse
|
||||||
|
{
|
||||||
|
$this->ruleRepository->moveDown($rule);
|
||||||
|
$rule = $this->ruleRepository->find($rule->id);
|
||||||
|
$manager = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var RuleTransformer $transformer */
|
||||||
|
$transformer = app(RuleTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($rule, $transformer, 'rules');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param Rule $rule
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function moveUp(Request $request, Rule $rule): JsonResponse
|
||||||
|
{
|
||||||
|
$this->ruleRepository->moveUp($rule);
|
||||||
|
$rule = $this->ruleRepository->find($rule->id);
|
||||||
|
$manager = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @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');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
|||||||
@@ -23,31 +23,46 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Controllers;
|
namespace FireflyIII\Api\V1\Controllers;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use FireflyIII\Api\V1\Requests\RuleGroupRequest;
|
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\Models\RuleGroup;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||||
|
use FireflyIII\TransactionRules\Engine\RuleEngine;
|
||||||
|
use FireflyIII\TransactionRules\TransactionMatcher;
|
||||||
use FireflyIII\Transformers\RuleGroupTransformer;
|
use FireflyIII\Transformers\RuleGroupTransformer;
|
||||||
|
use FireflyIII\Transformers\RuleTransformer;
|
||||||
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
use League\Fractal\Manager;
|
use League\Fractal\Manager;
|
||||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||||
use League\Fractal\Resource\Collection as FractalCollection;
|
use League\Fractal\Resource\Collection as FractalCollection;
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
use League\Fractal\Serializer\JsonApiSerializer;
|
use League\Fractal\Serializer\JsonApiSerializer;
|
||||||
|
use Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RuleGroupController
|
* Class RuleGroupController
|
||||||
*/
|
*/
|
||||||
class RuleGroupController extends Controller
|
class RuleGroupController extends Controller
|
||||||
{
|
{
|
||||||
|
/** @var AccountRepositoryInterface Account repository */
|
||||||
|
private $accountRepository;
|
||||||
/** @var RuleGroupRepositoryInterface The rule group repository */
|
/** @var RuleGroupRepositoryInterface The rule group repository */
|
||||||
private $ruleGroupRepository;
|
private $ruleGroupRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RuleGroupController constructor.
|
* RuleGroupController constructor.
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -60,6 +75,9 @@ class RuleGroupController extends Controller
|
|||||||
$this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
|
$this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
|
||||||
$this->ruleGroupRepository->setUser($user);
|
$this->ruleGroupRepository->setUser($user);
|
||||||
|
|
||||||
|
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||||
|
$this->accountRepository->setUser($user);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -71,6 +89,7 @@ class RuleGroupController extends Controller
|
|||||||
* @param RuleGroup $ruleGroup
|
* @param RuleGroup $ruleGroup
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function delete(RuleGroup $ruleGroup): JsonResponse
|
public function delete(RuleGroup $ruleGroup): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -84,7 +103,8 @@ class RuleGroupController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse]
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -106,31 +126,76 @@ class RuleGroupController extends Controller
|
|||||||
|
|
||||||
// present to user.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param RuleGroup $group
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function rules(Request $request, RuleGroup $group): JsonResponse
|
||||||
|
{
|
||||||
|
// create some objects:
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
|
||||||
|
// types to get, page size:
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
|
// get list of budgets. Count it and split it.
|
||||||
|
$collection = $this->ruleGroupRepository->getRules($group);
|
||||||
|
$count = $collection->count();
|
||||||
|
$rules = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
|
||||||
|
// make paginator:
|
||||||
|
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
$paginator->setPath(route('api.v1.rule_groups.rules', [$group->id]) . $this->buildParams());
|
||||||
|
|
||||||
|
// present to user.
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var RuleTransformer $transformer */
|
||||||
|
$transformer = app(RuleTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new FractalCollection($rules, $transformer, 'rules');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List single resource.
|
* List single resource.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param RuleGroup $ruleGroup
|
* @param RuleGroup $ruleGroup
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, RuleGroup $ruleGroup): JsonResponse
|
public function show(Request $request, RuleGroup $ruleGroup): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($ruleGroup, new RuleGroupTransformer($this->parameters), 'rule_groups');
|
/** @var RuleGroupTransformer $transformer */
|
||||||
|
$transformer = app(RuleGroupTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($ruleGroup, $transformer, 'rule_groups');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
@@ -150,17 +215,126 @@ class RuleGroupController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($ruleGroup, new RuleGroupTransformer($this->parameters), 'rule_groups');
|
/** @var RuleGroupTransformer $transformer */
|
||||||
|
$transformer = app(RuleGroupTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($ruleGroup, $transformer, 'rule_groups');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
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());
|
||||||
|
|
||||||
|
// resulting list is presented as JSON thing.
|
||||||
|
$manager = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
$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.
|
* Update a rule group.
|
||||||
*
|
*
|
||||||
* @param RuleGroupRequest $request
|
* @param RuleGroupRequest $request
|
||||||
* @param RuleGroup $ruleGroup
|
* @param RuleGroup $ruleGroup
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
@@ -171,9 +345,56 @@ class RuleGroupController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
$resource = new Item($ruleGroup, new RuleGroupTransformer($this->parameters), 'rule_groups');
|
/** @var RuleGroupTransformer $transformer */
|
||||||
|
$transformer = app(RuleGroupTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($ruleGroup, $transformer, 'rule_groups');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param RuleGroup $ruleGroup
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function moveDown(Request $request, RuleGroup $ruleGroup): JsonResponse
|
||||||
|
{
|
||||||
|
$this->ruleGroupRepository->moveDown($ruleGroup);
|
||||||
|
$ruleGroup = $this->ruleGroupRepository->find($ruleGroup->id);
|
||||||
|
$manager = new Manager();
|
||||||
|
$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, $transformer, 'rule_groups');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param RuleGroup $ruleGroup
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function moveUp(Request $request, RuleGroup $ruleGroup): JsonResponse
|
||||||
|
{
|
||||||
|
$this->ruleGroupRepository->moveUp($ruleGroup);
|
||||||
|
$ruleGroup = $this->ruleGroupRepository->find($ruleGroup->id);
|
||||||
|
$manager = new Manager();
|
||||||
|
$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, $transformer, 'rule_groups');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
432
app/Api/V1/Controllers/SummaryController.php
Normal file
432
app/Api/V1/Controllers/SummaryController.php
Normal file
@@ -0,0 +1,432 @@
|
|||||||
|
<?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\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||||
|
use FireflyIII\User;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class SummaryController
|
||||||
|
*/
|
||||||
|
class SummaryController extends Controller
|
||||||
|
{
|
||||||
|
/** @var AccountRepositoryInterface */
|
||||||
|
private $accountRepository;
|
||||||
|
/** @var BillRepositoryInterface */
|
||||||
|
private $billRepository;
|
||||||
|
/** @var BudgetRepositoryInterface */
|
||||||
|
private $budgetRepository;
|
||||||
|
/** @var CurrencyRepositoryInterface */
|
||||||
|
private $currencyRepos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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->billRepository->setUser($user);
|
||||||
|
$this->currencyRepos->setUser($user);
|
||||||
|
$this->budgetRepository->setUser($user);
|
||||||
|
$this->accountRepository->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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->budgetRepository->getAvailableBudgetWithCurrency($start, $end);
|
||||||
|
$budgets = $this->budgetRepository->getActiveBudgets();
|
||||||
|
$spentInfo = $this->budgetRepository->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will scroll through the results of the spentInPeriodMc() array and return the correct info.
|
||||||
|
*
|
||||||
|
* @param array $spentInfo
|
||||||
|
* @param TransactionCurrency $currency
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
private function findInSpentArray(array $spentInfo, TransactionCurrency $currency): float
|
||||||
|
{
|
||||||
|
foreach ($spentInfo as $array) {
|
||||||
|
if ($array['currency_id'] === $currency->id) {
|
||||||
|
return $array['amount'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0; // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
327
app/Api/V1/Controllers/TagController.php
Normal file
327
app/Api/V1/Controllers/TagController.php
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
<?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\Manager;
|
||||||
|
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||||
|
use League\Fractal\Resource\Collection as FractalCollection;
|
||||||
|
use League\Fractal\Resource\Item;
|
||||||
|
use League\Fractal\Serializer\JsonApiSerializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TagController
|
||||||
|
*/
|
||||||
|
class TagController extends Controller
|
||||||
|
{
|
||||||
|
use TransactionFilter;
|
||||||
|
|
||||||
|
/** @var TagRepositoryInterface The tag repository */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function index(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
// create some objects:
|
||||||
|
$manager = new Manager;
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
|
||||||
|
// types to get, page size:
|
||||||
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
|
// get list of budgets. Count it and split it.
|
||||||
|
$collection = $this->repository->get();
|
||||||
|
$count = $collection->count();
|
||||||
|
$rules = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
|
||||||
|
// make paginator:
|
||||||
|
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
|
||||||
|
$paginator->setPath(route('api.v1.tags.index') . $this->buildParams());
|
||||||
|
|
||||||
|
// present to user.
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var TagTransformer $transformer */
|
||||||
|
$transformer = app(TagTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new FractalCollection($rules, $transformer, 'tags');
|
||||||
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List single resource.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param Tag $tag
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function show(Request $request, Tag $tag): JsonResponse
|
||||||
|
{
|
||||||
|
$manager = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var TagTransformer $transformer */
|
||||||
|
$transformer = app(TagTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($tag, $transformer, 'tags');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store new object.
|
||||||
|
*
|
||||||
|
* @param TagRequest $request
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function store(TagRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$rule = $this->repository->store($request->getAll());
|
||||||
|
$manager = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @var TagTransformer $transformer */
|
||||||
|
$transformer = app(TagTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($rule, $transformer, 'tags');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show all transactions.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param Tag $tag
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @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 = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @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 = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
/** @var TagTransformer $transformer */
|
||||||
|
$transformer = app(TagTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($rule, $transformer, 'tags');
|
||||||
|
|
||||||
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,37 +24,51 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Controllers;
|
namespace FireflyIII\Api\V1\Controllers;
|
||||||
|
|
||||||
use FireflyIII\Api\V1\Requests\TransactionRequest;
|
use FireflyIII\Api\V1\Requests\TransactionStoreRequest;
|
||||||
|
use FireflyIII\Api\V1\Requests\TransactionUpdateRequest;
|
||||||
|
use FireflyIII\Events\StoredTransactionGroup;
|
||||||
|
use FireflyIII\Events\UpdatedTransactionGroup;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
use FireflyIII\Models\TransactionGroup;
|
||||||
use FireflyIII\Helpers\Filter\NegativeAmountFilter;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Helpers\Filter\PositiveAmountFilter;
|
use FireflyIII\Repositories\Journal\JournalAPIRepositoryInterface;
|
||||||
use FireflyIII\Models\Transaction;
|
|
||||||
use FireflyIII\Models\TransactionType;
|
|
||||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
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 FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use League\Fractal\Manager;
|
use League\Fractal\Manager;
|
||||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||||
use League\Fractal\Resource\Collection as FractalCollection;
|
use League\Fractal\Resource\Collection as FractalCollection;
|
||||||
|
use League\Fractal\Resource\Item;
|
||||||
use League\Fractal\Serializer\JsonApiSerializer;
|
use League\Fractal\Serializer\JsonApiSerializer;
|
||||||
|
use Log;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class TransactionController
|
* Class TransactionController
|
||||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
|
||||||
*/
|
*/
|
||||||
class TransactionController extends Controller
|
class TransactionController extends Controller
|
||||||
{
|
{
|
||||||
|
use TransactionFilter;
|
||||||
|
|
||||||
|
/** @var TransactionGroupRepositoryInterface Group repository. */
|
||||||
|
private $groupRepository;
|
||||||
/** @var JournalRepositoryInterface The journal repository */
|
/** @var JournalRepositoryInterface The journal repository */
|
||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
|
/** @var JournalAPIRepositoryInterface Journal API repos */
|
||||||
|
private $journalAPIRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TransactionController constructor.
|
* TransactionController constructor.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -64,9 +78,12 @@ class TransactionController extends Controller
|
|||||||
/** @var User $admin */
|
/** @var User $admin */
|
||||||
$admin = auth()->user();
|
$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->repository->setUser($admin);
|
||||||
|
$this->groupRepository->setUser($admin);
|
||||||
|
$this->journalAPIRepository->setUser($admin);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
@@ -74,16 +91,56 @@ class TransactionController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the specified resource from storage.
|
* @param Request $request
|
||||||
*
|
* @param TransactionJournal $transactionJournal
|
||||||
* @param \FireflyIII\Models\Transaction $transaction
|
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function delete(Transaction $transaction): JsonResponse
|
public function attachments(Request $request, TransactionJournal $transactionJournal): JsonResponse
|
||||||
{
|
{
|
||||||
$journal = $transaction->transactionJournal;
|
$manager = new Manager();
|
||||||
$this->repository->destroy($journal);
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
$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);
|
return response()->json([], 204);
|
||||||
}
|
}
|
||||||
@@ -94,6 +151,7 @@ class TransactionController extends Controller
|
|||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -101,77 +159,106 @@ class TransactionController extends Controller
|
|||||||
$type = $request->get('type') ?? 'default';
|
$type = $request->get('type') ?? 'default';
|
||||||
$this->parameters->set('type', $type);
|
$this->parameters->set('type', $type);
|
||||||
|
|
||||||
$types = $this->mapTypes($this->parameters->get('type'));
|
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
/** @var User $admin */
|
/** @var User $admin */
|
||||||
$admin = auth()->user();
|
$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)) {
|
// use new group collector:
|
||||||
$collector->removeFilter(InternalTransferFilter::class);
|
/** @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')) {
|
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||||
}
|
}
|
||||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
$paginator = $collector->getPaginatedGroups();
|
||||||
$collector->setTypes($types);
|
|
||||||
$paginator = $collector->getPaginatedTransactions();
|
|
||||||
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
|
$paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
|
||||||
$transactions = $paginator->getCollection();
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a single transaction.
|
* @param Request $request
|
||||||
*
|
* @param TransactionJournal $transactionJournal
|
||||||
* @param Request $request
|
|
||||||
* @param Transaction $transaction
|
|
||||||
* @param string $include
|
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, Transaction $transaction, string $include = null): JsonResponse
|
public function piggyBankEvents(Request $request, TransactionJournal $transactionJournal): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
// add include parameter:
|
$events = $this->journalAPIRepository->getPiggyBankEvents($transactionJournal);
|
||||||
$include = $include ?? '';
|
|
||||||
$include = $request->get('include') ?? $include;
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
// collect transactions using the journal collector
|
/** @var PiggyBankEventTransformer $transformer */
|
||||||
$collector = app(TransactionCollectorInterface::class);
|
$transformer = app(PiggyBankEventTransformer::class);
|
||||||
$collector->setUser(auth()->user());
|
$transformer->setParameters($this->parameters);
|
||||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
|
||||||
// filter on specific journals.
|
|
||||||
$collector->setJournals(new Collection([$transaction->transactionJournal]));
|
|
||||||
|
|
||||||
// add filter to remove transactions:
|
$resource = new FractalCollection($events, $transformer, 'piggy_bank_events');
|
||||||
$transactionType = $transaction->transactionJournal->transactionType->type;
|
|
||||||
if ($transactionType === TransactionType::WITHDRAWAL) {
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
$collector->addFilter(PositiveAmountFilter::class);
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a single transaction.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param TransactionGroup $transactionGroup
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function show(Request $request, TransactionGroup $transactionGroup): JsonResponse
|
||||||
|
{
|
||||||
|
$manager = new Manager();
|
||||||
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
|
/** @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();
|
||||||
}
|
}
|
||||||
if (!($transactionType === TransactionType::WITHDRAWAL)) {
|
/** @var TransactionGroupTransformer $transformer */
|
||||||
$collector->addFilter(NegativeAmountFilter::class);
|
$transformer = app(TransactionGroupTransformer::class);
|
||||||
}
|
$transformer->setParameters($this->parameters);
|
||||||
|
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||||
$transactions = $collector->getTransactions();
|
|
||||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -179,45 +266,47 @@ class TransactionController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Store a new transaction.
|
* Store a new transaction.
|
||||||
*
|
*
|
||||||
* @param TransactionRequest $request
|
* @param TransactionStoreRequest $request
|
||||||
*
|
*
|
||||||
* @param JournalRepositoryInterface $repository
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function store(TransactionRequest $request, JournalRepositoryInterface $repository): JsonResponse
|
public function store(TransactionStoreRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$data['user'] = auth()->user()->id;
|
$data['user'] = auth()->user()->id;
|
||||||
$journal = $repository->store($data);
|
|
||||||
|
Log::channel('audit')
|
||||||
|
->info('Store new transaction over API.', $data);
|
||||||
|
|
||||||
|
$transactionGroup = $this->groupRepository->store($data);
|
||||||
|
|
||||||
|
event(new StoredTransactionGroup($transactionGroup));
|
||||||
|
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
// add include parameter:
|
/** @var User $admin */
|
||||||
$include = $request->get('include') ?? '';
|
$admin = auth()->user();
|
||||||
$manager->parseIncludes($include);
|
// 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();
|
||||||
|
|
||||||
// collect transactions using the journal collector
|
$selectedGroup = $collector->getGroups()->first();
|
||||||
$collector = app(TransactionCollectorInterface::class);
|
if (null === $selectedGroup) {
|
||||||
$collector->setUser(auth()->user());
|
throw new NotFoundHttpException(); // @codeCoverageIgnore
|
||||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
|
||||||
// filter on specific journals.
|
|
||||||
$collector->setJournals(new Collection([$journal]));
|
|
||||||
|
|
||||||
// add filter to remove transactions:
|
|
||||||
$transactionType = $journal->transactionType->type;
|
|
||||||
if ($transactionType === TransactionType::WITHDRAWAL) {
|
|
||||||
$collector->addFilter(PositiveAmountFilter::class);
|
|
||||||
}
|
}
|
||||||
if (!($transactionType === TransactionType::WITHDRAWAL)) {
|
/** @var TransactionGroupTransformer $transformer */
|
||||||
$collector->addFilter(NegativeAmountFilter::class);
|
$transformer = app(TransactionGroupTransformer::class);
|
||||||
}
|
$transformer->setParameters($this->parameters);
|
||||||
|
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||||
$transactions = $collector->getTransactions();
|
|
||||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -226,82 +315,44 @@ class TransactionController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Update a transaction.
|
* Update a transaction.
|
||||||
*
|
*
|
||||||
* @param TransactionRequest $request
|
* @param TransactionUpdateRequest $request
|
||||||
* @param JournalRepositoryInterface $repository
|
* @param TransactionGroup $transactionGroup
|
||||||
* @param Transaction $transaction
|
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
public function update(TransactionRequest $request, JournalRepositoryInterface $repository, Transaction $transaction): JsonResponse
|
public function update(TransactionUpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getAll();
|
Log::debug('Now in update routine.');
|
||||||
$data['user'] = auth()->user()->id;
|
$data = $request->getAll();
|
||||||
$journal = $repository->update($transaction->transactionJournal, $data);
|
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
// add include parameter:
|
event(new UpdatedTransactionGroup($transactionGroup));
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
// needs a lot of extra data to match the journal collector. Or just expand that one.
|
/** @var User $admin */
|
||||||
// collect transactions using the journal collector
|
$admin = auth()->user();
|
||||||
$collector = app(TransactionCollectorInterface::class);
|
// use new group collector:
|
||||||
$collector->setUser(auth()->user());
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
$collector = app(GroupCollectorInterface::class);
|
||||||
// filter on specific journals.
|
$collector
|
||||||
$collector->setJournals(new Collection([$journal]));
|
->setUser($admin)
|
||||||
|
// filter on transaction group.
|
||||||
|
->setTransactionGroup($transactionGroup)
|
||||||
|
// all info needed for the API:
|
||||||
|
->withAPIInformation();
|
||||||
|
|
||||||
// add filter to remove transactions:
|
$selectedGroup = $collector->getGroups()->first();
|
||||||
$transactionType = $journal->transactionType->type;
|
if (null === $selectedGroup) {
|
||||||
if ($transactionType === TransactionType::WITHDRAWAL) {
|
throw new NotFoundHttpException(); // @codeCoverageIgnore
|
||||||
$collector->addFilter(PositiveAmountFilter::class);
|
|
||||||
}
|
}
|
||||||
if (!($transactionType === TransactionType::WITHDRAWAL)) {
|
/** @var TransactionGroupTransformer $transformer */
|
||||||
$collector->addFilter(NegativeAmountFilter::class);
|
$transformer = app(TransactionGroupTransformer::class);
|
||||||
}
|
$transformer->setParameters($this->parameters);
|
||||||
|
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||||
$transactions = $collector->getTransactions();
|
|
||||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
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
|
<?php
|
||||||
/**
|
/**
|
||||||
* JournalLinkController.php
|
* TransactionLinkController.php
|
||||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This file is part of Firefly III.
|
* This file is part of Firefly III.
|
||||||
@@ -23,12 +23,13 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Controllers;
|
namespace FireflyIII\Api\V1\Controllers;
|
||||||
|
|
||||||
use FireflyIII\Api\V1\Requests\JournalLinkRequest;
|
use FireflyIII\Api\V1\Requests\TransactionLinkRequest;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\TransactionJournalLink;
|
use FireflyIII\Models\TransactionJournalLink;
|
||||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||||
use FireflyIII\Transformers\JournalLinkTransformer;
|
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||||
|
use FireflyIII\Transformers\TransactionLinkTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -40,19 +41,20 @@ use League\Fractal\Resource\Item;
|
|||||||
use League\Fractal\Serializer\JsonApiSerializer;
|
use League\Fractal\Serializer\JsonApiSerializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class JournalLinkController.
|
* Class TransactionLinkController
|
||||||
*
|
|
||||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
|
||||||
*/
|
*/
|
||||||
class JournalLinkController extends Controller
|
class TransactionLinkController extends Controller
|
||||||
{
|
{
|
||||||
|
use TransactionFilter;
|
||||||
|
|
||||||
/** @var JournalRepositoryInterface The journal repository */
|
/** @var JournalRepositoryInterface The journal repository */
|
||||||
private $journalRepository;
|
private $journalRepository;
|
||||||
/** @var LinkTypeRepositoryInterface The link type repository */
|
/** @var LinkTypeRepositoryInterface The link type repository */
|
||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JournalLinkController constructor.
|
* TransactionLinkController constructor.
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -79,6 +81,7 @@ class JournalLinkController extends Controller
|
|||||||
* @param TransactionJournalLink $link
|
* @param TransactionJournalLink $link
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function delete(TransactionJournalLink $link): JsonResponse
|
public function delete(TransactionJournalLink $link): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -92,7 +95,8 @@ class JournalLinkController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse]
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -101,25 +105,29 @@ class JournalLinkController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
|
|
||||||
// read type from URI
|
// read type from URI
|
||||||
$name = $request->get('name') ?? null;
|
$name = $request->get('name');
|
||||||
|
|
||||||
// types to get, page size:
|
// types to get, page size:
|
||||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||||
|
|
||||||
$linkType = $this->repository->findByName($name);
|
$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);
|
$collection = $this->repository->getJournalLinks($linkType);
|
||||||
$count = $collection->count();
|
$count = $collection->count();
|
||||||
$journalLinks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
$journalLinks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||||
|
|
||||||
// make paginator:
|
// make paginator:
|
||||||
$paginator = new LengthAwarePaginator($journalLinks, $count, $pageSize, $this->parameters->get('page'));
|
$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.
|
// present to user.
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
@@ -129,22 +137,23 @@ class JournalLinkController extends Controller
|
|||||||
/**
|
/**
|
||||||
* List single resource.
|
* List single resource.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param TransactionJournalLink $journalLink
|
* @param TransactionJournalLink $journalLink
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, TransactionJournalLink $journalLink): JsonResponse
|
public function show(Request $request, TransactionJournalLink $journalLink): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
|
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
$resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'journal_links');
|
|
||||||
|
/** @var TransactionLinkTransformer $transformer */
|
||||||
|
$transformer = app(TransactionLinkTransformer::class);
|
||||||
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
|
$resource = new Item($journalLink, $transformer, 'transaction_links');
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
@@ -153,19 +162,14 @@ class JournalLinkController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Store new object.
|
* Store new object.
|
||||||
*
|
*
|
||||||
* @param JournalLinkRequest $request
|
* @param TransactionLinkRequest $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function store(JournalLinkRequest $request): JsonResponse
|
public function store(TransactionLinkRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
|
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$inward = $this->journalRepository->findNull($data['inward_id'] ?? 0);
|
$inward = $this->journalRepository->findNull($data['inward_id'] ?? 0);
|
||||||
$outward = $this->journalRepository->findNull($data['outward_id'] ?? 0);
|
$outward = $this->journalRepository->findNull($data['outward_id'] ?? 0);
|
||||||
@@ -175,7 +179,12 @@ class JournalLinkController extends Controller
|
|||||||
$data['direction'] = 'inward';
|
$data['direction'] = 'inward';
|
||||||
|
|
||||||
$journalLink = $this->repository->storeLink($data, $inward, $outward);
|
$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');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
@@ -184,21 +193,15 @@ class JournalLinkController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Update object.
|
* Update object.
|
||||||
*
|
*
|
||||||
* @param JournalLinkRequest $request
|
* @param TransactionLinkRequest $request
|
||||||
* @param TransactionJournalLink $journalLink
|
* @param TransactionJournalLink $journalLink
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function update(JournalLinkRequest $request, TransactionJournalLink $journalLink): JsonResponse
|
public function update(TransactionLinkRequest $request, TransactionJournalLink $journalLink): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
|
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
|
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$data['inward'] = $this->journalRepository->findNull($data['inward_id'] ?? 0);
|
$data['inward'] = $this->journalRepository->findNull($data['inward_id'] ?? 0);
|
||||||
$data['outward'] = $this->journalRepository->findNull($data['outward_id'] ?? 0);
|
$data['outward'] = $this->journalRepository->findNull($data['outward_id'] ?? 0);
|
||||||
@@ -208,7 +211,11 @@ class JournalLinkController extends Controller
|
|||||||
$data['direction'] = 'inward';
|
$data['direction'] = 'inward';
|
||||||
$journalLink = $this->repository->updateLink($journalLink, $data);
|
$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');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ use League\Fractal\Serializer\JsonApiSerializer;
|
|||||||
/**
|
/**
|
||||||
* Class UserController.
|
* Class UserController.
|
||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
*
|
||||||
*/
|
*/
|
||||||
class UserController extends Controller
|
class UserController extends Controller
|
||||||
{
|
{
|
||||||
@@ -52,6 +52,7 @@ class UserController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* UserController constructor.
|
* UserController constructor.
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -69,16 +70,17 @@ class UserController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Remove the specified resource from storage.
|
* Remove the specified resource from storage.
|
||||||
*
|
*
|
||||||
* @param \FireflyIII\User $user
|
* @param User $user
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function delete(User $user): JsonResponse
|
public function delete(User $user): JsonResponse
|
||||||
{
|
{
|
||||||
/** @var User $admin */
|
/** @var User $admin */
|
||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
if ($this->repository->hasRole($admin, 'owner')) {
|
if ($admin->id !== $user->id && $this->repository->hasRole($admin, 'owner')) {
|
||||||
$this->repository->destroy($user);
|
$this->repository->destroy($user);
|
||||||
|
|
||||||
return response()->json([], 204);
|
return response()->json([], 204);
|
||||||
@@ -92,6 +94,7 @@ class UserController extends Controller
|
|||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function index(Request $request): JsonResponse
|
public function index(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -113,7 +116,11 @@ class UserController extends Controller
|
|||||||
$paginator->setPath(route('api.v1.users.index') . $this->buildParams());
|
$paginator->setPath(route('api.v1.users.index') . $this->buildParams());
|
||||||
|
|
||||||
// make resource
|
// 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));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
@@ -123,9 +130,10 @@ class UserController extends Controller
|
|||||||
* Show a single user.
|
* Show a single user.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param User $user
|
* @param User $user
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, User $user): JsonResponse
|
public function show(Request $request, User $user): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -134,12 +142,12 @@ class UserController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
// make resource
|
// 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');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -161,12 +169,13 @@ class UserController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
// make resource
|
// 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');
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||||
}
|
}
|
||||||
@@ -175,7 +184,7 @@ class UserController extends Controller
|
|||||||
* Update a user.
|
* Update a user.
|
||||||
*
|
*
|
||||||
* @param UserRequest $request
|
* @param UserRequest $request
|
||||||
* @param User $user
|
* @param User $user
|
||||||
*
|
*
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
@@ -189,12 +198,12 @@ class UserController extends Controller
|
|||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||||
|
|
||||||
// add include parameter:
|
|
||||||
$include = $request->get('include') ?? '';
|
|
||||||
$manager->parseIncludes($include);
|
|
||||||
|
|
||||||
// make resource
|
// 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');
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
83
app/Api/V1/Requests/AccountStoreRequest.php
Normal file
83
app/Api/V1/Requests/AccountStoreRequest.php
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<?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;
|
||||||
|
}
|
||||||
|
}
|
||||||
84
app/Api/V1/Requests/AccountUpdateRequest.php
Normal file
84
app/Api/V1/Requests/AccountUpdateRequest.php
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<?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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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('required|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
|
<?php
|
||||||
/**
|
/**
|
||||||
* AttachmentRequest.php
|
* AttachmentStoreRequest.php
|
||||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This file is part of Firefly III.
|
* This file is part of Firefly III.
|
||||||
*
|
*
|
||||||
@@ -29,9 +29,10 @@ use FireflyIII\Models\TransactionJournal;
|
|||||||
use FireflyIII\Rules\IsValidAttachmentModel;
|
use FireflyIII\Rules\IsValidAttachmentModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class AttachmentRequest
|
* Class AttachmentStoreRequest
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
class AttachmentRequest extends Request
|
class AttachmentStoreRequest extends Request
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Authorize logged in users.
|
* Authorize logged in users.
|
||||||
@@ -68,30 +69,20 @@ class AttachmentRequest extends Request
|
|||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
$models = implode(
|
$models = implode(
|
||||||
',', [
|
',',
|
||||||
Bill::class,
|
[
|
||||||
ImportJob::class,
|
str_replace('FireflyIII\\Models\\', '', Bill::class),
|
||||||
TransactionJournal::class,
|
str_replace('FireflyIII\\Models\\', '', ImportJob::class),
|
||||||
]
|
str_replace('FireflyIII\\Models\\', '', TransactionJournal::class),
|
||||||
|
]
|
||||||
);
|
);
|
||||||
$model = $this->string('model');
|
$model = $this->string('model');
|
||||||
$rules = [
|
return [
|
||||||
'filename' => 'required|between:1,255',
|
'filename' => 'required|between:1,255',
|
||||||
'title' => 'between:1,255',
|
'title' => 'between:1,255',
|
||||||
'notes' => 'between:1,65000',
|
'notes' => 'between:1,65000',
|
||||||
'model' => sprintf('required|in:%s', $models),
|
'model' => sprintf('required|in:%s', $models),
|
||||||
'model_id' => ['required', 'numeric', new IsValidAttachmentModel($model)],
|
'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
|
* Class AvailableBudgetRequest
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
class AvailableBudgetRequest extends Request
|
class AvailableBudgetRequest extends Request
|
||||||
{
|
{
|
||||||
@@ -50,8 +52,8 @@ class AvailableBudgetRequest extends Request
|
|||||||
'currency_id' => $this->integer('currency_id'),
|
'currency_id' => $this->integer('currency_id'),
|
||||||
'currency_code' => $this->string('currency_code'),
|
'currency_code' => $this->string('currency_code'),
|
||||||
'amount' => $this->string('amount'),
|
'amount' => $this->string('amount'),
|
||||||
'start_date' => $this->date('start_date'),
|
'start' => $this->date('start'),
|
||||||
'end_date' => $this->date('end_date'),
|
'end' => $this->date('end'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,11 +65,11 @@ class AvailableBudgetRequest extends Request
|
|||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
$rules = [
|
$rules = [
|
||||||
'currency_id' => 'numeric|exists:transaction_currencies,id|required_without:currency_code',
|
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||||
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:currency_id',
|
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||||
'amount' => 'required|numeric|more:0',
|
'amount' => 'required|numeric|more:0',
|
||||||
'start_date' => 'required|date|before:end_date',
|
'start' => 'required|date|before:end',
|
||||||
'end_date' => 'required|date|after:start_date',
|
'end' => 'required|date|after:start',
|
||||||
];
|
];
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
|
|||||||
@@ -24,10 +24,15 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Requests;
|
namespace FireflyIII\Api\V1\Requests;
|
||||||
|
|
||||||
|
use FireflyIII\Rules\IsBoolean;
|
||||||
use Illuminate\Validation\Validator;
|
use Illuminate\Validation\Validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BillRequest
|
* Class BillRequest
|
||||||
|
*
|
||||||
|
* TODO AFTER 4.8,0: split this into two request classes.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
class BillRequest extends Request
|
class BillRequest extends Request
|
||||||
{
|
{
|
||||||
@@ -50,6 +55,11 @@ class BillRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function getAll(): array
|
public function getAll(): array
|
||||||
{
|
{
|
||||||
|
$active = true;
|
||||||
|
if (null !== $this->get('active')) {
|
||||||
|
$active = $this->boolean('active');
|
||||||
|
}
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'name' => $this->string('name'),
|
'name' => $this->string('name'),
|
||||||
'amount_min' => $this->string('amount_min'),
|
'amount_min' => $this->string('amount_min'),
|
||||||
@@ -59,8 +69,7 @@ class BillRequest extends Request
|
|||||||
'date' => $this->date('date'),
|
'date' => $this->date('date'),
|
||||||
'repeat_freq' => $this->string('repeat_freq'),
|
'repeat_freq' => $this->string('repeat_freq'),
|
||||||
'skip' => $this->integer('skip'),
|
'skip' => $this->integer('skip'),
|
||||||
'automatch' => $this->boolean('automatch'),
|
'active' => $active,
|
||||||
'active' => $this->boolean('active'),
|
|
||||||
'notes' => $this->string('notes'),
|
'notes' => $this->string('notes'),
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -71,6 +80,7 @@ class BillRequest extends Request
|
|||||||
* The rules that the incoming request must be matched against.
|
* The rules that the incoming request must be matched against.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
@@ -78,13 +88,12 @@ class BillRequest extends Request
|
|||||||
'name' => 'required|between:1,255|uniqueObjectForUser:bills,name',
|
'name' => 'required|between:1,255|uniqueObjectForUser:bills,name',
|
||||||
'amount_min' => 'required|numeric|more:0',
|
'amount_min' => 'required|numeric|more:0',
|
||||||
'amount_max' => 'required|numeric|more:0',
|
'amount_max' => 'required|numeric|more:0',
|
||||||
'currency_id' => 'numeric|exists:transaction_currencies,id|required_without:currency_code',
|
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||||
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:currency_id',
|
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||||
'date' => 'required|date',
|
'date' => 'required|date',
|
||||||
'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly',
|
'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly',
|
||||||
'skip' => 'required|between:0,31',
|
'skip' => 'between:0,31',
|
||||||
'automatch' => 'required|boolean',
|
'active' => [new IsBoolean],
|
||||||
'active' => 'required|boolean',
|
|
||||||
'notes' => 'between:1,65536',
|
'notes' => 'between:1,65536',
|
||||||
];
|
];
|
||||||
switch ($this->method()) {
|
switch ($this->method()) {
|
||||||
@@ -103,14 +112,14 @@ class BillRequest extends Request
|
|||||||
/**
|
/**
|
||||||
* Configure the validator instance.
|
* Configure the validator instance.
|
||||||
*
|
*
|
||||||
* @param Validator $validator
|
* @param Validator $validator
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function withValidator(Validator $validator): void
|
public function withValidator(Validator $validator): void
|
||||||
{
|
{
|
||||||
$validator->after(
|
$validator->after(
|
||||||
function (Validator $validator) {
|
static function (Validator $validator) {
|
||||||
$data = $validator->getData();
|
$data = $validator->getData();
|
||||||
$min = (float)($data['amount_min'] ?? 0);
|
$min = (float)($data['amount_min'] ?? 0);
|
||||||
$max = (float)($data['amount_max'] ?? 0);
|
$max = (float)($data['amount_max'] ?? 0);
|
||||||
|
|||||||
@@ -23,9 +23,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Requests;
|
namespace FireflyIII\Api\V1\Requests;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BudgetLimitRequest
|
* Class BudgetLimitRequest
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* TODO AFTER 4.8,0: split this into two request classes.
|
||||||
*/
|
*/
|
||||||
class BudgetLimitRequest extends Request
|
class BudgetLimitRequest extends Request
|
||||||
{
|
{
|
||||||
@@ -48,10 +50,12 @@ class BudgetLimitRequest extends Request
|
|||||||
public function getAll(): array
|
public function getAll(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'budget_id' => $this->integer('budget_id'),
|
'budget_id' => $this->integer('budget_id'),
|
||||||
'start_date' => $this->date('start_date'),
|
'start' => $this->date('start'),
|
||||||
'end_date' => $this->date('end_date'),
|
'end' => $this->date('end'),
|
||||||
'amount' => $this->string('amount'),
|
'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
|
public function rules(): array
|
||||||
{
|
{
|
||||||
$rules = [
|
$rules = [
|
||||||
'budget_id' => 'required|exists:budgets,id|belongsToUser:budgets,id',
|
'budget_id' => 'required|exists:budgets,id|belongsToUser:budgets,id',
|
||||||
'start_date' => 'required|before:end_date|date',
|
'start' => 'required|before:end|date',
|
||||||
'end_date' => 'required|after:start_date|date',
|
'end' => 'required|after:start|date',
|
||||||
'amount' => 'required|more:0',
|
'amount' => 'required|more:0',
|
||||||
|
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||||
|
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||||
];
|
];
|
||||||
switch ($this->method()) {
|
switch ($this->method()) {
|
||||||
default:
|
default:
|
||||||
@@ -76,6 +82,12 @@ class BudgetLimitRequest extends Request
|
|||||||
$rules['budget_id'] = 'required|exists:budgets,id|belongsToUser:budgets,id';
|
$rules['budget_id'] = 'required|exists:budgets,id|belongsToUser:budgets,id';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// if request has a budget already, drop the rule.
|
||||||
|
$budget = $this->route()->parameter('budget');
|
||||||
|
if (null !== $budget) {
|
||||||
|
unset($rules['budget_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,12 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Api\V1\Requests;
|
namespace FireflyIII\Api\V1\Requests;
|
||||||
|
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
|
use FireflyIII\Rules\IsBoolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BudgetRequest
|
* Class BudgetRequest
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* TODO AFTER 4.8,0: split this into two request classes.
|
||||||
*/
|
*/
|
||||||
class BudgetRequest extends Request
|
class BudgetRequest extends Request
|
||||||
{
|
{
|
||||||
@@ -48,9 +51,14 @@ class BudgetRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function getAll(): array
|
public function getAll(): array
|
||||||
{
|
{
|
||||||
|
$active = true;
|
||||||
|
if (null !== $this->get('active')) {
|
||||||
|
$active = $this->boolean('active');
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'name' => $this->string('name'),
|
'name' => $this->string('name'),
|
||||||
'active' => $this->boolean('active'),
|
'active' => $active,
|
||||||
'order' => 0,
|
'order' => 0,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -64,7 +72,7 @@ class BudgetRequest extends Request
|
|||||||
{
|
{
|
||||||
$rules = [
|
$rules = [
|
||||||
'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name',
|
'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name',
|
||||||
'active' => 'required|boolean',
|
'active' => [new IsBoolean],
|
||||||
];
|
];
|
||||||
switch ($this->method()) {
|
switch ($this->method()) {
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ use FireflyIII\Models\Category;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CategoryRequest
|
* Class CategoryRequest
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* TODO AFTER 4.8,0: split this into two request classes.
|
||||||
*/
|
*/
|
||||||
class CategoryRequest extends Request
|
class CategoryRequest extends Request
|
||||||
{
|
{
|
||||||
@@ -49,8 +51,7 @@ class CategoryRequest extends Request
|
|||||||
public function getAll(): array
|
public function getAll(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => $this->string('name'),
|
'name' => $this->string('name'),
|
||||||
'active' => $this->boolean('active'),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,8 +63,7 @@ class CategoryRequest extends Request
|
|||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
$rules = [
|
$rules = [
|
||||||
'name' => 'required|between:1,100|uniqueObjectForUser:categories,name',
|
'name' => 'required|between:1,100|uniqueObjectForUser:categories,name',
|
||||||
'active' => 'required|boolean',
|
|
||||||
];
|
];
|
||||||
switch ($this->method()) {
|
switch ($this->method()) {
|
||||||
default:
|
default:
|
||||||
|
|||||||
84
app/Api/V1/Requests/ConfigurationRequest.php
Normal file
84
app/Api/V1/Requests/ConfigurationRequest.php
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<?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,13 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Requests;
|
namespace FireflyIII\Api\V1\Requests;
|
||||||
|
|
||||||
|
use FireflyIII\Rules\IsBoolean;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CurrencyRequest
|
* Class CurrencyRequest
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* TODO AFTER 4.8,0: split this into two request classes.
|
||||||
*/
|
*/
|
||||||
class CurrencyRequest extends Request
|
class CurrencyRequest extends Request
|
||||||
{
|
{
|
||||||
@@ -47,12 +51,22 @@ class CurrencyRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function getAll(): array
|
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 [
|
return [
|
||||||
'name' => $this->string('name'),
|
'name' => $this->string('name'),
|
||||||
'code' => $this->string('code'),
|
'code' => $this->string('code'),
|
||||||
'symbol' => $this->string('symbol'),
|
'symbol' => $this->string('symbol'),
|
||||||
'decimal_places' => $this->integer('decimal_places'),
|
'decimal_places' => $this->integer('decimal_places'),
|
||||||
'default' => $this->boolean('default'),
|
'default' => $default,
|
||||||
|
'enabled' => $enabled,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,8 +81,10 @@ class CurrencyRequest extends Request
|
|||||||
'name' => 'required|between:1,255|unique:transaction_currencies,name',
|
'name' => 'required|between:1,255|unique:transaction_currencies,name',
|
||||||
'code' => 'required|between:3,3|unique:transaction_currencies,code',
|
'code' => 'required|between:3,3|unique:transaction_currencies,code',
|
||||||
'symbol' => 'required|between:1,5|unique:transaction_currencies,symbol',
|
'symbol' => 'required|between:1,5|unique:transaction_currencies,symbol',
|
||||||
'decimal_places' => 'required|between:0,20|numeric|min:0|max:20',
|
'decimal_places' => 'between:0,20|numeric|min:0|max:20',
|
||||||
'default' => 'boolean',
|
'enabled' => [new IsBoolean()],
|
||||||
|
'default' => [new IsBoolean()],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
switch ($this->method()) {
|
switch ($this->method()) {
|
||||||
@@ -76,7 +92,7 @@ class CurrencyRequest extends Request
|
|||||||
break;
|
break;
|
||||||
case 'PUT':
|
case 'PUT':
|
||||||
case 'PATCH':
|
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['name'] = 'required|between:1,255|unique:transaction_currencies,name,' . $currency->id;
|
||||||
$rules['code'] = 'required|between:1,255|unique:transaction_currencies,code,' . $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['symbol'] = 'required|between:1,255|unique:transaction_currencies,symbol,' . $currency->id;
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ReconciliationUpdateRequest.php
|
* DateRequest.php
|
||||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This file is part of Firefly III.
|
* This file is part of Firefly III.
|
||||||
*
|
*
|
||||||
@@ -18,54 +19,53 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
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
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize(): bool
|
||||||
{
|
{
|
||||||
// Only allow logged in users
|
// Only allow authenticated users
|
||||||
return auth()->check();
|
return auth()->check();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns and validates the data required to update a reconciliation.
|
* Get all data from the request.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getJournalData(): array
|
public function getAll(): array
|
||||||
{
|
{
|
||||||
$data = [
|
return [
|
||||||
'tags' => explode(',', $this->string('tags')),
|
'start' => $this->date('start'),
|
||||||
'amount' => $this->string('amount'),
|
'end' => $this->date('end'),
|
||||||
'category' => $this->string('category'),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rules for this request.
|
* The rules that the incoming request must be matched against.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
$rules = [
|
return [
|
||||||
'amount' => 'numeric|required',
|
'start' => 'required|date',
|
||||||
'category' => 'between:1,255|nullable',
|
'end' => 'required|date|after:start',
|
||||||
];
|
];
|
||||||
|
|
||||||
return $rules;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,8 @@ use Illuminate\Validation\Rule;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Class LinkTypeRequest
|
* Class LinkTypeRequest
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* TODO AFTER 4.8,0: split this into two request classes.
|
||||||
*/
|
*/
|
||||||
class LinkTypeRequest extends Request
|
class LinkTypeRequest extends Request
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,10 +25,13 @@ namespace FireflyIII\Api\V1\Requests;
|
|||||||
|
|
||||||
use FireflyIII\Models\PiggyBank;
|
use FireflyIII\Models\PiggyBank;
|
||||||
use FireflyIII\Rules\IsAssetAccountId;
|
use FireflyIII\Rules\IsAssetAccountId;
|
||||||
|
use FireflyIII\Rules\ZeroOrMore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Class PiggyBankRequest
|
* Class PiggyBankRequest
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* TODO AFTER 4.8,0: split this into two request classes.
|
||||||
*/
|
*/
|
||||||
class PiggyBankRequest extends Request
|
class PiggyBankRequest extends Request
|
||||||
{
|
{
|
||||||
@@ -50,14 +53,17 @@ class PiggyBankRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function getAll(): array
|
public function getAll(): array
|
||||||
{
|
{
|
||||||
|
$current = $this->string('current_amount');
|
||||||
|
$current = '' === $current ? '0' : $current;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'name' => $this->string('name'),
|
'name' => $this->string('name'),
|
||||||
'account_id' => $this->integer('account_id'),
|
'account_id' => $this->integer('account_id'),
|
||||||
'targetamount' => $this->string('target_amount'),
|
'targetamount' => $this->string('target_amount'),
|
||||||
'current_amount' => $this->string('current_amount'),
|
'current_amount' => $current,
|
||||||
'start_date' => $this->date('start_date'),
|
'startdate' => $this->date('start_date'),
|
||||||
'target_date' => $this->date('target_date'),
|
'targetdate' => $this->date('target_date'),
|
||||||
'notes' => $this->string('notes'),
|
'notes' => $this->string('notes'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,9 +78,9 @@ class PiggyBankRequest extends Request
|
|||||||
'name' => 'required|between:1,255|uniquePiggyBankForUser',
|
'name' => 'required|between:1,255|uniquePiggyBankForUser',
|
||||||
'account_id' => ['required', 'belongsToUser:accounts', new IsAssetAccountId],
|
'account_id' => ['required', 'belongsToUser:accounts', new IsAssetAccountId],
|
||||||
'target_amount' => 'required|numeric|more:0',
|
'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',
|
'start_date' => 'date|nullable',
|
||||||
'target_date' => 'date|nullable',
|
'target_date' => 'date|nullable|after:start_date',
|
||||||
'notes' => 'max:65000',
|
'notes' => 'max:65000',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Class PreferenceRequest
|
* Class PreferenceRequest
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
class PreferenceRequest extends Request
|
class PreferenceRequest extends Request
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,203 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* RecurrenceRequest.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 Carbon\Carbon;
|
|
||||||
use FireflyIII\Rules\BelongsUser;
|
|
||||||
use FireflyIII\Validation\RecurrenceValidation;
|
|
||||||
use FireflyIII\Validation\TransactionValidation;
|
|
||||||
use Illuminate\Validation\Validator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class RecurrenceRequest
|
|
||||||
*/
|
|
||||||
class RecurrenceRequest 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
|
|
||||||
{
|
|
||||||
$return = [
|
|
||||||
'recurrence' => [
|
|
||||||
'type' => $this->string('type'),
|
|
||||||
'title' => $this->string('title'),
|
|
||||||
'description' => $this->string('description'),
|
|
||||||
'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')),
|
|
||||||
],
|
|
||||||
'transactions' => $this->getTransactionData(),
|
|
||||||
'repetitions' => $this->getRepetitionData(),
|
|
||||||
];
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The rules that the incoming request must be matched against.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function rules(): array
|
|
||||||
{
|
|
||||||
$today = Carbon::now()->addDay();
|
|
||||||
|
|
||||||
return [
|
|
||||||
'type' => 'required|in:withdrawal,transfer,deposit',
|
|
||||||
'title' => 'required|between:1,255|uniqueObjectForUser:recurrences,title',
|
|
||||||
'description' => 'between:1,65000',
|
|
||||||
'first_date' => sprintf('required|date|after:%s', $today->format('Y-m-d')),
|
|
||||||
'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.*.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.*.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',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the validator instance.
|
|
||||||
*
|
|
||||||
* @param Validator $validator
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function withValidator(Validator $validator): void
|
|
||||||
{
|
|
||||||
$validator->after(
|
|
||||||
function (Validator $validator) {
|
|
||||||
$this->validateOneTransaction($validator);
|
|
||||||
$this->validateOneRepetition($validator);
|
|
||||||
$this->validateRecurrenceRepetition($validator);
|
|
||||||
$this->validateRepetitionMoment($validator);
|
|
||||||
$this->validateForeignCurrencyInformation($validator);
|
|
||||||
$this->validateAccountInformation($validator);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the repetition data as it is found in the submitted data.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getRepetitionData(): array
|
|
||||||
{
|
|
||||||
$return = [];
|
|
||||||
// repetition data:
|
|
||||||
/** @var array $repetitions */
|
|
||||||
$repetitions = $this->get('repetitions');
|
|
||||||
/** @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
|
|
||||||
* @SuppressWarnings(PHPMD.NPathComplexity)
|
|
||||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
|
||||||
*/
|
|
||||||
private function getTransactionData(): array
|
|
||||||
{
|
|
||||||
$return = [];
|
|
||||||
// transaction data:
|
|
||||||
/** @var array $transactions */
|
|
||||||
$transactions = $this->get('transactions');
|
|
||||||
/** @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,
|
|
||||||
'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'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
78
app/Api/V1/Requests/RecurrenceStoreRequest.php
Normal file
78
app/Api/V1/Requests/RecurrenceStoreRequest.php
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* RecurrenceStoreRequest.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\Validation\RecurrenceValidation;
|
||||||
|
use FireflyIII\Validation\TransactionValidation;
|
||||||
|
use Illuminate\Validation\Validator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RecurrenceStoreRequest
|
||||||
|
*/
|
||||||
|
class RecurrenceStoreRequest extends Request
|
||||||
|
{
|
||||||
|
use RecurrenceValidation, TransactionValidation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
return $this->rulesRecurrence();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the validator instance.
|
||||||
|
*
|
||||||
|
* @param Validator $validator
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function withValidator(Validator $validator): void
|
||||||
|
{
|
||||||
|
$validator->after(
|
||||||
|
function (Validator $validator) {
|
||||||
|
$this->validateOneRecurrenceTransaction($validator);
|
||||||
|
$this->validateOneRepetition($validator);
|
||||||
|
$this->validateRecurrenceRepetition($validator);
|
||||||
|
$this->validateRepetitionMoment($validator);
|
||||||
|
$this->validateForeignCurrencyInformation($validator);
|
||||||
|
$this->validateAccountInformation($validator);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
78
app/Api/V1/Requests/RecurrenceUpdateRequest.php
Normal file
78
app/Api/V1/Requests/RecurrenceUpdateRequest.php
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<?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\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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rules that the incoming request must be matched against.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return $this->rulesRecurrence();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the validator instance.
|
||||||
|
*
|
||||||
|
* @param Validator $validator
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function withValidator(Validator $validator): void
|
||||||
|
{
|
||||||
|
$validator->after(
|
||||||
|
function (Validator $validator) {
|
||||||
|
$this->validateOneTransaction($validator);
|
||||||
|
$this->validateOneRepetition($validator);
|
||||||
|
$this->validateRecurrenceRepetition($validator);
|
||||||
|
$this->validateRepetitionMoment($validator);
|
||||||
|
$this->validateForeignCurrencyInformation($validator);
|
||||||
|
$this->validateAccountInformation($validator);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,16 +24,205 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Requests;
|
namespace FireflyIII\Api\V1\Requests;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Http\Requests\Request as FireflyIIIRequest;
|
use FireflyIII\Http\Requests\Request as FireflyIIIRequest;
|
||||||
|
use FireflyIII\Rules\BelongsUser;
|
||||||
|
use FireflyIII\Rules\IsBoolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Request.
|
* Class Request.
|
||||||
*
|
*
|
||||||
* Technically speaking this class does not have to be extended like this but who knows what the future brings.
|
* 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
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all data from the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAllRecurrenceData(): 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'),
|
||||||
|
'title' => $this->string('title'),
|
||||||
|
'description' => $this->string('description'),
|
||||||
|
'first_date' => $this->date('first_date'),
|
||||||
|
'repeat_until' => $this->date('repeat_until'),
|
||||||
|
'repetitions' => $this->integer('nr_of_repetitions'),
|
||||||
|
'apply_rules' => $applyRules,
|
||||||
|
'active' => $active,
|
||||||
|
],
|
||||||
|
'meta' => [
|
||||||
|
'piggy_bank_id' => $this->integer('piggy_bank_id'),
|
||||||
|
'piggy_bank_name' => $this->string('piggy_bank_name'),
|
||||||
|
'tags' => explode(',', $this->string('tags')),
|
||||||
|
],
|
||||||
|
'transactions' => $this->getRecurrenceTransactionData(),
|
||||||
|
'repetitions' => $this->getRecurrenceRepetitionData(),
|
||||||
|
];
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rules that the incoming request must be matched against.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function rulesRecurrence(): array
|
||||||
|
{
|
||||||
|
$today = Carbon::now()->addDay();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'type' => 'required|in:withdrawal,transfer,deposit',
|
||||||
|
'title' => 'required|between:1,255|uniqueObjectForUser:recurrences,title',
|
||||||
|
'description' => 'between:1,65000',
|
||||||
|
'first_date' => sprintf('required|date|after:%s', $today->format('Y-m-d')),
|
||||||
|
'apply_rules' => [new IsBoolean],
|
||||||
|
'active' => [new IsBoolean],
|
||||||
|
'repeat_until' => sprintf('date|after:%s', $today->format('Y-m-d')),
|
||||||
|
'nr_of_repetitions' => 'numeric|between:1,31',
|
||||||
|
'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.*.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',
|
||||||
|
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the repetition data as it is found in the submitted data.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getRecurrenceRepetitionData(): array
|
||||||
|
{
|
||||||
|
$return = [];
|
||||||
|
// repetition data:
|
||||||
|
/** @var array $repetitions */
|
||||||
|
$repetitions = $this->get('repetitions');
|
||||||
|
/** @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
|
||||||
|
*/
|
||||||
|
protected function getRecurrenceTransactionData(): array
|
||||||
|
{
|
||||||
|
$return = [];
|
||||||
|
// transaction data:
|
||||||
|
/** @var array $transactions */
|
||||||
|
$transactions = $this->get('transactions');
|
||||||
|
/** @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,
|
||||||
|
'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'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,11 +24,13 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Api\V1\Requests;
|
namespace FireflyIII\Api\V1\Requests;
|
||||||
|
|
||||||
use FireflyIII\Models\RuleGroup;
|
use FireflyIII\Models\RuleGroup;
|
||||||
|
use FireflyIII\Rules\IsBoolean;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @codeCoverageIgnore
|
||||||
* Class RuleGroupRequest
|
* Class RuleGroupRequest
|
||||||
|
* TODO AFTER 4.8,0: split this into two request classes.
|
||||||
*/
|
*/
|
||||||
class RuleGroupRequest extends Request
|
class RuleGroupRequest extends Request
|
||||||
{
|
{
|
||||||
@@ -50,10 +52,16 @@ class RuleGroupRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function getAll(): array
|
public function getAll(): array
|
||||||
{
|
{
|
||||||
|
$active = true;
|
||||||
|
|
||||||
|
if (null !== $this->get('active')) {
|
||||||
|
$active = $this->boolean('active');
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $this->string('title'),
|
'title' => $this->string('title'),
|
||||||
'description' => $this->string('description'),
|
'description' => $this->string('description'),
|
||||||
'active' => $this->boolean('active'),
|
'active' => $active,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +75,7 @@ class RuleGroupRequest extends Request
|
|||||||
$rules = [
|
$rules = [
|
||||||
'title' => 'required|between:1,100|uniqueObjectForUser:rule_groups,title',
|
'title' => 'required|between:1,100|uniqueObjectForUser:rule_groups,title',
|
||||||
'description' => 'between:1,5000|nullable',
|
'description' => 'between:1,5000|nullable',
|
||||||
'active' => 'required|boolean',
|
'active' => [new IsBoolean],
|
||||||
];
|
];
|
||||||
switch ($this->method()) {
|
switch ($this->method()) {
|
||||||
default:
|
default:
|
||||||
|
|||||||
148
app/Api/V1/Requests/RuleGroupTestRequest.php
Normal file
148
app/Api/V1/Requests/RuleGroupTestRequest.php
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
<?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 [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 Account|null $account
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function validAccount(?Account $account): bool
|
||||||
|
{
|
||||||
|
return null !== $account && AccountType::ASSET === $account->accountType->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
123
app/Api/V1/Requests/RuleGroupTriggerRequest.php
Normal file
123
app/Api/V1/Requests/RuleGroupTriggerRequest.php
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
<?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',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 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 Account|null $account
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function validAccount(?Account $account): bool
|
||||||
|
{
|
||||||
|
return null !== $account && AccountType::ASSET === $account->accountType->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -23,11 +23,14 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Requests;
|
namespace FireflyIII\Api\V1\Requests;
|
||||||
|
|
||||||
|
use FireflyIII\Rules\IsBoolean;
|
||||||
use Illuminate\Validation\Validator;
|
use Illuminate\Validation\Validator;
|
||||||
|
use function is_array;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RuleRequest
|
* Class RuleRequest
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
class RuleRequest extends Request
|
class RuleRequest extends Request
|
||||||
{
|
{
|
||||||
@@ -49,17 +52,30 @@ class RuleRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function getAll(): array
|
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 = [
|
$data = [
|
||||||
'title' => $this->string('title'),
|
'title' => $this->string('title'),
|
||||||
'description' => $this->string('description'),
|
'description' => $this->string('description'),
|
||||||
'rule_group_id' => $this->integer('rule_group_id'),
|
'rule_group_id' => $this->integer('rule_group_id'),
|
||||||
'rule_group_title' => $this->string('rule_group_title'),
|
'rule_group_title' => $this->string('rule_group_title'),
|
||||||
'trigger' => $this->string('trigger'),
|
'trigger' => $this->string('trigger'),
|
||||||
'strict' => $this->boolean('strict'),
|
'strict' => $strict,
|
||||||
'stop_processing' => $this->boolean('stop_processing'),
|
'stop_processing' => $stopProcessing,
|
||||||
'active' => $this->boolean('active'),
|
'active' => $active,
|
||||||
'rule_triggers' => $this->getRuleTriggers(),
|
'triggers' => $this->getRuleTriggers(),
|
||||||
'rule_actions' => $this->getRuleActions(),
|
'actions' => $this->getRuleActions(),
|
||||||
];
|
];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
@@ -75,24 +91,26 @@ class RuleRequest extends Request
|
|||||||
$validTriggers = array_keys(config('firefly.rule-triggers'));
|
$validTriggers = array_keys(config('firefly.rule-triggers'));
|
||||||
$validActions = array_keys(config('firefly.rule-actions'));
|
$validActions = array_keys(config('firefly.rule-actions'));
|
||||||
|
|
||||||
// some actions require text:
|
// some triggers and actions require text:
|
||||||
$contextActions = implode(',', config('firefly.rule-actions-text'));
|
$contextTriggers = implode(',', config('firefly.context-rule-triggers'));
|
||||||
|
$contextActions = implode(',', config('firefly.context-rule-actions'));
|
||||||
$rules = [
|
$rules = [
|
||||||
'title' => 'required|between:1,100|uniqueObjectForUser:rules,title',
|
'title' => 'required|between:1,100|uniqueObjectForUser:rules,title',
|
||||||
'description' => 'between:1,5000|nullable',
|
'description' => 'between:1,5000|nullable',
|
||||||
'rule_group_id' => 'required|belongsToUser:rule_groups|required_without:rule_group_title',
|
'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',
|
'rule_group_title' => 'nullable|between:1,255|required_without:rule_group_id|belongsToUser:rule_groups,title',
|
||||||
'trigger' => 'required|in:store-journal,update-journal',
|
'trigger' => 'required|in:store-journal,update-journal',
|
||||||
'rule_triggers.*.name' => 'required|in:' . implode(',', $validTriggers),
|
'triggers.*.type' => 'required|in:' . implode(',', $validTriggers),
|
||||||
'rule_triggers.*.stop_processing' => 'boolean',
|
'triggers.*.value' => 'required_if:actions.*.type,' . $contextTriggers . '|min:1|ruleTriggerValue',
|
||||||
'rule_triggers.*.value' => 'required|min:1|ruleTriggerValue',
|
'triggers.*.stop_processing' => [new IsBoolean],
|
||||||
'rule_actions.*.name' => 'required|in:' . implode(',', $validActions),
|
'triggers.*.active' => [new IsBoolean],
|
||||||
'rule_actions.*.value' => 'required_if:rule_actions.*.type,' . $contextActions . '|ruleActionValue',
|
'actions.*.type' => 'required|in:' . implode(',', $validActions),
|
||||||
'rule_actions.*.stop_processing' => 'boolean',
|
'actions.*.value' => 'required_if:actions.*.type,' . $contextActions . '|ruleActionValue',
|
||||||
'strict' => 'required|boolean',
|
'actions.*.stop_processing' => [new IsBoolean],
|
||||||
'stop_processing' => 'required|boolean',
|
'actions.*.active' => [new IsBoolean],
|
||||||
'active' => 'required|boolean',
|
'strict' => [new IsBoolean],
|
||||||
|
'stop_processing' => [new IsBoolean],
|
||||||
|
'active' => [new IsBoolean],
|
||||||
];
|
];
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
@@ -101,7 +119,7 @@ class RuleRequest extends Request
|
|||||||
/**
|
/**
|
||||||
* Configure the validator instance.
|
* Configure the validator instance.
|
||||||
*
|
*
|
||||||
* @param Validator $validator
|
* @param Validator $validator
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@@ -120,13 +138,13 @@ class RuleRequest extends Request
|
|||||||
*
|
*
|
||||||
* @param Validator $validator
|
* @param Validator $validator
|
||||||
*/
|
*/
|
||||||
protected function atLeastOneAction(Validator $validator): void
|
protected function atLeastOneTrigger(Validator $validator): void
|
||||||
{
|
{
|
||||||
$data = $validator->getData();
|
$data = $validator->getData();
|
||||||
$repetitions = $data['rule_actions'] ?? [];
|
$triggers = $data['triggers'] ?? [];
|
||||||
// need at least one transaction
|
// need at least one trigger
|
||||||
if (0 === \count($repetitions)) {
|
if (0 === count($triggers)) {
|
||||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
|
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,49 +153,51 @@ class RuleRequest extends Request
|
|||||||
*
|
*
|
||||||
* @param Validator $validator
|
* @param Validator $validator
|
||||||
*/
|
*/
|
||||||
protected function atLeastOneTrigger(Validator $validator): void
|
protected function atLeastOneAction(Validator $validator): void
|
||||||
{
|
{
|
||||||
$data = $validator->getData();
|
$data = $validator->getData();
|
||||||
$repetitions = $data['rule_triggers'] ?? [];
|
$actions = $data['actions'] ?? [];
|
||||||
// need at least one transaction
|
// need at least one trigger
|
||||||
if (0 === \count($repetitions)) {
|
if (0 === count($actions)) {
|
||||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
|
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getRuleActions(): array
|
|
||||||
{
|
|
||||||
$actions = $this->get('rule_actions');
|
|
||||||
$return = [];
|
|
||||||
if (\is_array($actions)) {
|
|
||||||
foreach ($actions as $action) {
|
|
||||||
$return[] = [
|
|
||||||
'name' => $action['name'],
|
|
||||||
'value' => $action['value'],
|
|
||||||
'stop_processing' => 1 === (int)($action['stop-processing'] ?? '0'),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function getRuleTriggers(): array
|
private function getRuleTriggers(): array
|
||||||
{
|
{
|
||||||
$triggers = $this->get('rule_triggers');
|
$triggers = $this->get('triggers');
|
||||||
$return = [];
|
$return = [];
|
||||||
if (\is_array($triggers)) {
|
if (is_array($triggers)) {
|
||||||
foreach ($triggers as $trigger) {
|
foreach ($triggers as $trigger) {
|
||||||
$return[] = [
|
$return[] = [
|
||||||
'name' => $trigger['name'],
|
'type' => $trigger['type'],
|
||||||
'value' => $trigger['value'],
|
'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')),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getRuleActions(): array
|
||||||
|
{
|
||||||
|
$actions = $this->get('actions');
|
||||||
|
$return = [];
|
||||||
|
if (is_array($actions)) {
|
||||||
|
foreach ($actions as $action) {
|
||||||
|
$return[] = [
|
||||||
|
'type' => $action['type'],
|
||||||
|
'value' => $action['value'],
|
||||||
|
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
|
||||||
|
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
148
app/Api/V1/Requests/RuleTestRequest.php
Normal file
148
app/Api/V1/Requests/RuleTestRequest.php
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
<?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 [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 Account|null $account
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function validAccount(?Account $account): bool
|
||||||
|
{
|
||||||
|
return null !== $account && AccountType::ASSET === $account->accountType->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
122
app/Api/V1/Requests/RuleTriggerRequest.php
Normal file
122
app/Api/V1/Requests/RuleTriggerRequest.php
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<?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',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 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 Account|null $account
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function validAccount(?Account $account): bool
|
||||||
|
{
|
||||||
|
return null !== $account && AccountType::ASSET === $account->accountType->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
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
|
<?php
|
||||||
/**
|
/**
|
||||||
* JournalLinkRequest.php
|
* TransactionLinkRequest.php
|
||||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||||
*
|
*
|
||||||
* This file is part of Firefly III.
|
* This file is part of Firefly III.
|
||||||
@@ -25,13 +25,14 @@ namespace FireflyIII\Api\V1\Requests;
|
|||||||
|
|
||||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||||
|
use FireflyIII\User;
|
||||||
use Illuminate\Validation\Validator;
|
use Illuminate\Validation\Validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Class JournalLinkRequest
|
* Class TransactionLinkRequest
|
||||||
*/
|
*/
|
||||||
class JournalLinkRequest extends Request
|
class TransactionLinkRequest extends Request
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Authorize logged in users.
|
* Authorize logged in users.
|
||||||
@@ -71,8 +72,8 @@ class JournalLinkRequest extends Request
|
|||||||
return [
|
return [
|
||||||
'link_type_id' => 'exists:link_types,id|required_without:link_type_name',
|
'link_type_id' => 'exists:link_types,id|required_without:link_type_name',
|
||||||
'link_type_name' => 'exists:link_types,name|required_without:link_type_id',
|
'link_type_name' => 'exists:link_types,name|required_without:link_type_id',
|
||||||
'inward_id' => 'required|belongsToUser:transaction_journals,id',
|
'inward_id' => 'required|belongsToUser:transaction_journals,id|different:outward_id',
|
||||||
'outward_id' => 'required|belongsToUser:transaction_journals,id',
|
'outward_id' => 'required|belongsToUser:transaction_journals,id|different:inward_id',
|
||||||
'notes' => 'between:0,65000',
|
'notes' => 'between:0,65000',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -80,7 +81,7 @@ class JournalLinkRequest extends Request
|
|||||||
/**
|
/**
|
||||||
* Configure the validator instance.
|
* Configure the validator instance.
|
||||||
*
|
*
|
||||||
* @param Validator $validator
|
* @param Validator $validator
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@@ -98,13 +99,15 @@ class JournalLinkRequest extends Request
|
|||||||
*/
|
*/
|
||||||
private function validateExistingLink(Validator $validator): void
|
private function validateExistingLink(Validator $validator): void
|
||||||
{
|
{
|
||||||
|
/** @var User $user */
|
||||||
|
$user = auth()->user();
|
||||||
/** @var LinkTypeRepositoryInterface $repository */
|
/** @var LinkTypeRepositoryInterface $repository */
|
||||||
$repository = app(LinkTypeRepositoryInterface::class);
|
$repository = app(LinkTypeRepositoryInterface::class);
|
||||||
$repository->setUser(auth()->user());
|
$repository->setUser($user);
|
||||||
|
|
||||||
/** @var JournalRepositoryInterface $journalRepos */
|
/** @var JournalRepositoryInterface $journalRepos */
|
||||||
$journalRepos = app(JournalRepositoryInterface::class);
|
$journalRepos = app(JournalRepositoryInterface::class);
|
||||||
$journalRepos->setUser(auth()->user());
|
$journalRepos->setUser($user);
|
||||||
|
|
||||||
$data = $validator->getData();
|
$data = $validator->getData();
|
||||||
$inwardId = (int)($data['inward_id'] ?? 0);
|
$inwardId = (int)($data['inward_id'] ?? 0);
|
||||||
@@ -124,8 +127,12 @@ class JournalLinkRequest extends Request
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($repository->findLink($inward, $outward)) {
|
if ($repository->findLink($inward, $outward)) {
|
||||||
$validator->errors()->add('outward_id', 'Already have a link between inward and outward.');
|
// only if not updating:
|
||||||
$validator->errors()->add('inward_id', 'Already have a link between inward and outward.');
|
$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;
|
||||||
|
}
|
||||||
|
}
|
||||||
324
app/Api/V1/Requests/TransactionUpdateRequest.php
Normal file
324
app/Api/V1/Requests/TransactionUpdateRequest.php
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
<?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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,11 +25,14 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Api\V1\Requests;
|
namespace FireflyIII\Api\V1\Requests;
|
||||||
|
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
|
use FireflyIII\Rules\IsBoolean;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class UserRequest
|
* Class UserRequest
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* TODO AFTER 4.8,0: split this into two request classes.
|
||||||
*/
|
*/
|
||||||
class UserRequest extends Request
|
class UserRequest extends Request
|
||||||
{
|
{
|
||||||
@@ -64,10 +67,15 @@ class UserRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function getAll(): array
|
public function getAll(): array
|
||||||
{
|
{
|
||||||
|
$blocked = false;
|
||||||
|
if (null === $this->get('blocked')) {
|
||||||
|
$blocked = $this->boolean('blocked');
|
||||||
|
}
|
||||||
$data = [
|
$data = [
|
||||||
'email' => $this->string('email'),
|
'email' => $this->string('email'),
|
||||||
'blocked' => $this->boolean('blocked'),
|
'blocked' => $blocked,
|
||||||
'blocked_code' => $this->string('blocked_code'),
|
'blocked_code' => $this->string('blocked_code'),
|
||||||
|
'role' => $this->string('role'),
|
||||||
];
|
];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
@@ -82,8 +90,9 @@ class UserRequest extends Request
|
|||||||
{
|
{
|
||||||
$rules = [
|
$rules = [
|
||||||
'email' => 'required|email|unique:users,email,',
|
'email' => 'required|email|unique:users,email,',
|
||||||
'blocked' => 'required|boolean',
|
'blocked' => [new IsBoolean],
|
||||||
'blocked_code' => 'in:email_changed',
|
'blocked_code' => 'in:email_changed',
|
||||||
|
'role' => 'in:owner,demo',
|
||||||
];
|
];
|
||||||
switch ($this->method()) {
|
switch ($this->method()) {
|
||||||
default:
|
default:
|
||||||
|
|||||||
83
app/Console/Commands/Correction/CorrectDatabase.php
Normal file
83
app/Console/Commands/Correction/CorrectDatabase.php
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* CorrectDatabase.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\Console\Commands\Correction;
|
||||||
|
|
||||||
|
|
||||||
|
use Artisan;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Schema;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CorrectDatabase
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
class CorrectDatabase extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Will correct the integrity of your database, if necessary.';
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'firefly-iii:correct-database';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
// if table does not exist, return false
|
||||||
|
if (!Schema::hasTable('users')) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
$commands = [
|
||||||
|
'firefly-iii:fix-piggies',
|
||||||
|
'firefly-iii:create-link-types',
|
||||||
|
'firefly-iii:create-access-tokens',
|
||||||
|
'firefly-iii:remove-bills',
|
||||||
|
'firefly-iii:enable-currencies',
|
||||||
|
'firefly-iii:fix-transfer-budgets',
|
||||||
|
'firefly-iii:fix-uneven-amount',
|
||||||
|
'firefly-iii:delete-zero-amount',
|
||||||
|
'firefly-iii:delete-orphaned-transactions',
|
||||||
|
'firefly-iii:delete-empty-journals',
|
||||||
|
'firefly-iii:delete-empty-groups',
|
||||||
|
'firefly-iii:fix-account-types',
|
||||||
|
'firefly-iii:rename-meta-fields',
|
||||||
|
];
|
||||||
|
foreach ($commands as $command) {
|
||||||
|
$this->line(sprintf('Now executing %s', $command));
|
||||||
|
Artisan::call($command);
|
||||||
|
$result = Artisan::output();
|
||||||
|
echo $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
57
app/Console/Commands/Correction/CorrectionSkeleton.php.stub
Normal file
57
app/Console/Commands/Correction/CorrectionSkeleton.php.stub
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* VerifySkeleton.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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace FireflyIII\Console\Commands\Correction;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CorrectionSkeleton
|
||||||
|
*/
|
||||||
|
class CorrectionSkeleton extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'DESCRIPTION HERE';
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'firefly-iii:CORR_COMMAND';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
//
|
||||||
|
$this->warn('Congrats, you found the skeleton command. Boo!');
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user