mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-11-02 12:15:55 +00:00
Compare commits
1840 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 | ||
|
|
bc4ac303e2 | ||
|
|
0e9fbecbe4 | ||
|
|
226b3cfdd8 | ||
|
|
d43fa3790d | ||
|
|
ca04113aa7 | ||
|
|
817c157db4 | ||
|
|
07edbe758a | ||
|
|
46ba0a5a5a | ||
|
|
480b636c7e | ||
|
|
20340dff7b | ||
|
|
cfbabb500f | ||
|
|
a4cb2c1cb1 | ||
|
|
bd31b7e943 | ||
|
|
b2e7c767df | ||
|
|
bb9f763729 | ||
|
|
fb61229bf3 | ||
|
|
fc30d41ee5 | ||
|
|
7666147f3c | ||
|
|
52f8b24041 | ||
|
|
eaf2667abb | ||
|
|
de754ca4e0 | ||
|
|
96dd89fbeb | ||
|
|
bae40e2cbc | ||
|
|
6a647dab8b | ||
|
|
ebcf5b71d2 | ||
|
|
02370fb65d | ||
|
|
1e4f4907e3 | ||
|
|
13f72c73fb | ||
|
|
69b4632ef6 | ||
|
|
ede8c293fc | ||
|
|
0cfe991482 | ||
|
|
6377459e2f | ||
|
|
33fe6dbfa3 | ||
|
|
e158b9b64e | ||
|
|
dfa9e537b3 | ||
|
|
6d28ece616 | ||
|
|
59f4ecdaa6 | ||
|
|
10d953f336 | ||
|
|
5b771f7def | ||
|
|
4a8e3ee845 | ||
|
|
9a1f559dd2 | ||
|
|
62321a03ca | ||
|
|
40ca72c656 | ||
|
|
34fcff7a9d | ||
|
|
e1c829f4fa | ||
|
|
46136d94e9 | ||
|
|
0e2e8d1be5 | ||
|
|
1d1aa5dd3a | ||
|
|
0d82589916 | ||
|
|
4fc13037d2 | ||
|
|
3764499714 | ||
|
|
c4bbbc49b4 | ||
|
|
503158ab97 | ||
|
|
8c1d1d1db0 | ||
|
|
7dc72a2894 | ||
|
|
07cfba1b3a | ||
|
|
c55b80f467 | ||
|
|
2099da7142 | ||
|
|
ea125936e7 | ||
|
|
5de01628a6 | ||
|
|
2834aca597 | ||
|
|
88bab888d8 | ||
|
|
dfdbace298 | ||
|
|
a9590d2bb6 | ||
|
|
29a81eb05e | ||
|
|
20490fcd80 | ||
|
|
e775927f60 | ||
|
|
835a421909 | ||
|
|
850a0ae17e | ||
|
|
2b54363dd7 | ||
|
|
b174a06b86 | ||
|
|
d4096103cb | ||
|
|
3f493aceb2 | ||
|
|
05309da76d | ||
|
|
179f720806 | ||
|
|
7c34144ccd | ||
|
|
cc234b594d | ||
|
|
024cf610a8 | ||
|
|
a1896a6336 | ||
|
|
d30da7bf5d | ||
|
|
f8e914416d | ||
|
|
433da921bb | ||
|
|
4876053018 | ||
|
|
0c3a580b33 | ||
|
|
7689b7b4b0 | ||
|
|
21bff39e31 | ||
|
|
ba09901228 | ||
|
|
90bf2e58b2 | ||
|
|
004807aa32 | ||
|
|
35bacf2ad0 | ||
|
|
81d17409d4 | ||
|
|
a8080f55f0 | ||
|
|
379c540bd8 | ||
|
|
f319005357 | ||
|
|
df0e2dd2a2 | ||
|
|
219a0cd612 | ||
|
|
3ca3ce0726 | ||
|
|
566be8dc63 | ||
|
|
6bd4fa1c0a | ||
|
|
c767ee04f4 | ||
|
|
a5f89e0967 | ||
|
|
7355d14159 | ||
|
|
efd5ceb405 | ||
|
|
035dc8ceb4 | ||
|
|
11be33e942 | ||
|
|
e125254687 | ||
|
|
a2b997ba20 | ||
|
|
7327941c77 | ||
|
|
6c9eb1b699 | ||
|
|
60e262dece | ||
|
|
9c5463e515 | ||
|
|
6941176519 | ||
|
|
cb2c52cddb | ||
|
|
dd95776144 | ||
|
|
b95ca98be9 | ||
|
|
67b090b4d8 | ||
|
|
54b76a03ce | ||
|
|
cd6c727730 | ||
|
|
a35c6e29b6 | ||
|
|
95ce72fce7 | ||
|
|
a803dfc7fa | ||
|
|
c465d1c059 | ||
|
|
9914c0791e | ||
|
|
96baf5d3c7 | ||
|
|
a205367b62 | ||
|
|
6218fa90de | ||
|
|
51a770cfdc | ||
|
|
16fba15b5c | ||
|
|
ec2463a3ba | ||
|
|
b605ede74e | ||
|
|
b1b13d3696 | ||
|
|
51b11e5188 | ||
|
|
eefa84a77b | ||
|
|
5908b4b000 | ||
|
|
2ed433c96d | ||
|
|
9865800e39 | ||
|
|
4f697e77d5 | ||
|
|
c957aded98 | ||
|
|
aa0758cd2b | ||
|
|
0c2093753d | ||
|
|
136f983353 | ||
|
|
7943164375 | ||
|
|
32e58d0a60 | ||
|
|
bc807965ab | ||
|
|
477788658b | ||
|
|
723abf44bd | ||
|
|
fd1298d4d2 | ||
|
|
42f39536a1 | ||
|
|
6f0ac91bd2 | ||
|
|
6dea9156ab | ||
|
|
c5051b3e46 | ||
|
|
229d033e1a | ||
|
|
f494ba7065 | ||
|
|
201bc7db53 | ||
|
|
cd2a251f22 | ||
|
|
ff44ad4994 | ||
|
|
b496ca6a2c | ||
|
|
5908c0ce8c | ||
|
|
f7eef25fed | ||
|
|
049c93465a | ||
|
|
33294dd9f0 | ||
|
|
0a89f4000d | ||
|
|
422e80530b | ||
|
|
07a8c69ba8 | ||
|
|
5449879a7d | ||
|
|
8dbc846314 | ||
|
|
f0d3ca5d53 | ||
|
|
5af026674f | ||
|
|
2ebb4778cd | ||
|
|
bf3c57d26b | ||
|
|
cb9c87102f | ||
|
|
c73b003de4 | ||
|
|
771d448a7b | ||
|
|
de12db5f05 | ||
|
|
dd49926cc2 | ||
|
|
7a9ab190eb | ||
|
|
2290fcde22 | ||
|
|
ae85876965 | ||
|
|
f07d8e958f | ||
|
|
610af45dee | ||
|
|
138a5bc3fe | ||
|
|
427e9c5637 | ||
|
|
e3e8336602 | ||
|
|
194073e49a | ||
|
|
1af45aff73 | ||
|
|
56518ea028 | ||
|
|
c1ac2bb156 | ||
|
|
a004f27361 | ||
|
|
7843c55409 | ||
|
|
41da7d9f9a | ||
|
|
2add644706 | ||
|
|
dfd9cf0874 | ||
|
|
7ad09da4e9 | ||
|
|
8efbeb14d2 | ||
|
|
a1005d91df | ||
|
|
a681f1ce3c | ||
|
|
5a0714ca1a | ||
|
|
bd5c790043 | ||
|
|
2ae3cf79e4 | ||
|
|
fb122ba097 | ||
|
|
0c104cd86c | ||
|
|
a687f4ad68 | ||
|
|
228f42cf04 | ||
|
|
6d4956b574 | ||
|
|
0c7b652a70 | ||
|
|
d35470a79e | ||
|
|
719d610be3 | ||
|
|
07ae64693e | ||
|
|
0ccc1271a6 | ||
|
|
26fa2b0b74 | ||
|
|
6f64c19c32 | ||
|
|
e3e0e12fef | ||
|
|
0312ba8ad7 | ||
|
|
2ad8e7f343 | ||
|
|
d6298d9f05 | ||
|
|
89be30c4b9 | ||
|
|
6bcfea1de4 | ||
|
|
e8c9554dd6 | ||
|
|
02272f7db0 | ||
|
|
5a73e79475 | ||
|
|
7f4ecd40ce | ||
|
|
7c950c3022 | ||
|
|
dbf019135a | ||
|
|
e504ee82e5 | ||
|
|
780a15fe4f | ||
|
|
abb249643f | ||
|
|
086eccaf4a | ||
|
|
871033501a | ||
|
|
ccd727488f | ||
|
|
aa59d0f082 | ||
|
|
5d12f53283 | ||
|
|
59c005875a | ||
|
|
06d22e843a | ||
|
|
4fa5f4e5a3 | ||
|
|
67ea825d4a | ||
|
|
a616e06f9d | ||
|
|
b7752928a4 | ||
|
|
ca096852a5 | ||
|
|
ea2c48bca5 | ||
|
|
a722dc4235 | ||
|
|
dbbf0ff5e4 | ||
|
|
a941519db5 | ||
|
|
d4ba014a8a | ||
|
|
d193a6aec4 | ||
|
|
1f0fdf3da7 | ||
|
|
b705240faa | ||
|
|
662b832274 | ||
|
|
aed7e6d289 | ||
|
|
f7a1201d02 | ||
|
|
4d5bdd25a8 | ||
|
|
4a90ce35f2 | ||
|
|
02f5eddd14 | ||
|
|
5ca4f1b181 | ||
|
|
ec7ef3a813 | ||
|
|
49ff6febe5 | ||
|
|
2d66a9212f | ||
|
|
44fb307da4 | ||
|
|
cfc2181a48 | ||
|
|
cf4a846312 | ||
|
|
633b357d7b | ||
|
|
b96d67a54e | ||
|
|
5b83931b01 | ||
|
|
f22b54de30 | ||
|
|
a3306bb26f | ||
|
|
0adacac269 | ||
|
|
7359ed2ba2 | ||
|
|
5a5f4e8161 | ||
|
|
b886cc1333 | ||
|
|
9299efd086 | ||
|
|
1502aa3b20 | ||
|
|
73e32ecdcb | ||
|
|
ac8776aea4 | ||
|
|
7b41c5b301 | ||
|
|
369839e012 | ||
|
|
8fde16422e | ||
|
|
f1462dbd3d | ||
|
|
5dad569d62 | ||
|
|
c424bb097d | ||
|
|
e4b1760b20 | ||
|
|
780e365a78 | ||
|
|
3d1523a060 | ||
|
|
ff403dfa2e | ||
|
|
89834baf01 | ||
|
|
b8699422c8 | ||
|
|
6bc772d640 | ||
|
|
0712f30a51 | ||
|
|
9116796d90 | ||
|
|
a95fdb903b | ||
|
|
2ca6421206 | ||
|
|
cd076cc069 | ||
|
|
46482bdae1 | ||
|
|
5189c897be | ||
|
|
2c7d25d472 | ||
|
|
0da370c42d | ||
|
|
6f036d9120 | ||
|
|
260bbd79fd | ||
|
|
37ad6a3a62 | ||
|
|
aa25007431 | ||
|
|
8b33ec1339 | ||
|
|
cede11ecea | ||
|
|
2b4088c5f7 | ||
|
|
d872484607 | ||
|
|
f3f2160d96 | ||
|
|
bcdb849b46 | ||
|
|
5846431b34 | ||
|
|
0217d9396a | ||
|
|
c99e233026 | ||
|
|
f670d930f3 | ||
|
|
0237d78f61 | ||
|
|
5665f127aa | ||
|
|
76386dad7d | ||
|
|
42072fdda4 | ||
|
|
fc80f828be | ||
|
|
d05a1e0260 | ||
|
|
b315882f58 | ||
|
|
2f2f907ffe | ||
|
|
10492e3b2f | ||
|
|
8e08ff2d39 | ||
|
|
e78a59a8a8 | ||
|
|
cbe47a9dcc | ||
|
|
a1056147d8 | ||
|
|
8692590600 | ||
|
|
57345113b5 | ||
|
|
52f02cb9eb | ||
|
|
5d4dcd7e4b | ||
|
|
7d1f4d8907 | ||
|
|
a76241c7ba | ||
|
|
bdc6678341 | ||
|
|
c99b7e927d | ||
|
|
1675a0d442 | ||
|
|
c0d2cd8962 | ||
|
|
146c9fd947 | ||
|
|
666e9897ea | ||
|
|
81d70bd811 | ||
|
|
f6f8bb7fd1 | ||
|
|
7c3aaf7b7c | ||
|
|
32ea28f783 | ||
|
|
17f365941b | ||
|
|
c2216843d8 | ||
|
|
339fb5099f | ||
|
|
cf56707b02 | ||
|
|
19f38aa6ed | ||
|
|
9f69e112d0 | ||
|
|
8eb4259be0 | ||
|
|
d3a1f43cbb | ||
|
|
18b06ff283 | ||
|
|
53addcf99a | ||
|
|
0fa4d75a47 | ||
|
|
2ef86c3339 | ||
|
|
d48c3a6d2f | ||
|
|
2260ede559 | ||
|
|
5690a44c38 | ||
|
|
e36a9fda1b | ||
|
|
10f195d334 | ||
|
|
54afc6ca8c | ||
|
|
2e67bd3b78 | ||
|
|
f27eb084c7 | ||
|
|
7629dfd54a | ||
|
|
f62fd18b72 | ||
|
|
c6b60ff6b4 | ||
|
|
e9655e6d86 | ||
|
|
3bca9b06f8 | ||
|
|
d97fdc3393 | ||
|
|
7dc72f98bf | ||
|
|
da00179066 | ||
|
|
89910031cd | ||
|
|
5676aeac80 | ||
|
|
b0b9055e2e | ||
|
|
c0aefed764 | ||
|
|
e2ec9ca5fb | ||
|
|
8e38f5c2c0 | ||
|
|
99b2858863 | ||
|
|
b43669e731 | ||
|
|
3bc9905715 | ||
|
|
c55aebd005 | ||
|
|
55c331f536 | ||
|
|
ce236284f4 | ||
|
|
c24cac68f6 | ||
|
|
db149ca6e1 | ||
|
|
0502f2a4a5 | ||
|
|
f13df7e605 | ||
|
|
36a6981329 | ||
|
|
7abcdea816 | ||
|
|
0509e54a95 | ||
|
|
b8893bcad7 | ||
|
|
c9356c1237 | ||
|
|
2d7b7c2f3f | ||
|
|
d0db1117f7 | ||
|
|
e287e76db5 | ||
|
|
8c28c4b5ac | ||
|
|
f048e943f8 | ||
|
|
12a84572e2 | ||
|
|
c8de1d3372 | ||
|
|
234e3f4ca5 | ||
|
|
7749fb1a0b | ||
|
|
f55d4e32c0 | ||
|
|
cfd98a33fe | ||
|
|
7bdf20fee5 | ||
|
|
e906fa3653 | ||
|
|
57cf7f6f0d | ||
|
|
d378e7e897 | ||
|
|
a8e666db34 | ||
|
|
7b46339a5d | ||
|
|
20aa6e429b | ||
|
|
7ba11a57a8 | ||
|
|
49de4f2200 | ||
|
|
5d01955133 | ||
|
|
7591f3fa29 | ||
|
|
89f8f9b45b | ||
|
|
59f5b38dca | ||
|
|
5b0e61033c | ||
|
|
096af00a72 | ||
|
|
dca2dc4600 | ||
|
|
96b482dac5 | ||
|
|
e05664f34f | ||
|
|
72cca5ccbf | ||
|
|
0b9be029ac | ||
|
|
91701473af | ||
|
|
ad6a9a7df7 | ||
|
|
32b6ded008 | ||
|
|
4f2d0a0322 | ||
|
|
793cfcb2c5 | ||
|
|
3a71bd01fb | ||
|
|
a1d99c1954 | ||
|
|
19a874b274 | ||
|
|
b95dd5c238 | ||
|
|
7c84af2370 | ||
|
|
db1c27d833 | ||
|
|
636cd84f4f | ||
|
|
f2d4fae813 | ||
|
|
986c9ab20a | ||
|
|
cd7e222b72 | ||
|
|
50b599b1a9 | ||
|
|
1d162edb59 | ||
|
|
7bdd4ddeab | ||
|
|
ae6e5a5599 | ||
|
|
1222184b68 | ||
|
|
18f779c6de | ||
|
|
138f67581c | ||
|
|
597d6ac513 | ||
|
|
3ab25c2e8c | ||
|
|
b11d97ba4e | ||
|
|
080c810131 | ||
|
|
56bc79d64e | ||
|
|
72d2c9d600 | ||
|
|
0374c32236 | ||
|
|
d73cd4b515 | ||
|
|
54e3e3f051 | ||
|
|
abf218fc21 | ||
|
|
dcf90b6159 | ||
|
|
1cf91c78f8 | ||
|
|
968abd26e8 | ||
|
|
aa05f7a2d2 | ||
|
|
181c23b07c | ||
|
|
955cde3ed9 | ||
|
|
477a3c7eb2 | ||
|
|
f4b66b980b | ||
|
|
281de63e0d | ||
|
|
c19a700662 | ||
|
|
fc011ba1d9 | ||
|
|
b941f590e0 | ||
|
|
8f4db78ff2 | ||
|
|
4b4dc2e298 | ||
|
|
2de19547ca | ||
|
|
5a058491b0 | ||
|
|
6743d99d9b | ||
|
|
35a5ec78c3 | ||
|
|
3440c3e77a | ||
|
|
dd17f06362 | ||
|
|
8a15cb3a34 | ||
|
|
4a548ac282 | ||
|
|
d22353b13d | ||
|
|
c18046c25d | ||
|
|
4a12d4d156 | ||
|
|
20044427b4 | ||
|
|
073dedd483 | ||
|
|
06c25c913c | ||
|
|
08d06cf465 | ||
|
|
1e9eb843c0 | ||
|
|
78a5dae2a0 | ||
|
|
19443a5b34 | ||
|
|
74acc90702 | ||
|
|
349f580371 | ||
|
|
f019d33a03 | ||
|
|
c7af25ac38 | ||
|
|
b52bd59cea | ||
|
|
332d32c319 | ||
|
|
2f824ba1a8 | ||
|
|
a6b09acd5e | ||
|
|
d4779c8c8f | ||
|
|
ba01c4bbe8 | ||
|
|
ddc1d81665 | ||
|
|
790aeb3c46 | ||
|
|
6ed5be10b1 | ||
|
|
a7b8470d9e | ||
|
|
2a05cc382f | ||
|
|
1e10a6ce1b | ||
|
|
7645ef55c2 | ||
|
|
6ce200b60d | ||
|
|
d782e28906 | ||
|
|
da3bd31fb8 | ||
|
|
aa3ed40430 | ||
|
|
ad7e564f14 | ||
|
|
f23ee2dac5 | ||
|
|
1962f74439 | ||
|
|
0064d060ea | ||
|
|
e47e6b1958 | ||
|
|
4c04415e80 | ||
|
|
3654e75b8c | ||
|
|
66fa73aea4 | ||
|
|
df87d03f32 | ||
|
|
3fbe851a0b | ||
|
|
d1b2e63950 | ||
|
|
34fd8cf751 | ||
|
|
f1fe90fce0 | ||
|
|
2ba6fa0dda | ||
|
|
f2928e3d7d | ||
|
|
895ab9c5d8 | ||
|
|
fb07c68132 | ||
|
|
68e7d45f63 | ||
|
|
49e302e1bc | ||
|
|
b33ca786ae | ||
|
|
dc77d8edda | ||
|
|
c339a183b9 | ||
|
|
f263795a99 | ||
|
|
e9e771e57b | ||
|
|
fbb9d7c6b4 | ||
|
|
10abd7b0ae | ||
|
|
3de36901b8 | ||
|
|
5b4967acb9 | ||
|
|
0a007b1e6e | ||
|
|
4ad68b7dfa | ||
|
|
73aef1b9a4 | ||
|
|
dcfea20973 | ||
|
|
9b6766d3b2 | ||
|
|
b8bc8e2c47 | ||
|
|
039e3aa34c | ||
|
|
551ff109c9 | ||
|
|
664451d0c6 | ||
|
|
4031057bc0 | ||
|
|
fcf9b782c1 | ||
|
|
d693d382b9 | ||
|
|
0a1b6c7793 | ||
|
|
5acba2bddf | ||
|
|
883b16fad1 | ||
|
|
ef48b3e751 | ||
|
|
3c956e7e98 | ||
|
|
519ea271a9 | ||
|
|
09d5160404 | ||
|
|
97dcf03334 | ||
|
|
896a804a72 | ||
|
|
656bb5043d | ||
|
|
e953becbae | ||
|
|
6c9901b919 | ||
|
|
ff45c94106 | ||
|
|
a8a3fbeef4 | ||
|
|
dae8092ecd | ||
|
|
70110208fc | ||
|
|
217ca98933 | ||
|
|
c2945c532e | ||
|
|
ea750576b3 | ||
|
|
82538ba4fc | ||
|
|
2b2f37a8c9 | ||
|
|
4db2ec60e0 | ||
|
|
7d88d35556 | ||
|
|
3c3e91ff48 | ||
|
|
039e8d6e17 | ||
|
|
50bf79ab18 | ||
|
|
467c6762fa | ||
|
|
740f4e403f | ||
|
|
5664d51695 | ||
|
|
b195a61498 | ||
|
|
94e6816bf6 | ||
|
|
ebf97f710f | ||
|
|
714b54ed06 | ||
|
|
620c5f515e | ||
|
|
c06fd12b07 | ||
|
|
2c206bba64 | ||
|
|
04953b5645 | ||
|
|
1732ce63f3 | ||
|
|
1e212c6da2 | ||
|
|
7d8fc54351 | ||
|
|
dd44a1e517 | ||
|
|
9f26757e8a | ||
|
|
a9c8c8384d | ||
|
|
a826b0e0fb | ||
|
|
4aaec0e379 | ||
|
|
69019d5215 | ||
|
|
96411b17e9 | ||
|
|
5a093b58d8 | ||
|
|
470b3e0973 | ||
|
|
dc251c216c | ||
|
|
ae9ef61f80 | ||
|
|
d9ca7b7277 | ||
|
|
0c99248deb | ||
|
|
1aae84a4d0 | ||
|
|
528da3f08e | ||
|
|
9c507f7f62 | ||
|
|
07da2fdda3 | ||
|
|
ca3366544e | ||
|
|
ccee7b483c | ||
|
|
5903133e3b | ||
|
|
5bf520b6ed | ||
|
|
a47da92d81 | ||
|
|
63f84ae7b1 | ||
|
|
4d6bc55723 | ||
|
|
9bb4df4cc3 | ||
|
|
c47a5379ae | ||
|
|
cde9c4a2bc | ||
|
|
5a560b42ef | ||
|
|
50874c9cf7 | ||
|
|
6f984aa591 | ||
|
|
274162afcd | ||
|
|
6bd23d897f | ||
|
|
73f29ebf69 | ||
|
|
cabcb9c6d0 | ||
|
|
116f7ed613 | ||
|
|
6ef0eb73d0 | ||
|
|
7f4feb0cfc | ||
|
|
626f7357bb | ||
|
|
690c9203c8 | ||
|
|
1209f3b39a | ||
|
|
a4524b3c2c | ||
|
|
a3cbdadb39 | ||
|
|
9e3c5fd984 | ||
|
|
7d80ac37a6 | ||
|
|
f74b9ba7ab | ||
|
|
3ac240dc1c | ||
|
|
d233b3f24f | ||
|
|
19fff681d2 | ||
|
|
bc7c3bb9b3 | ||
|
|
57be7f2905 | ||
|
|
1c0da454db | ||
|
|
b541f7b944 | ||
|
|
6e84326583 | ||
|
|
ca14496e4e | ||
|
|
480d65fc1f | ||
|
|
6bddb63b45 | ||
|
|
c5142aeba5 | ||
|
|
38d9f10672 | ||
|
|
937394af7a | ||
|
|
fe10955eb9 | ||
|
|
ccda71ff8e | ||
|
|
cd75224cdd | ||
|
|
1c2089b8a3 | ||
|
|
3ead4d4587 | ||
|
|
f2b71bc280 | ||
|
|
f027d71136 | ||
|
|
fa41d6df04 | ||
|
|
d2bb65bf04 | ||
|
|
b5be1b11d1 | ||
|
|
9fb049991f | ||
|
|
fba847dd28 | ||
|
|
b33883b334 | ||
|
|
f74a6dffca | ||
|
|
7390e20218 | ||
|
|
9646dc439e | ||
|
|
554c63b9c7 | ||
|
|
24d8640e9b | ||
|
|
ea151d069c | ||
|
|
f140d2f37a | ||
|
|
4e163c4bda | ||
|
|
ddcf8b892b | ||
|
|
49138eb03a | ||
|
|
71b63bd33b | ||
|
|
88348f59c2 | ||
|
|
7eb5643204 | ||
|
|
565cb6d79e | ||
|
|
c0d715c78a | ||
|
|
a3d0355ddd | ||
|
|
bc4e06568d | ||
|
|
8acb9f4056 | ||
|
|
9cbbd581ee | ||
|
|
fdc9467218 | ||
|
|
84ac3df580 | ||
|
|
7f459df9e9 | ||
|
|
3625f3293a | ||
|
|
0a2308592f | ||
|
|
8ef3f18da7 | ||
|
|
e126427809 | ||
|
|
7b39828980 | ||
|
|
d03de52735 | ||
|
|
cabe90b2dd | ||
|
|
13b78bdc20 | ||
|
|
6f0e1c79ac | ||
|
|
b66daad3d3 | ||
|
|
9c5523252d | ||
|
|
bc8bcf7a1a | ||
|
|
85d655d3e2 | ||
|
|
ac419e01d3 | ||
|
|
5d4467a6c0 | ||
|
|
81da7f3667 | ||
|
|
9734196eb9 | ||
|
|
7e0f9b9b8e | ||
|
|
bb25132865 | ||
|
|
28bcff99f6 | ||
|
|
246cb36836 | ||
|
|
9a0c0f6d21 | ||
|
|
a9dd8eb9e7 | ||
|
|
9026c9d6f1 | ||
|
|
d5f7430723 | ||
|
|
5a53249fbb | ||
|
|
d2848cf569 | ||
|
|
71f39f55f2 | ||
|
|
490c817fc1 | ||
|
|
2e1a777811 | ||
|
|
48357d1cc9 | ||
|
|
846df21764 | ||
|
|
f78b8f9267 | ||
|
|
798d9ee876 | ||
|
|
1eea81e9dd | ||
|
|
4fcdfd41fa | ||
|
|
36a5f17af2 | ||
|
|
8032684ad0 | ||
|
|
f7d3d4a010 | ||
|
|
9975e0b3f3 | ||
|
|
ea484a7787 | ||
|
|
c2e8a67330 | ||
|
|
8f3e4a2dee | ||
|
|
07768a43c8 | ||
|
|
01c10e320c | ||
|
|
f16b2257c6 | ||
|
|
e005fe7ce1 | ||
|
|
c682e69ee7 | ||
|
|
49421f50ac | ||
|
|
529dd490b7 | ||
|
|
36329e596e | ||
|
|
fb75e2ef02 | ||
|
|
352171e339 | ||
|
|
592901b143 | ||
|
|
769b4819b2 | ||
|
|
77fa2bcc39 | ||
|
|
1129001bc6 | ||
|
|
8dd765ee89 | ||
|
|
479648e7c1 | ||
|
|
45cd19d1e3 | ||
|
|
f8718e0b7b | ||
|
|
dcc45631da | ||
|
|
c6d3a5bedc | ||
|
|
7cc8539298 | ||
|
|
900e8202e6 | ||
|
|
eb6ac7d1d1 | ||
|
|
178f917a49 | ||
|
|
1a8293d9ef | ||
|
|
ecdc00dcb7 | ||
|
|
147e04ecd2 | ||
|
|
49e48725a5 | ||
|
|
b3af744041 | ||
|
|
58a6a95d90 | ||
|
|
1aa9461370 | ||
|
|
1f78b9d4bc | ||
|
|
6f974fe285 | ||
|
|
f4f3c8798e | ||
|
|
ce1614f4e7 | ||
|
|
91494584c2 | ||
|
|
a85ebb49b2 | ||
|
|
ae273f8320 | ||
|
|
ef62e31b61 | ||
|
|
0c2c5d5344 | ||
|
|
11e93eac3d | ||
|
|
dbe17debb4 | ||
|
|
6c12337317 | ||
|
|
b2aa73b31e | ||
|
|
38b1fc7aa6 | ||
|
|
f4afcb4d50 | ||
|
|
4b019fe38b | ||
|
|
191401f32b | ||
|
|
62b68c6a21 | ||
|
|
15a22f0bfc | ||
|
|
926c03986c | ||
|
|
d8a00f4314 | ||
|
|
5862b832d9 | ||
|
|
67fa4a0fc7 | ||
|
|
90cf7a3bf5 | ||
|
|
0847040017 | ||
|
|
69b577048e | ||
|
|
3fbd2f93c8 | ||
|
|
8f0e36a8e4 | ||
|
|
7583698ee5 | ||
|
|
b561e79a6c | ||
|
|
5850ad06b1 | ||
|
|
e597f04b0d | ||
|
|
7b715925cf | ||
|
|
d3701837e3 | ||
|
|
7af10aca9e | ||
|
|
b54e99642b | ||
|
|
b1ad0668cc | ||
|
|
6583d0f69b | ||
|
|
cee6bbf134 | ||
|
|
43e49bf14a | ||
|
|
371b58a807 | ||
|
|
7812a1bb51 | ||
|
|
538e045e4c | ||
|
|
91fe1493a7 | ||
|
|
4650a2ea52 | ||
|
|
7cd51a7747 | ||
|
|
b55545b959 | ||
|
|
2685256c93 | ||
|
|
3819de4e74 | ||
|
|
73fee4eb6b | ||
|
|
609c193b88 | ||
|
|
03a42976b1 | ||
|
|
6db0efdfbc |
@@ -1,12 +0,0 @@
|
||||
---
|
||||
exclude_patterns:
|
||||
- public/lib/
|
||||
- public/js/lib/
|
||||
- public/fonts/
|
||||
- public/css/jquery-ui/
|
||||
- public/css/bootstrap-multiselect.css
|
||||
- public/css/bootstrap-sortable.css
|
||||
- public/css/bootstrap-tagsinput.css
|
||||
- public/css/daterangepicker.css
|
||||
- public/css/google-fonts.css
|
||||
- .sandstorm/
|
||||
@@ -1,73 +1,3 @@
|
||||
# This is the main Apache server configuration file. It contains the
|
||||
# configuration directives that give the server its instructions.
|
||||
# See http://httpd.apache.org/docs/2.4/ for detailed information about
|
||||
# the directives and /usr/share/doc/apache2/README.Debian about Debian specific
|
||||
# hints.
|
||||
#
|
||||
#
|
||||
# Summary of how the Apache 2 configuration works in Debian:
|
||||
# The Apache 2 web server configuration in Debian is quite different to
|
||||
# upstream's suggested way to configure the web server. This is because Debian's
|
||||
# default Apache2 installation attempts to make adding and removing modules,
|
||||
# virtual hosts, and extra configuration directives as flexible as possible, in
|
||||
# order to make automating the changes and administering the server as easy as
|
||||
# possible.
|
||||
|
||||
# It is split into several files forming the configuration hierarchy outlined
|
||||
# below, all located in the /etc/apache2/ directory:
|
||||
#
|
||||
# /etc/apache2/
|
||||
# |-- apache2.conf
|
||||
# | `-- ports.conf
|
||||
# |-- mods-enabled
|
||||
# | |-- *.load
|
||||
# | `-- *.conf
|
||||
# |-- conf-enabled
|
||||
# | `-- *.conf
|
||||
# `-- sites-enabled
|
||||
# `-- *.conf
|
||||
#
|
||||
#
|
||||
# * apache2.conf is the main configuration file (this file). It puts the pieces
|
||||
# together by including all remaining configuration files when starting up the
|
||||
# web server.
|
||||
#
|
||||
# * ports.conf is always included from the main configuration file. It is
|
||||
# supposed to determine listening ports for incoming connections which can be
|
||||
# customized anytime.
|
||||
#
|
||||
# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/
|
||||
# directories contain particular configuration snippets which manage modules,
|
||||
# global configuration fragments, or virtual host configurations,
|
||||
# respectively.
|
||||
#
|
||||
# They are activated by symlinking available configuration files from their
|
||||
# respective *-available/ counterparts. These should be managed by using our
|
||||
# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See
|
||||
# their respective man pages for detailed information.
|
||||
#
|
||||
# * The binary is called apache2. Due to the use of environment variables, in
|
||||
# the default configuration, apache2 needs to be started/stopped with
|
||||
# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not
|
||||
# work with the default configuration.
|
||||
|
||||
|
||||
# Global configuration
|
||||
#
|
||||
|
||||
#
|
||||
# ServerRoot: The top of the directory tree under which the server's
|
||||
# configuration, error, and log files are kept.
|
||||
#
|
||||
# NOTE! If you intend to place this on an NFS (or otherwise network)
|
||||
# mounted filesystem then please read the Mutex documentation (available
|
||||
# at <URL:http://httpd.apache.org/docs/2.4/mod/core.html#mutex>);
|
||||
# you will save yourself a lot of trouble.
|
||||
#
|
||||
# Do NOT add a slash at the end of the directory path.
|
||||
#
|
||||
#ServerRoot "/etc/apache2"
|
||||
|
||||
#
|
||||
# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
|
||||
#
|
||||
|
||||
20
.deploy/docker/build-amd64.sh
Executable file
20
.deploy/docker/build-amd64.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# build image
|
||||
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
|
||||
|
||||
if [ "$TRAVIS_BRANCH" == "develop" ]; then
|
||||
echo "Build develop amd64"
|
||||
docker build -t jc5x/firefly-iii:develop-amd64 -f Dockerfile.amd64 .
|
||||
docker tag jc5x/firefly-iii:develop-amd64 jc5x/firefly-iii:develop-$VERSION-amd64
|
||||
docker push jc5x/firefly-iii:develop-amd64
|
||||
docker push jc5x/firefly-iii:develop-$VERSION-amd64
|
||||
fi
|
||||
|
||||
if [ "$TRAVIS_BRANCH" == "master" ]; then
|
||||
echo "Build master amd64"
|
||||
docker build -t jc5x/firefly-iii:latest-amd64 -f Dockerfile.amd64 .
|
||||
docker tag jc5x/firefly-iii:latest-amd64 jc5x/firefly-iii:release-$VERSION-amd64
|
||||
docker push jc5x/firefly-iii:latest-amd64
|
||||
docker push jc5x/firefly-iii:release-$VERSION-amd64
|
||||
fi
|
||||
29
.deploy/docker/build-arm.sh
Executable file
29
.deploy/docker/build-arm.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
docker run --rm --privileged multiarch/qemu-user-static:register --reset
|
||||
|
||||
# get qemu-arm-static binary
|
||||
mkdir tmp
|
||||
pushd tmp && \
|
||||
curl -L -o qemu-arm-static.tar.gz https://github.com/multiarch/qemu-user-static/releases/download/v2.6.0/qemu-arm-static.tar.gz && \
|
||||
tar xzf qemu-arm-static.tar.gz && \
|
||||
popd
|
||||
|
||||
# build image
|
||||
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
|
||||
|
||||
if [ "$TRAVIS_BRANCH" == "develop" ]; then
|
||||
echo "Build develop arm"
|
||||
docker build --tag jc5x/firefly-iii:develop-arm --file Dockerfile.arm .
|
||||
docker tag jc5x/firefly-iii:develop-arm jc5x/firefly-iii:develop-$VERSION-arm
|
||||
docker push jc5x/firefly-iii:develop-arm
|
||||
docker push jc5x/firefly-iii:develop-$VERSION-arm
|
||||
fi
|
||||
|
||||
if [ "$TRAVIS_BRANCH" == "master" ]; then
|
||||
echo "Build master arm"
|
||||
docker build --tag jc5x/firefly-iii:latest-arm --file Dockerfile.arm .
|
||||
docker tag jc5x/firefly-iii:latest-arm jc5x/firefly-iii:release-$VERSION-arm
|
||||
docker push jc5x/firefly-iii:latest-arm
|
||||
docker push jc5x/firefly-iii:release-$VERSION-arm
|
||||
fi
|
||||
3314
.deploy/docker/cacert.pem
Normal file
3314
.deploy/docker/cacert.pem
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,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,12 +1,98 @@
|
||||
#!/bin/bash
|
||||
|
||||
# make sure we own the volumes:
|
||||
chown -R www-data:www-data $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload
|
||||
chmod -R 775 $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload
|
||||
echo "Now in entrypoint.sh for Firefly III"
|
||||
|
||||
cat .env.docker | envsubst > .env && cat .env
|
||||
# make sure the correct directories exists (suggested by @chrif):
|
||||
echo "Making directories..."
|
||||
mkdir -p $FIREFLY_PATH/storage/app/public
|
||||
mkdir -p $FIREFLY_PATH/storage/build
|
||||
mkdir -p $FIREFLY_PATH/storage/database
|
||||
mkdir -p $FIREFLY_PATH/storage/debugbar
|
||||
mkdir -p $FIREFLY_PATH/storage/export
|
||||
mkdir -p $FIREFLY_PATH/storage/framework/cache/data
|
||||
mkdir -p $FIREFLY_PATH/storage/framework/sessions
|
||||
mkdir -p $FIREFLY_PATH/storage/framework/testing
|
||||
mkdir -p $FIREFLY_PATH/storage/framework/views/v1
|
||||
mkdir -p $FIREFLY_PATH/storage/framework/views/v2
|
||||
mkdir -p $FIREFLY_PATH/storage/logs
|
||||
mkdir -p $FIREFLY_PATH/storage/upload
|
||||
|
||||
|
||||
echo "Touch DB file (if SQLlite)..."
|
||||
if [[ $DB_CONNECTION == "sqlite" ]]
|
||||
then
|
||||
touch $FIREFLY_PATH/storage/database/database.sqlite
|
||||
echo "Touched!"
|
||||
fi
|
||||
|
||||
# make sure we own the volumes:
|
||||
echo "Run chown on ${FIREFLY_PATH}/storage..."
|
||||
chown -R www-data:www-data -R $FIREFLY_PATH/storage
|
||||
echo "Run chmod on ${FIREFLY_PATH}/storage..."
|
||||
chmod -R 775 $FIREFLY_PATH/storage
|
||||
|
||||
# remove any lingering files that may break upgrades:
|
||||
echo "Remove log file..."
|
||||
rm -f $FIREFLY_PATH/storage/logs/laravel.log
|
||||
|
||||
echo "Dump auto load..."
|
||||
composer dump-autoload
|
||||
php artisan optimize
|
||||
echo "Discover packages..."
|
||||
php artisan package:discover
|
||||
|
||||
echo "Run various artisan commands..."
|
||||
if [[ -z "$DB_PORT" ]]; then
|
||||
if [[ $DB_CONNECTION == "pgsql" ]]; then
|
||||
DB_PORT=5432
|
||||
elif [[ $DB_CONNECTION == "mysql" ]]; then
|
||||
DB_PORT=3306
|
||||
fi
|
||||
fi
|
||||
if [[ ! -z "$DB_PORT" ]]; then
|
||||
$FIREFLY_PATH/.deploy/docker/wait-for-it.sh "${DB_HOST}:${DB_PORT}" -- echo "db is up. Time to execute artisan commands"
|
||||
fi
|
||||
#env $(grep -v "^\#" .env | xargs)
|
||||
php artisan cache:clear
|
||||
php artisan migrate --seed
|
||||
php artisan firefly-iii:decrypt-all
|
||||
|
||||
# there are 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
|
||||
|
||||
echo "Go!"
|
||||
exec apache2-foreground
|
||||
|
||||
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
|
||||
26
.deploy/docker/vhost.conf
Normal file
26
.deploy/docker/vhost.conf
Normal file
@@ -0,0 +1,26 @@
|
||||
server {
|
||||
listen 80 default_server;
|
||||
|
||||
server_name _ *.vm docker;
|
||||
|
||||
root "/app/public";
|
||||
index index.php;
|
||||
|
||||
include /opt/docker/etc/nginx/vhost.common.d/*.conf;
|
||||
}
|
||||
|
||||
##############
|
||||
# SSL
|
||||
##############
|
||||
|
||||
server {
|
||||
listen 443 default_server;
|
||||
|
||||
server_name _ *.vm docker;
|
||||
|
||||
root "/app/public";
|
||||
index index.php;
|
||||
|
||||
include /opt/docker/etc/nginx/vhost.common.d/*.conf;
|
||||
include /opt/docker/etc/nginx/vhost.ssl.conf;
|
||||
}
|
||||
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
|
||||
183
.deploy/heroku/.env.heroku
Normal file
183
.deploy/heroku/.env.heroku
Normal file
@@ -0,0 +1,183 @@
|
||||
# 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=heroku
|
||||
|
||||
# Set to true if you want to see debug information in error screens.
|
||||
APP_DEBUG=false
|
||||
|
||||
# This should be your email address
|
||||
SITE_OWNER=heroku@example.com
|
||||
|
||||
# The encryption key for your database and sessions. Keep this very secure.
|
||||
# If you generate a new one all existing data must be considered LOST.
|
||||
# Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it
|
||||
APP_KEY=7ahyYVPVsmxjdhsweWCauGeJfwc92NP2
|
||||
|
||||
# Change this value to your preferred time zone.
|
||||
# Example: Europe/Amsterdam
|
||||
TZ=UTC
|
||||
|
||||
# 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=stdout
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=debug
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# If you use SQLite, set connection to `sqlite` and remove the database, username and password settings.
|
||||
DB_CONNECTION=pgsql
|
||||
|
||||
|
||||
|
||||
# PostgreSQL supports SSL. You can configure it here.
|
||||
PGSQL_SSL_MODE=prefer
|
||||
PGSQL_SSL_ROOT_CERT=null
|
||||
PGSQL_SSL_CERT=null
|
||||
PGSQL_SSL_KEY=null
|
||||
PGSQL_SSL_CRL_FILE=null
|
||||
|
||||
|
||||
# If you're looking for performance improvements, you could install memcached.
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
# You can configure another file storage backend if you cannot use the local storage option.
|
||||
# To set this up, fill in the following variables. The upload path is used to store uploaded
|
||||
# files and the export path is to store exported data (before download).
|
||||
SFTP_HOST=
|
||||
SFTP_PORT=
|
||||
SFTP_UPLOAD_PATH=
|
||||
SFTP_EXPORT_PATH=
|
||||
|
||||
# SFTP uses either the username/password combination or the private key to authenticate.
|
||||
SFTP_USERNAME=
|
||||
SFTP_PASSWORD=
|
||||
SFTP_PRIV_KEY=
|
||||
|
||||
# Cookie settings. Should not be necessary to change these.
|
||||
COOKIE_PATH="/"
|
||||
COOKIE_DOMAIN=
|
||||
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=true
|
||||
|
||||
# These messages contain (sensitive) transaction information:
|
||||
SEND_REPORT_JOURNALS=true
|
||||
|
||||
# Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places.
|
||||
MAPBOX_API_KEY=
|
||||
|
||||
# Firefly III currently supports two provider for live Currency Exchange Rates:
|
||||
# "fixer" is the default (for backward compatibility), and "ratesapi" is the new one.
|
||||
# RatesApi.IO (see https://ratesapi.io) is a FREE and OPEN SOURCE live currency exchange rates,
|
||||
# built compatible with Fixer.IO, based on data published by European Central Bank, and don't require API key.
|
||||
CER_PROVIDER=fixer
|
||||
# If you have select "fixer" as default currency exchange rates,
|
||||
# set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this WILL ONLY WORK FOR PAID fixer.io accounts because they severely limited
|
||||
# the free API up to the point where you might as well offer nothing.
|
||||
FIXER_API_KEY=
|
||||
|
||||
# If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here.
|
||||
ANALYTICS_ID=
|
||||
|
||||
# Most parts of the database are encrypted by default, but you can turn this off if you want to.
|
||||
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
||||
USE_ENCRYPTION=true
|
||||
|
||||
# Firefly III has two options for user authentication. "eloquent" is the default,
|
||||
# and "ldap" for LDAP servers.
|
||||
# For full instructions on these settings please visit:
|
||||
# https://firefly-iii.readthedocs.io/en/latest/installation/authentication.html
|
||||
LOGIN_PROVIDER=eloquent
|
||||
|
||||
# LDAP connection configuration
|
||||
# OpenLDAP, FreeIPA or ActiveDirectory
|
||||
ADLDAP_CONNECTION_SCHEME=OpenLDAP
|
||||
ADLDAP_AUTO_CONNECT=true
|
||||
|
||||
# LDAP connection settings
|
||||
ADLDAP_CONTROLLERS=
|
||||
ADLDAP_PORT=389
|
||||
ADLDAP_TIMEOUT=5
|
||||
ADLDAP_BASEDN=""
|
||||
ADLDAP_FOLLOW_REFFERALS=false
|
||||
ADLDAP_USE_SSL=false
|
||||
ADLDAP_USE_TLS=false
|
||||
|
||||
ADLDAP_ADMIN_USERNAME=
|
||||
ADLDAP_ADMIN_PASSWORD=
|
||||
|
||||
ADLDAP_ACCOUNT_PREFIX=
|
||||
ADLDAP_ACCOUNT_SUFFIX=
|
||||
|
||||
# LDAP authentication settings.
|
||||
ADLDAP_PASSWORD_SYNC=false
|
||||
ADLDAP_LOGIN_FALLBACK=false
|
||||
|
||||
ADLDAP_DISCOVER_FIELD=distinguishedname
|
||||
ADLDAP_AUTH_FIELD=distinguishedname
|
||||
|
||||
# Will allow SSO if your server provides an AUTH_USER field.
|
||||
WINDOWS_SSO_DISCOVER=samaccountname
|
||||
WINDOWS_SSO_KEY=AUTH_USER
|
||||
|
||||
# field to sync as local username.
|
||||
ADLDAP_SYNC_FIELD=userprincipalname
|
||||
|
||||
# You can disable the X-Frame-Options header if it interfears with tools like
|
||||
# Organizr. This is at your own risk.
|
||||
DISABLE_FRAME_HEADER=false
|
||||
|
||||
# Leave the following configuration vars as is.
|
||||
# Unless you like to tinker and know what you're doing.
|
||||
APP_NAME=FireflyIII
|
||||
ADLDAP_CONNECTION=default
|
||||
BROADCAST_DRIVER=log
|
||||
QUEUE_DRIVER=sync
|
||||
REDIS_HOST=127.0.0.1
|
||||
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=false
|
||||
IS_SANDSTORM=false
|
||||
IS_HEROKU=true
|
||||
BUNQ_USE_SANDBOX=false
|
||||
FFIII_LAYOUT=v1
|
||||
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
|
||||
name: firefly-local
|
||||
env:
|
||||
- name: FF_APP_ENV
|
||||
- name: APP_ENV
|
||||
value: "local"
|
||||
- name: FF_APP_KEY
|
||||
- name: APP_KEY
|
||||
value: "S0m3R@nd0mString0f32Ch@rsEx@ct1y"
|
||||
- name: FF_DB_HOST
|
||||
- name: DB_HOST
|
||||
value: "172.17.0.9"
|
||||
- name: FF_DB_NAME
|
||||
- name: DB_NAME
|
||||
value: "firefly_db"
|
||||
- name: FF_DB_USER
|
||||
- name: DB_USER
|
||||
value: "firefly_db"
|
||||
- name: FF_DB_PASSWORD
|
||||
- name: DB_PASSWORD
|
||||
value: "password"
|
||||
volumeMounts:
|
||||
- mountPath: "/var/www/firefly-iii/storage/export"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
APP_ENV=local
|
||||
|
||||
# Set to true if you want to see debug information in error screens.
|
||||
APP_DEBUG=false
|
||||
APP_DEBUG=true
|
||||
|
||||
# This should be your email address
|
||||
SITE_OWNER=sandstorm@example.com
|
||||
@@ -17,12 +17,24 @@ APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
# Example: Europe/Amsterdam
|
||||
TZ=UTC
|
||||
|
||||
# APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy.
|
||||
# This variable must match your installation's external address but keep in mind that
|
||||
# it's only used on the command line as a fallback value.
|
||||
APP_URL=http://localhost
|
||||
|
||||
# TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy.
|
||||
TRUSTED_PROXIES=
|
||||
|
||||
# The log channel defines where your log entries go to.
|
||||
LOG_CHANNEL=syslog
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# Several other options exist. You can use 'single' for one big fat error log (not recommended).
|
||||
# Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself.
|
||||
LOG_CHANNEL=stdout
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=debug
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# If you use SQLite, set connection to `sqlite` and remove the database, username and password settings.
|
||||
@@ -33,28 +45,31 @@ DB_DATABASE=firefly
|
||||
DB_USERNAME=firefly
|
||||
DB_PASSWORD=firefly
|
||||
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# Several other options exist. You can use 'single' for one big fat error log (not recommended).
|
||||
# Also available are 'syslog' and 'errorlog' which will log to the system itself.
|
||||
APP_LOG=syslog
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=info
|
||||
|
||||
# If you're looking for performance improvements, you could install memcached.
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
# You can configure another file storage backend if you cannot use the local storage option.
|
||||
# To set this up, fill in the following variables. The upload path is used to store uploaded
|
||||
# files and the export path is to store exported data (before download).
|
||||
SFTP_HOST=
|
||||
SFTP_PORT=
|
||||
SFTP_UPLOAD_PATH=
|
||||
SFTP_EXPORT_PATH=
|
||||
|
||||
# SFTP uses either the username/password combination or the private key to authenticate.
|
||||
SFTP_USERNAME=
|
||||
SFTP_PASSWORD=
|
||||
SFTP_PRIV_KEY=
|
||||
|
||||
# Cookie settings. Should not be necessary to change these.
|
||||
COOKIE_PATH="/"
|
||||
COOKIE_DOMAIN=
|
||||
COOKIE_SECURE=false
|
||||
|
||||
# If you want Firefly III to mail you, update these settings
|
||||
MAIL_DRIVER=smtp
|
||||
# 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
|
||||
@@ -62,15 +77,30 @@ 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=true
|
||||
|
||||
# These messages contain (sensitive) transaction information:
|
||||
SEND_REPORT_JOURNALS=true
|
||||
|
||||
# Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places.
|
||||
MAPBOX_API_KEY=
|
||||
|
||||
# Set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this will only work for paid fixer.io accounts because they severly limited
|
||||
# Firefly III currently supports two provider for live Currency Exchange Rates:
|
||||
# "fixer" is the default (for backward compatibility), and "ratesapi" is the new one.
|
||||
# RatesApi.IO (see https://ratesapi.io) is a FREE and OPEN SOURCE live currency exchange rates,
|
||||
# built compatible with Fixer.IO, based on data published by European Central Bank, and don't require API key.
|
||||
CER_PROVIDER=fixer
|
||||
# If you have select "fixer" as default currency exchange rates,
|
||||
# set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this WILL ONLY WORK FOR PAID fixer.io accounts because they severely limited
|
||||
# the free API up to the point where you might as well offer nothing.
|
||||
FIXER_API_KEY=
|
||||
|
||||
@@ -81,9 +111,54 @@ ANALYTICS_ID=
|
||||
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
||||
USE_ENCRYPTION=true
|
||||
|
||||
# Firefly III has two options for user authentication. "eloquent" is the default,
|
||||
# and "ldap" for LDAP servers.
|
||||
# For full instructions on these settings please visit:
|
||||
# https://firefly-iii.readthedocs.io/en/latest/installation/authentication.html
|
||||
LOGIN_PROVIDER=eloquent
|
||||
|
||||
# LDAP connection configuration
|
||||
# or FreeIPA or ActiveDirectory
|
||||
ADLDAP_CONNECTION_SCHEME=OpenLDAP
|
||||
ADLDAP_AUTO_CONNECT=true
|
||||
|
||||
# LDAP connection settings
|
||||
ADLDAP_CONTROLLERS=
|
||||
ADLDAP_PORT=389
|
||||
ADLDAP_TIMEOUT=5
|
||||
ADLDAP_BASEDN=""
|
||||
ADLDAP_FOLLOW_REFFERALS=false
|
||||
ADLDAP_USE_SSL=false
|
||||
ADLDAP_USE_TLS=false
|
||||
|
||||
ADLDAP_ADMIN_USERNAME=
|
||||
ADLDAP_ADMIN_PASSWORD=
|
||||
|
||||
ADLDAP_ACCOUNT_PREFIX=
|
||||
ADLDAP_ACCOUNT_SUFFIX=
|
||||
|
||||
# LDAP authentication settings.
|
||||
ADLDAP_PASSWORD_SYNC=false
|
||||
ADLDAP_LOGIN_FALLBACK=false
|
||||
|
||||
ADLDAP_DISCOVER_FIELD=distinguishedname
|
||||
ADLDAP_AUTH_FIELD=distinguishedname
|
||||
|
||||
# Will allow SSO if your server provides an AUTH_USER field.
|
||||
WINDOWS_SSO_DISCOVER=samaccountname
|
||||
WINDOWS_SSO_KEY=AUTH_USER
|
||||
|
||||
# field to sync as local username.
|
||||
ADLDAP_SYNC_FIELD=userprincipalname
|
||||
|
||||
# You can disable the X-Frame-Options header if it interfears with tools like
|
||||
# Organizr. This is at your own risk.
|
||||
DISABLE_FRAME_HEADER=true
|
||||
|
||||
# Leave the following configuration vars as is.
|
||||
# Unless you like to tinker and know what you're doing.
|
||||
APP_NAME=FireflyIII
|
||||
ADLDAP_CONNECTION=default
|
||||
BROADCAST_DRIVER=log
|
||||
QUEUE_DRIVER=sync
|
||||
REDIS_HOST=127.0.0.1
|
||||
@@ -99,3 +174,5 @@ DEMO_PASSWORD=
|
||||
IS_DOCKER=false
|
||||
IS_SANDSTORM=true
|
||||
IS_HEROKU=false
|
||||
BUNQ_USE_SANDBOX=false
|
||||
FFIII_LAYOUT=v1
|
||||
@@ -1,4 +1,3 @@
|
||||
# Ignore composer specific files and vendor folder
|
||||
composer.phar
|
||||
composer.lock
|
||||
vendor
|
||||
|
||||
98
.env.docker
98
.env.docker
@@ -1,98 +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}
|
||||
|
||||
# APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy.
|
||||
APP_URL=${APP_URL}
|
||||
TRUSTED_PROXIES=${TRUSTED_PROXIES}
|
||||
|
||||
# The log channel defines where your log entries go to.
|
||||
LOG_CHANNEL=${LOG_CHANNEL}
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# If you use SQLite, set connection to `sqlite` and remove the database, username and password settings.
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=${FF_DB_HOST}
|
||||
DB_PORT=${FF_DB_PORT}
|
||||
DB_DATABASE=${FF_DB_NAME}
|
||||
DB_USERNAME=${FF_DB_USER}
|
||||
DB_PASSWORD=${FF_DB_PASSWORD}
|
||||
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# Several other options exist. You can use 'single' for one big fat error log (not recommended).
|
||||
# Also available are 'syslog' and 'errorlog' which will log to the system itself.
|
||||
APP_LOG=syslog
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=info
|
||||
|
||||
# If you're looking for performance improvements, you could install memcached.
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
# 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
|
||||
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}
|
||||
|
||||
# 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
|
||||
TZ=${TZ}
|
||||
130
.env.example
130
.env.example
@@ -8,35 +8,28 @@ APP_DEBUG=false
|
||||
# This should be your email address
|
||||
SITE_OWNER=mail@example.com
|
||||
|
||||
# The encryption key for your database and sessions. Keep this very secure.
|
||||
# If you generate a new one all existing data must be considered LOST.
|
||||
# The encryption key for your sessions. Keep this very secure.
|
||||
# If you generate a new one existing data must be considered LOST.
|
||||
# Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it
|
||||
APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
|
||||
# Change this value to your preferred time zone.
|
||||
# Example: Europe/Amsterdam
|
||||
TZ=UTC
|
||||
TZ=Europe/Amsterdam
|
||||
|
||||
# APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy.
|
||||
# This variable must match your installation's external address but keep in mind that
|
||||
# it's only used on the command line as a fallback value.
|
||||
APP_URL=http://localhost
|
||||
|
||||
# TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy.
|
||||
# Set it to ** and reverse proxies work just fine.
|
||||
TRUSTED_PROXIES=
|
||||
|
||||
# The log channel defines where your log entries go to.
|
||||
LOG_CHANNEL=daily
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=homestead
|
||||
DB_USERNAME=homestead
|
||||
DB_PASSWORD=secret
|
||||
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# Several other options exist. You can use 'single' for one big fat error log (not recommended).
|
||||
# Also available are 'syslog' and 'errorlog' which will log to the system itself.
|
||||
APP_LOG=daily
|
||||
# Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself.
|
||||
LOG_CHANNEL=daily
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
@@ -44,17 +37,48 @@ APP_LOG=daily
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=notice
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html
|
||||
DB_CONNECTION=mysql
|
||||
# If you use DOCKER COMPOSE, change this variable to "firefly_iii_db"
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=homestead
|
||||
DB_USERNAME=homestead
|
||||
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.
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
# You can configure another file storage backend if you cannot use the local storage option.
|
||||
# To set this up, fill in the following variables. The upload path is used to store uploaded
|
||||
# files and the export path is to store exported data (before download).
|
||||
SFTP_HOST=
|
||||
SFTP_PORT=
|
||||
SFTP_UPLOAD_PATH=
|
||||
SFTP_EXPORT_PATH=
|
||||
|
||||
# SFTP uses either the username/password combination or the private key to authenticate.
|
||||
SFTP_USERNAME=
|
||||
SFTP_PASSWORD=
|
||||
SFTP_PRIV_KEY=
|
||||
|
||||
# Cookie settings. Should not be necessary to change these.
|
||||
COOKIE_PATH="/"
|
||||
COOKIE_DOMAIN=
|
||||
COOKIE_SECURE=false
|
||||
|
||||
# If you want Firefly III to mail you, update these settings
|
||||
MAIL_DRIVER=smtp
|
||||
# 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
|
||||
@@ -62,28 +86,85 @@ 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=true
|
||||
|
||||
# These messages contain (sensitive) transaction information:
|
||||
SEND_REPORT_JOURNALS=true
|
||||
|
||||
# Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places.
|
||||
MAPBOX_API_KEY=
|
||||
|
||||
# Set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this will only work for paid fixer.io accounts because they severly limited
|
||||
# Firefly III currently supports two provider for live Currency Exchange Rates:
|
||||
# "fixer", and "ratesapi".
|
||||
# RatesApi.IO (see https://ratesapi.io) is a FREE and OPEN SOURCE live currency exchange rates,
|
||||
# built compatible with Fixer.IO, based on data published by European Central Bank, and doesn't require API key.
|
||||
CER_PROVIDER=ratesapi
|
||||
|
||||
# If you have select "fixer" as default currency exchange rates,
|
||||
# set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this WILL ONLY WORK FOR PAID fixer.io accounts because they severely limited
|
||||
# the free API up to the point where you might as well offer nothing.
|
||||
FIXER_API_KEY=
|
||||
|
||||
# If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here.
|
||||
ANALYTICS_ID=
|
||||
|
||||
# Most parts of the database are encrypted by default, but you can turn this off if you want to.
|
||||
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
||||
USE_ENCRYPTION=true
|
||||
# Firefly III has two options for user authentication. "eloquent" is the default,
|
||||
# and "ldap" for LDAP servers.
|
||||
# For full instructions on these settings please visit:
|
||||
# https://firefly-iii.readthedocs.io/en/latest/installation/authentication.html
|
||||
LOGIN_PROVIDER=eloquent
|
||||
|
||||
# LDAP connection configuration
|
||||
# OpenLDAP, FreeIPA or ActiveDirectory
|
||||
ADLDAP_CONNECTION_SCHEME=OpenLDAP
|
||||
ADLDAP_AUTO_CONNECT=true
|
||||
|
||||
# LDAP connection settings
|
||||
ADLDAP_CONTROLLERS=
|
||||
ADLDAP_PORT=389
|
||||
ADLDAP_TIMEOUT=5
|
||||
ADLDAP_BASEDN=""
|
||||
ADLDAP_FOLLOW_REFFERALS=false
|
||||
ADLDAP_USE_SSL=false
|
||||
ADLDAP_USE_TLS=false
|
||||
|
||||
ADLDAP_ADMIN_USERNAME=
|
||||
ADLDAP_ADMIN_PASSWORD=
|
||||
|
||||
ADLDAP_ACCOUNT_PREFIX=
|
||||
ADLDAP_ACCOUNT_SUFFIX=
|
||||
|
||||
# LDAP authentication settings.
|
||||
ADLDAP_PASSWORD_SYNC=false
|
||||
ADLDAP_LOGIN_FALLBACK=false
|
||||
|
||||
ADLDAP_DISCOVER_FIELD=distinguishedname
|
||||
ADLDAP_AUTH_FIELD=distinguishedname
|
||||
|
||||
# Will allow SSO if your server provides an AUTH_USER field.
|
||||
WINDOWS_SSO_DISCOVER=samaccountname
|
||||
WINDOWS_SSO_KEY=AUTH_USER
|
||||
|
||||
# field to sync as local username.
|
||||
ADLDAP_SYNC_FIELD=userprincipalname
|
||||
|
||||
# You can disable the X-Frame-Options header if it interfears with tools like
|
||||
# Organizr. This is at your own risk.
|
||||
DISABLE_FRAME_HEADER=false
|
||||
|
||||
# Leave the following configuration vars as is.
|
||||
# Unless you like to tinker and know what you're doing.
|
||||
APP_NAME=FireflyIII
|
||||
ADLDAP_CONNECTION=default
|
||||
BROADCAST_DRIVER=log
|
||||
QUEUE_DRIVER=sync
|
||||
REDIS_HOST=127.0.0.1
|
||||
@@ -97,5 +178,8 @@ PUSHER_ID=
|
||||
DEMO_USERNAME=
|
||||
DEMO_PASSWORD=
|
||||
IS_DOCKER=false
|
||||
USE_ENCRYPTION=false
|
||||
IS_SANDSTORM=false
|
||||
IS_HEROKU=false
|
||||
BUNQ_USE_SANDBOX=false
|
||||
FFIII_LAYOUT=v1
|
||||
|
||||
101
.env.heroku
101
.env.heroku
@@ -1,101 +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=heroku
|
||||
|
||||
# Set to true if you want to see debug information in error screens.
|
||||
APP_DEBUG=false
|
||||
|
||||
# This should be your email address
|
||||
SITE_OWNER=heroku@example.com
|
||||
|
||||
# The encryption key for your database and sessions. Keep this very secure.
|
||||
# If you generate a new one all existing data must be considered LOST.
|
||||
# Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it
|
||||
APP_KEY=7ahyYVPVsmxjdhsweWCauGeJfwc92NP2
|
||||
|
||||
# Change this value to your preferred time zone.
|
||||
# Example: Europe/Amsterdam
|
||||
TZ=UTC
|
||||
|
||||
# APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy.
|
||||
APP_URL=http://localhost
|
||||
TRUSTED_PROXIES=
|
||||
|
||||
# The log channel defines where your log entries go to.
|
||||
LOG_CHANNEL=syslog
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# If you use SQLite, set connection to `sqlite` and remove the database, username and password settings.
|
||||
DB_CONNECTION=pgsql
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# Several other options exist. You can use 'single' for one big fat error log (not recommended).
|
||||
# Also available are 'syslog' and 'errorlog' which will log to the system itself.
|
||||
APP_LOG=errorlog
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=debug
|
||||
|
||||
# If you're looking for performance improvements, you could install memcached.
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
# 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
|
||||
MAIL_DRIVER=smtp
|
||||
MAIL_HOST=smtp.mailtrap.io
|
||||
MAIL_PORT=2525
|
||||
MAIL_FROM=changeme@example.com
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
|
||||
# Firefly III can send you the following messages
|
||||
SEND_REGISTRATION_MAIL=true
|
||||
SEND_ERROR_MESSAGE=true
|
||||
|
||||
# Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places.
|
||||
MAPBOX_API_KEY=
|
||||
|
||||
# Set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates.
|
||||
# Please note that this will only work for paid fixer.io accounts because they severly limited
|
||||
# the free API up to the point where you might as well offer nothing.
|
||||
FIXER_API_KEY=
|
||||
|
||||
# If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here.
|
||||
ANALYTICS_ID=
|
||||
|
||||
# Most parts of the database are encrypted by default, but you can turn this off if you want to.
|
||||
# This makes it easier to migrate your database. Not that some fields will never be decrypted.
|
||||
USE_ENCRYPTION=true
|
||||
|
||||
# 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=false
|
||||
IS_SANDSTORM=false
|
||||
IS_HEROKU=true
|
||||
97
.env.testing
97
.env.testing
@@ -1,97 +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
|
||||
|
||||
# APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy.
|
||||
APP_URL=http://localhost
|
||||
TRUSTED_PROXIES=
|
||||
|
||||
# The log channel defines where your log entries go to.
|
||||
LOG_CHANNEL=dailytest
|
||||
|
||||
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
|
||||
# For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html
|
||||
DB_CONNECTION=sqlite
|
||||
|
||||
# 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/.
|
||||
# Several other options exist. You can use 'single' for one big fat error log (not recommended).
|
||||
# Also available are 'syslog' and 'errorlog' which will log to the system itself.
|
||||
APP_LOG=daily
|
||||
|
||||
# Log level. You can set this from least severe to most severe:
|
||||
# debug, info, notice, warning, error, critical, alert, emergency
|
||||
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
|
||||
# nothing will get logged, ever.
|
||||
APP_LOG_LEVEL=debug
|
||||
|
||||
# If you're looking for performance improvements, you could install memcached.
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
# 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
|
||||
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
|
||||
|
||||
# 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
|
||||
27
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
27
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help Firefly III improve
|
||||
|
||||
---
|
||||
|
||||
**Bug description**
|
||||
I am running Firefly III version x.x.x, and my problem is:
|
||||
|
||||
<!-- Replace the version and describe your problem or your issue will be closed. -->
|
||||
|
||||
**Steps to reproduce**
|
||||
<!-- What do you need to do to trigger this bug? -->
|
||||
|
||||
**Expected behavior**
|
||||
<!-- What do you expect to see after those steps? -->
|
||||
|
||||
**Extra info**
|
||||
<!-- Please add extra info here, such as OS, browser, and the output from the /debug page of your Firefly III installation (click the version at the bottom). -->
|
||||
|
||||
**Bonus points**
|
||||
<!-- Earn bonus points by:
|
||||
|
||||
- Post a stacktrace from your log files
|
||||
- Add a screenshot
|
||||
- Remember the human
|
||||
-->
|
||||
25
.github/ISSUE_TEMPLATE/Custom.md
vendored
Normal file
25
.github/ISSUE_TEMPLATE/Custom.md
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
name: I have a question or a problem
|
||||
about: Ask away!
|
||||
|
||||
---
|
||||
|
||||
I am running Firefly III version x.x.x
|
||||
|
||||
**Description**
|
||||
<!-- (if relevant of course) -->
|
||||
|
||||
**Extra info**
|
||||
<!-- Please add extra info here, such as OS, browser, and the output from the `/debug`-page of your Firefly III installation (click the version at the bottom). -->
|
||||
|
||||
|
||||
|
||||
**Bonus points**
|
||||
<!-- Earn bonus points by:
|
||||
|
||||
- Add a screenshot
|
||||
- Make a drawing
|
||||
- Donate money (just kidding ;)
|
||||
- Replicate the problem on the demo site https://demo.firefly-iii.org/
|
||||
- Remember the human
|
||||
-->
|
||||
32
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
32
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea or feature for Firefly III
|
||||
|
||||
---
|
||||
|
||||
**Description**
|
||||
<!--
|
||||
Please describe your feature request:
|
||||
|
||||
- I would like Firefly III to do ABC.
|
||||
- What if you would add feature XYZ?
|
||||
- Firefly III doesn't do DEF.
|
||||
|
||||
-->
|
||||
|
||||
**Solution**
|
||||
<!-- Describe what your feature would add to Firefly III. -->
|
||||
|
||||
**What are alternatives?**
|
||||
<!-- Please describe what alternatives currently exist. -->
|
||||
|
||||
**Additional context**
|
||||
<!-- 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/issue_template.md
vendored
11
.github/issue_template.md
vendored
@@ -1,11 +0,0 @@
|
||||
I am running Firefly III version x.x.x
|
||||
|
||||
#### Description of my issue:
|
||||
|
||||
#### Steps to reproduce
|
||||
|
||||
(please include if this problem also exists on the demo site)
|
||||
|
||||
#### Other important details (log files, system info):
|
||||
|
||||
Please click the version number in the right corner of any Firefly III page to get debug information.
|
||||
11
.github/pull_request_template.md
vendored
11
.github/pull_request_template.md
vendored
@@ -1,4 +1,13 @@
|
||||
Fixes # (if relevant)
|
||||
<!--
|
||||
Before you create a new PR, please consider the following two considerations.
|
||||
|
||||
1) Pull request for the MASTER branch will be closed.
|
||||
2) We cannot accept pull requests to add new currencies.
|
||||
|
||||
Thanks.
|
||||
-->
|
||||
|
||||
Fixes issue # (if relevant)
|
||||
|
||||
Changes in this pull request:
|
||||
|
||||
|
||||
8
.github/ranger.yml
vendored
Normal file
8
.github/ranger.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# in .github/ranger.yml
|
||||
comments:
|
||||
-
|
||||
action: delete_comment
|
||||
pattern: 1
|
||||
-
|
||||
action: delete_comment
|
||||
pattern: ":+1:"
|
||||
59
.github/stale.yml
vendored
Normal file
59
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 7
|
||||
|
||||
# Number of days of inactivity before a stale Issue or Pull Request is closed.
|
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||
daysUntilClose: 7
|
||||
|
||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||
# - "[Status] Maybe Later"
|
||||
exemptLabels:
|
||||
- enhancement
|
||||
- feature
|
||||
- bug
|
||||
- possible-bug
|
||||
- "possible bug"
|
||||
- announcement
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false)
|
||||
exemptMilestones: false
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: stale
|
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
|
||||
# Comment to post when removing the stale label.
|
||||
# unmarkComment: >
|
||||
# Your comment here.
|
||||
|
||||
# Comment to post when closing a stale Issue or Pull Request.
|
||||
# closeComment: >
|
||||
# Your comment here.
|
||||
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 30
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
# only: issues
|
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||
# pulls:
|
||||
# daysUntilStale: 30
|
||||
# markComment: >
|
||||
# This pull request has been automatically marked as stale because it has not had
|
||||
# recent activity. It will be closed if no further activity occurs. Thank you
|
||||
# for your contributions.
|
||||
|
||||
# issues:
|
||||
# exemptLabels:
|
||||
# - confirmed
|
||||
9
.sandstorm/Vagrantfile
vendored
9
.sandstorm/Vagrantfile
vendored
@@ -9,9 +9,16 @@ VM_NAME = File.basename(File.dirname(File.dirname(__FILE__))) + "_sandstorm_#{Ti
|
||||
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
||||
VAGRANTFILE_API_VERSION = "2"
|
||||
|
||||
# ugly hack to prevent hashicorp's bitrot. See https://github.com/hashicorp/vagrant/issues/9442
|
||||
# this setting is required for pre-2.0 vagrant, but causes an error as of 2.0.3,
|
||||
# remove entirely when confident nobody uses vagrant 1.x for anything.
|
||||
unless Vagrant::DEFAULT_SERVER_URL.frozen?
|
||||
Vagrant::DEFAULT_SERVER_URL.replace('https://vagrantcloud.com')
|
||||
end
|
||||
|
||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
# Base on the Sandstorm snapshots of the official Debian 8 (jessie) box.
|
||||
config.vm.box = "sandstorm/debian-jessie64"
|
||||
config.vm.box = "debian/contrib-jessie64"
|
||||
|
||||
if Vagrant.has_plugin?("vagrant-vbguest") then
|
||||
# vagrant-vbguest is a Vagrant plugin that upgrades
|
||||
|
||||
@@ -6,7 +6,7 @@ set -euo pipefail
|
||||
echo "In build.sh"
|
||||
|
||||
cd /opt/app
|
||||
cp .env.sandstorm .env
|
||||
cp .deploy/sandstorm/.env.sandstorm .env
|
||||
|
||||
if [ -f /opt/app/composer.json ] ; then
|
||||
if [ ! -f composer.phar ] ; then
|
||||
|
||||
@@ -1,3 +1,481 @@
|
||||
# 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
|
||||
- Docker file builds again.
|
||||
- Fix CSS of OAuth2 authorization view.
|
||||
|
||||
# 4.7.6.1
|
||||
- An issue where I switched variables from the Docker `.env` file to the normal `.env` file and vice versa -- breaking both.
|
||||
- [Issue 1649](https://github.com/firefly-iii/firefly-iii/issues/1649) 2FA QR code would not show up due to very strict security policy headers
|
||||
- Docker build gave a cURL error whenever it runs PHP commands.
|
||||
|
||||
# 4.7.6
|
||||
- [Issue 145](https://github.com/firefly-iii/firefly-iii/issues/145) You can now download transactions from YNAB.
|
||||
- [Issue 306](https://github.com/firefly-iii/firefly-iii/issues/306) You can now add liabilities to Firefly III.
|
||||
- [Issue 740](https://github.com/firefly-iii/firefly-iii/issues/740) Various charts are now currency aware.
|
||||
- [Issue 833](https://github.com/firefly-iii/firefly-iii/issues/833) Bills can use non-default currencies.
|
||||
- [Issue 1578](https://github.com/firefly-iii/firefly-iii/issues/1578) Firefly III will notify you if the cron job hasn't fired.
|
||||
- [Issue 1623](https://github.com/firefly-iii/firefly-iii/issues/1623) New transactions will link back from the success message.
|
||||
- [Issue 1624](https://github.com/firefly-iii/firefly-iii/issues/1624) transactions will link to the object.
|
||||
- You can call the cron job over the web now (see docs).
|
||||
- You don't need to call the cron job every minute any more.
|
||||
- Various charts are now red/green to signify income and expenses.
|
||||
- Option to add or remove accounts from the net worth calculations.
|
||||
- This will be the last release on PHP 7.1. Future versions will require PHP 7.2.
|
||||
- [Issue 1460](https://github.com/firefly-iii/firefly-iii/issues/1460) Downloading transactions from bunq should go more smoothly.
|
||||
- [Issue 1464](https://github.com/firefly-iii/firefly-iii/issues/1464) Fixed the docker file to work on Raspberry Pi's.
|
||||
- [Issue 1540](https://github.com/firefly-iii/firefly-iii/issues/1540) The Docker file now has a working cron job for recurring transactions.
|
||||
- [Issue 1564](https://github.com/firefly-iii/firefly-iii/issues/1564) Fix double transfers when importing from bunq.
|
||||
- [Issue 1575](https://github.com/firefly-iii/firefly-iii/issues/1575) Some views would give a XSRF token warning
|
||||
- [Issue 1576](https://github.com/firefly-iii/firefly-iii/issues/1576) Fix assigning budgets
|
||||
- [Issue 1580](https://github.com/firefly-iii/firefly-iii/issues/1580) Missing string for translation
|
||||
- [Issue 1581](https://github.com/firefly-iii/firefly-iii/issues/1581) Expand help text
|
||||
- [Issue 1584](https://github.com/firefly-iii/firefly-iii/issues/1584) Link to administration is back.
|
||||
- [Issue 1586](https://github.com/firefly-iii/firefly-iii/issues/1586) Date fields in import were mislabeled.
|
||||
- [Issue 1593](https://github.com/firefly-iii/firefly-iii/issues/1593) Link types are translatable.
|
||||
- [Issue 1594](https://github.com/firefly-iii/firefly-iii/issues/1594) Very long breadcrumbs are weird.
|
||||
- [Issue 1598](https://github.com/firefly-iii/firefly-iii/issues/1598) Fix budget calculations.
|
||||
- [Issue 1597](https://github.com/firefly-iii/firefly-iii/issues/1597) Piggy banks are always inactive.
|
||||
- [Issue 1605](https://github.com/firefly-iii/firefly-iii/issues/1605) System will ignore foreign currency setting if user doesn't indicate the amount.
|
||||
- [Issue 1608](https://github.com/firefly-iii/firefly-iii/issues/1608) Spelling error in command line import.
|
||||
- [Issue 1609](https://github.com/firefly-iii/firefly-iii/issues/1609) Link to budgets page was absolute.
|
||||
- [Issue 1615](https://github.com/firefly-iii/firefly-iii/issues/1615) Fix currency bug in transactions.
|
||||
- [Issue 1616](https://github.com/firefly-iii/firefly-iii/issues/1616) Fix null pointer exception in pie charts.
|
||||
- [Issue 1617](https://github.com/firefly-iii/firefly-iii/issues/1617) Fix for complex tag names in URL's.
|
||||
- [Issue 1620](https://github.com/firefly-iii/firefly-iii/issues/1620) Fixed index reference in API.
|
||||
- [Issue 1639](https://github.com/firefly-iii/firefly-iii/issues/1639) Firefly III trusts the Heroku load balancer, fixing deployment on Heroku.
|
||||
- [Issue 1642](https://github.com/firefly-iii/firefly-iii/issues/1642) Fix issue with split journals.
|
||||
- [Issue 1643](https://github.com/firefly-iii/firefly-iii/issues/1643) Fix reconciliation issue.
|
||||
- Users can no longer give income a budget.
|
||||
- Fix bug in Spectre import.
|
||||
- Heroku would not make you owner.
|
||||
- Add `.htaccess` files to all public directories.
|
||||
- New secure headers will make Firefly III slightly more secure.
|
||||
- The rule "tester" will now also take the "strict"-checkbox into account.
|
||||
|
||||
# 4.7.5.3
|
||||
- [Issue 1527](https://github.com/firefly-iii/firefly-iii/issues/1527), fixed views for transactions without a budget.
|
||||
- [Issue 1553](https://github.com/firefly-iii/firefly-iii/issues/1553), report could not handle transactions before the first one in the system.
|
||||
- [Issue 1549](https://github.com/firefly-iii/firefly-iii/issues/1549) update a budget will also update any rules that refer to that budget.
|
||||
- [Issue 1530](https://github.com/firefly-iii/firefly-iii/issues/1530), fix issue with bill chart.
|
||||
- [Issue 1563](https://github.com/firefly-iii/firefly-iii/issues/1563), fix piggy bank suggested amount
|
||||
- [Issue 1571](https://github.com/firefly-iii/firefly-iii/issues/1571), fix OAuth in Sandstorm
|
||||
- [Issue 1568](https://github.com/firefly-iii/firefly-iii/issues/1568), bug in Sandstorm user code.
|
||||
- [Issue 1569](https://github.com/firefly-iii/firefly-iii/issues/1569), optimized Sandstorm build by [ocdtrekkie](https://github.com/ocdtrekkie)
|
||||
- Fixed a bug where transfers would be stored inversely when using the CSV import.
|
||||
- Retired the "Rabobank description"-fix, because it is no longer necessary.
|
||||
- Fixed a bug where users could not delete budget limits in the API.
|
||||
- Piggy bank notes are visible again.
|
||||
|
||||
# 4.7.5.1
|
||||
- [Issue 1531](https://github.com/firefly-iii/firefly-iii/issues/1531), the database routine incorrectly reports empty categories.
|
||||
- [Issue 1532](https://github.com/firefly-iii/firefly-iii/issues/1532), broken dropdown for autosuggest things.
|
||||
- [Issue 1533](https://github.com/firefly-iii/firefly-iii/issues/1533), fix where the import could not import category names.
|
||||
- [Issue 1538](https://github.com/firefly-iii/firefly-iii/issues/1538), fix a bug where Spectre would not work when ignoring rules.
|
||||
- [Issue 1542](https://github.com/firefly-iii/firefly-iii/issues/1542), fix a bug where the importer was incapable of generating new currencies.
|
||||
- [Issue 1541](https://github.com/firefly-iii/firefly-iii/issues/1541), no longer ignore composer.lock in Docker ignore.
|
||||
- Bills are stored inactive.
|
||||
|
||||
# 4.7.5
|
||||
- A new feature called "recurring transactions" that will make Firefly III automatically create transactions for you.
|
||||
- New API end points for attachments, available budgets, budgets, budget limits, categories, configuration, currency exchange rates, journal links, link types, piggy banks, preferences, recurring transactions, rules, rule groups and tags.
|
||||
- Added support for YunoHost.
|
||||
- The 2FA secret is visible so you can type it into 2FA apps.
|
||||
- Bunq and Spectre imports will now ask to apply rules.
|
||||
- Sandstorm users can now make API keys.
|
||||
- Various typo's in the English translations. [issue 1493](https://github.com/firefly-iii/firefly-iii/issues/1493)
|
||||
- Bug where Spectre was never called [issue 1492](https://github.com/firefly-iii/firefly-iii/issues/1492)
|
||||
- Clear cache after journal is created through API [issue 1483](https://github.com/firefly-iii/firefly-iii/issues/1483)
|
||||
- Make sure docker directories exist [issue 1500](https://github.com/firefly-iii/firefly-iii/issues/1500)
|
||||
- Broken link to bill edit [issue 1505](https://github.com/firefly-iii/firefly-iii/issues/1505)
|
||||
- Several bugs in the editing of split transactions [issue 1509](https://github.com/firefly-iii/firefly-iii/issues/1509)
|
||||
- Import routine ignored formatting of several date fields [issue 1510](https://github.com/firefly-iii/firefly-iii/issues/1510)
|
||||
- Piggy bank events now show the correct currency [issue 1446](https://github.com/firefly-iii/firefly-iii/issues/1446)
|
||||
- Inactive accounts are no longer suggested [issue 1463](https://github.com/firefly-iii/firefly-iii/issues/1463)
|
||||
- Some income / expense charts are less confusing [issue 1518](https://github.com/firefly-iii/firefly-iii/issues/1518)
|
||||
- Validation bug in multi-currency create view [issue 1521](https://github.com/firefly-iii/firefly-iii/issues/1521)
|
||||
|
||||
# 4.7.4
|
||||
- [Issue 1409](https://github.com/firefly-iii/firefly-iii/issues/1409), add Indian Rupee and explain that users can do this themselves [issue 1413](https://github.com/firefly-iii/firefly-iii/issues/1413)
|
||||
- [Issue 1445](https://github.com/firefly-iii/firefly-iii/issues/1445), upgrade Curl in Docker image.
|
||||
- [Issue 1386](https://github.com/firefly-iii/firefly-iii/issues/1386), quick links to often used pages.
|
||||
- [Issue 1405](https://github.com/firefly-iii/firefly-iii/issues/1405), show proposed amount to piggy banks.
|
||||
- [Issue 1416](https://github.com/firefly-iii/firefly-iii/issues/1416), ability to delete lost attachments.
|
||||
- A completely rewritten import routine that can handle bunq (thanks everybody for testing!), CSV files and Spectre. Please make sure you read about this at http://bit.ly/FF3-new-import
|
||||
- [Issue 1392](https://github.com/firefly-iii/firefly-iii/issues/1392), explicitly mention rules are inactive (when they are).
|
||||
- [Issue 1406](https://github.com/firefly-iii/firefly-iii/issues/1406), bill conversion to rules will be smarter about the rules they create.
|
||||
- [Issue 1369](https://github.com/firefly-iii/firefly-iii/issues/1369), you can now properly order piggy banks again.
|
||||
- [Issue 1389](https://github.com/firefly-iii/firefly-iii/issues/1389), null-pointer in the import routine.
|
||||
- [Issue 1400](https://github.com/firefly-iii/firefly-iii/issues/1400), missing translation.
|
||||
- [Issue 1403](https://github.com/firefly-iii/firefly-iii/issues/1403), bill would always be marked as inactive in edit screen.
|
||||
- [Issue 1418](https://github.com/firefly-iii/firefly-iii/issues/1418), missing note text on bill page.
|
||||
- Export routine would break when encountering un-decryptable files.
|
||||
- [Issue 1425](https://github.com/firefly-iii/firefly-iii/issues/1425), empty fields when edit multiple transactions at once.
|
||||
- [Issue 1449](https://github.com/firefly-iii/firefly-iii/issues/1449), bad calculations in "budget left to spend" view.
|
||||
- [Issue 1451](https://github.com/firefly-iii/firefly-iii/issues/1451), same but in another view.
|
||||
- [Issue 1453](https://github.com/firefly-iii/firefly-iii/issues/1453), same as [issue 1403](https://github.com/firefly-iii/firefly-iii/issues/1403).
|
||||
- [Issue 1455](https://github.com/firefly-iii/firefly-iii/issues/1455), could add income to a budget.
|
||||
- [Issue 1442](https://github.com/firefly-iii/firefly-iii/issues/1442), issues with editing a split deposit.
|
||||
- [Issue 1452](https://github.com/firefly-iii/firefly-iii/issues/1452), date range problems with tags.
|
||||
- [Issue 1458](https://github.com/firefly-iii/firefly-iii/issues/1458), same for transactions.
|
||||
- [Issue 1415](https://github.com/firefly-iii/firefly-iii/issues/1415), will email you when OAuth2 keys are generated.
|
||||
|
||||
# 4.7.3.2
|
||||
- Forgot to increase the version number :(.
|
||||
|
||||
# 4.7.3.1
|
||||
- Fixed a critical bug where the rules-engine would fire inadvertently.
|
||||
|
||||
# 4.7.3
|
||||
- Currency added to API
|
||||
- Firfely III will also generate a cash wallet for new users.
|
||||
- Can now reset Spectre and bunq settings
|
||||
- Docker file has a time zone
|
||||
- Allow database connection to be configured in Docker file
|
||||
- Can now view and edit attachments in edit-screen
|
||||
- User can visit hidden `/attachments` page
|
||||
- [Issue 1356](https://github.com/firefly-iii/firefly-iii/issues/1356): Budgets will show the remaining amount per day
|
||||
- [Issue 1367](https://github.com/firefly-iii/firefly-iii/issues/1367): Rules now come in strict and non-strict mode.
|
||||
- Added a security.txt
|
||||
- More support for trusted proxies
|
||||
- Improved edit routine for split transactions.
|
||||
- Upgrade routine can handle `proc_close` being disabled.
|
||||
- Bills now use rules to match transactions, making it more flexible.
|
||||
- [Issue 1328](https://github.com/firefly-iii/firefly-iii/issues/1328): piggy banks no have a more useful chart.
|
||||
- Spectre API upgraded to v4
|
||||
- Move to MariaDB ([issue 1366](https://github.com/firefly-iii/firefly-iii/issues/1366))
|
||||
- Piggy banks take currency from parent account ([issue 1334](https://github.com/firefly-iii/firefly-iii/issues/1334))
|
||||
- [Issue 1341](https://github.com/firefly-iii/firefly-iii/issues/1341): Removed depricated command from dockerfile
|
||||
- Several issues with docker image ([issue 1320](https://github.com/firefly-iii/firefly-iii/issues/1320), [issue 1382](https://github.com/firefly-iii/firefly-iii/issues/1382)).
|
||||
- Fix giant tags and division by zero ([issue 1325](https://github.com/firefly-iii/firefly-iii/issues/1325) and others)
|
||||
- Several issues with bunq import ([issue 1352](https://github.com/firefly-iii/firefly-iii/issues/1352), [issue 1330](https://github.com/firefly-iii/firefly-iii/issues/1330), [issue 1378](https://github.com/firefly-iii/firefly-iii/issues/1378), [issue 1380](https://github.com/firefly-iii/firefly-iii/issues/1380))
|
||||
- [Issue 1246](https://github.com/firefly-iii/firefly-iii/issues/1246): date picker is internationalised
|
||||
- [Issue 1327](https://github.com/firefly-iii/firefly-iii/issues/1327): fix formattting issues in piggy banks
|
||||
- [Issue 1348](https://github.com/firefly-iii/firefly-iii/issues/1348): 500 error in API
|
||||
- [Issue 1349](https://github.com/firefly-iii/firefly-iii/issues/1349): Errors in import routine
|
||||
- Several fixes for (multi-currency) reconciliation ([issue 1336](https://github.com/firefly-iii/firefly-iii/issues/1336), [issue 1363](https://github.com/firefly-iii/firefly-iii/issues/1363))
|
||||
- [Issue 1353](https://github.com/firefly-iii/firefly-iii/issues/1353): return NULL values in range-indicator
|
||||
- Bug in split transaction edit routine
|
||||
- Piggy bank percentage was very specific.
|
||||
- Logging in Slack is easier to config.
|
||||
- [Issue 1312](https://github.com/firefly-iii/firefly-iii/issues/1312) Import broken for ING accounts
|
||||
- [Issue 1313](https://github.com/firefly-iii/firefly-iii/issues/1313) Error when creating new asset account
|
||||
- [Issue 1317](https://github.com/firefly-iii/firefly-iii/issues/1317) Forgot an include :(
|
||||
- Null pointer exception in transaction overview.
|
||||
- Installations running in subdirs were incapable of creating OAuth tokens.
|
||||
- OAuth keys were not created in all cases.
|
||||
|
||||
# 4.7.2
|
||||
- [Issue 1123](https://github.com/firefly-iii/firefly-iii/issues/1123) First browser based update routine.
|
||||
- Add support for Italian.
|
||||
@@ -40,8 +518,6 @@
|
||||
- [Issue 1297](https://github.com/firefly-iii/firefly-iii/issues/1297) Could not convert to withdrawal
|
||||
- [Issue 1226](https://github.com/firefly-iii/firefly-iii/issues/1226) Category overview in default report shows no income.
|
||||
- Various other bugs and problems ([issue 1198](https://github.com/firefly-iii/firefly-iii/issues/1198), [issue 1213](https://github.com/firefly-iii/firefly-iii/issues/1213), [issue 1237](https://github.com/firefly-iii/firefly-iii/issues/1237), [issue 1238](https://github.com/firefly-iii/firefly-iii/issues/1238), [issue 1199](https://github.com/firefly-iii/firefly-iii/issues/1199), [issue 1200](https://github.com/firefly-iii/firefly-iii/issues/1200))
|
||||
|
||||
### Security
|
||||
- Fixed an issue with token validation on the command line.
|
||||
|
||||
# 4.7.1
|
||||
|
||||
@@ -9,6 +9,10 @@ CURL_OPTS="--silent --show-error"
|
||||
echo localhost > /etc/hostname
|
||||
hostname localhost
|
||||
|
||||
# Install curl that is needed below.
|
||||
apt-get update
|
||||
apt-get install -y curl
|
||||
|
||||
# The following line copies stderr through stderr to cat without accidentally leaving it in the
|
||||
# output file. Be careful when changing. See: https://github.com/sandstorm-io/vagrant-spk/pull/159
|
||||
curl $CURL_OPTS https://install.sandstorm.io/ 2>&1 > /host-dot-sandstorm/caches/install.sh | cat
|
||||
|
||||
@@ -11,7 +11,7 @@ mkdir -p /var/log
|
||||
mkdir -p /var/log/mysql
|
||||
mkdir -p /var/log/nginx
|
||||
# Wipe /var/run, since pidfiles and socket files from previous launches should go away
|
||||
# TODO someday: I'd prefer a tmpfs for these.
|
||||
# Someday: I'd prefer a tmpfs for these.
|
||||
rm -rf /var/run
|
||||
mkdir -p /var/run
|
||||
rm -rf /var/tmp
|
||||
@@ -25,9 +25,9 @@ mkdir -p /var/storage/build
|
||||
mkdir -p /var/storage/database
|
||||
mkdir -p /var/storage/debugbar
|
||||
mkdir -p /var/storage/export
|
||||
mkdir -p /var/storage/framework/cache
|
||||
mkdir -p /var/storage/framework/cache/v1
|
||||
mkdir -p /var/storage/framework/sessions
|
||||
mkdir -p /var/storage/framework/views
|
||||
mkdir -p /var/storage/framework/views/v1
|
||||
mkdir -p /var/storage/logs
|
||||
mkdir -p /var/storage/upload
|
||||
|
||||
@@ -37,15 +37,15 @@ HOME=/etc/mysql /usr/bin/mysql_install_db --force
|
||||
# Spawn mysqld, php
|
||||
HOME=/etc/mysql /usr/sbin/mysqld &
|
||||
|
||||
/usr/sbin/php-fpm7.1 --nodaemonize --fpm-config /etc/php/7.1/fpm/php-fpm.conf &
|
||||
/usr/sbin/php-fpm7.2 --nodaemonize --fpm-config /etc/php/7.2/fpm/php-fpm.conf &
|
||||
|
||||
# Wait until mysql and php have bound their sockets, indicating readiness
|
||||
while [ ! -e /var/run/mysqld/mysqld.sock ] ; do
|
||||
echo "waiting for mysql to be available at /var/run/mysqld/mysqld.sock"
|
||||
sleep .5
|
||||
done
|
||||
while [ ! -e /var/run/php7.1-fpm.sock ] ; do
|
||||
echo "waiting for php7.1-fpm to be available at /var/run/php7.1-fpm.sock"
|
||||
while [ ! -e /var/run/php7.2-fpm.sock ] ; do
|
||||
echo "waiting for php7.2-fpm to be available at /var/run/php7.2-fpm.sock"
|
||||
sleep .5
|
||||
done
|
||||
|
||||
@@ -58,9 +58,5 @@ echo "Migrating..."
|
||||
php /opt/app/artisan migrate --seed --force
|
||||
echo "Done!"
|
||||
|
||||
echo "Clear cache.."
|
||||
php /opt/app/artisan cache:clear
|
||||
echo "Done"
|
||||
|
||||
# Start nginx.
|
||||
/usr/sbin/nginx -c /opt/app/.sandstorm/service-config/nginx.conf -g "daemon off;"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,8 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
|
||||
manifest = (
|
||||
appTitle = (defaultText = "Firefly III"),
|
||||
appVersion = 10,
|
||||
appMarketingVersion = (defaultText = "4.7.2"),
|
||||
appVersion = 34,
|
||||
appMarketingVersion = (defaultText = "4.8.0.2"),
|
||||
|
||||
actions = [
|
||||
# Define your "new document" handlers here.
|
||||
@@ -65,9 +65,9 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
# Sizes are given in device-independent pixels, so if you took these
|
||||
# screenshots on a Retina-style high DPI screen, divide each dimension by two.
|
||||
|
||||
(width = 1291, height = 800, png = embed "screenshots/screenshot-1.png"),
|
||||
(width = 1291, height = 800, png = embed "screenshots/screenshot-2.png"),
|
||||
(width = 1291, height = 800, png = embed "screenshots/screenshot-3.png"),
|
||||
(width = 1290, height = 800, png = embed "screenshots/screenshot-1.png"),
|
||||
(width = 1290, height = 800, png = embed "screenshots/screenshot-2.png"),
|
||||
(width = 1290, height = 800, png = embed "screenshots/screenshot-3.png"),
|
||||
|
||||
],
|
||||
changeLog = (defaultText = embed "changelog.md"),
|
||||
@@ -103,7 +103,7 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
# not have been detected as a dependency during `spk dev`. If you list
|
||||
# a directory here, its entire contents will be included recursively.
|
||||
|
||||
#bridgeConfig = (
|
||||
bridgeConfig = (
|
||||
# # Used for integrating permissions and roles into the Sandstorm shell
|
||||
# # and for sandstorm-http-bridge to pass to your app.
|
||||
# # Uncomment this block and adjust the permissions and roles to make
|
||||
@@ -165,12 +165,12 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
# ),
|
||||
# ],
|
||||
# ),
|
||||
# #apiPath = "/api",
|
||||
apiPath = "/api/v1/",
|
||||
# # Apps can export an API to the world. The API is to be used primarily by Javascript
|
||||
# # code and native apps, so it can't serve out regular HTML to browsers. If a request
|
||||
# # comes in to your app's API, sandstorm-http-bridge will prefix the request's path with
|
||||
# # this string, if specified.
|
||||
#),
|
||||
),
|
||||
);
|
||||
|
||||
const myCommand :Spk.Manifest.Command = (
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 173 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 171 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 163 KiB |
@@ -53,7 +53,7 @@ http {
|
||||
}
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_pass unix:/var/run/php7.1-fpm.sock;
|
||||
fastcgi_pass unix:/var/run/php7.2-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -13,65 +13,67 @@ apt-get update
|
||||
apt-get install -y python-software-properties software-properties-common
|
||||
|
||||
# install all languages
|
||||
sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
|
||||
#en_US
|
||||
sed -i 's/# es_ES.UTF-8 UTF-8/es_ES.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# id_ID.UTF-8 UTF-8/id_ID.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/# nl_NL.UTF-8 UTF-8/nl_NL.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# pl_PL.UTF-8 UTF-8/pl_PL.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# pt_BR.UTF-8 UTF-8/pt_BR.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# ru_RU.UTF-8 UTF-8/ru_RU.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# tr_TR.UTF-8 UTF-8/tr_TR.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# zh_TW.UTF-8 UTF-8/zh_TW.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# nb_NO.UTF-8 UTF-8/nb_NO.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# ro_RO.UTF-8 UTF-8/ro_RO.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# cs_CZ.UTF-8 UTF-8/cs_CZ.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# id_ID.UTF-8 UTF-8/id_ID.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
sed -i 's/# hu_HU.UTF-8 UTF-8/hu_HU.UTF-8 UTF-8/g' /etc/locale.gen
|
||||
|
||||
dpkg-reconfigure --frontend=noninteractive locales
|
||||
|
||||
|
||||
|
||||
|
||||
# actually add repository
|
||||
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E9C74FEEA2098A6E
|
||||
add-apt-repository "deb http://packages.dotdeb.org jessie all"
|
||||
|
||||
# add another repos
|
||||
apt-get install apt-transport-https lsb-release ca-certificates
|
||||
apt-get install -y apt-transport-https lsb-release ca-certificates
|
||||
wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
|
||||
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list
|
||||
|
||||
# install packages.
|
||||
apt-get update
|
||||
apt-get install -y nginx php7.1-fpm php7.1-mysql php7.1-gd php7.1-cli php7.1-curl git php7.1-dev php7.1-zip php7.1-intl php7.1-dom php7.1-mbstring php7.1-bcmath mysql-server
|
||||
apt-get install -y nginx php7.2-fpm php7.2-mysql php7.2-gd php7.2-cli php7.2-curl php7.2-ldap git php7.2-dev php7.2-zip php7.2-intl php7.2-dom php7.2-mbstring php7.2-bcmath mysql-server
|
||||
service nginx stop
|
||||
service php7.1-fpm stop
|
||||
service php7.2-fpm stop
|
||||
service mysql stop
|
||||
systemctl disable nginx
|
||||
systemctl disable php7.1-fpm
|
||||
systemctl disable php7.2-fpm
|
||||
systemctl disable mysql
|
||||
|
||||
# make php.ini display errors:
|
||||
sed -i 's/display_errors = Off/display_errors = On/g' /etc/php/7.1/fpm/php.ini
|
||||
sed -i 's/display_errors = Off/display_errors = On/g' /etc/php/7.2/fpm/php.ini
|
||||
|
||||
# patch /etc/php/7.1/fpm/pool.d/www.conf to not change uid/gid to www-data
|
||||
# patch /etc/php/7.2/fpm/pool.d/www.conf to not change uid/gid to www-data
|
||||
sed --in-place='' \
|
||||
--expression='s/^listen.owner = www-data/;listen.owner = www-data/' \
|
||||
--expression='s/^listen.group = www-data/;listen.group = www-data/' \
|
||||
/etc/php/7.1/fpm/pool.d/www.conf
|
||||
# patch /etc/php/7.1/fpm/php-fpm.conf to not have a pidfile
|
||||
/etc/php/7.2/fpm/pool.d/www.conf
|
||||
# patch /etc/php/7.2/fpm/php-fpm.conf to not have a pidfile
|
||||
sed --in-place='' \
|
||||
--expression='s/^pid =/;pid =/' \
|
||||
/etc/php/7.1/fpm/php-fpm.conf
|
||||
/etc/php/7.2/fpm/php-fpm.conf
|
||||
|
||||
# move sock file to better dir:
|
||||
sed --in-place='' \
|
||||
--expression='s/^listen = \/run\/php\/php7.1-fpm.sock/listen = \/var\/run\/php7.1-fpm.sock/' \
|
||||
/etc/php/7.1/fpm/pool.d/www.conf
|
||||
--expression='s/^listen = \/run\/php\/php7.2-fpm.sock/listen = \/var\/run\/php7.2-fpm.sock/' \
|
||||
/etc/php/7.2/fpm/pool.d/www.conf
|
||||
|
||||
# patch /etc/php/7.1/fpm/pool.d/www.conf to no clear environment variables
|
||||
# patch /etc/php/7.2/fpm/pool.d/www.conf to no clear environment variables
|
||||
# so we can pass in SANDSTORM=1 to apps
|
||||
sed --in-place='' \
|
||||
--expression='s/^;clear_env = no/clear_env=no/' \
|
||||
/etc/php/7.1/fpm/pool.d/www.conf
|
||||
/etc/php/7.2/fpm/pool.d/www.conf
|
||||
# patch mysql conf to not change uid, and to use /var/tmp over /tmp
|
||||
# for secure-file-priv see https://github.com/sandstorm-io/vagrant-spk/issues/195
|
||||
sed --in-place='' \
|
||||
|
||||
45
.travis.yml
45
.travis.yml
@@ -1,30 +1,29 @@
|
||||
language: php
|
||||
php:
|
||||
- 7.1
|
||||
sudo: required
|
||||
language: bash
|
||||
env:
|
||||
- VERSION=4.8.0.2
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- vendor
|
||||
- $HOME/.composer/cache
|
||||
|
||||
install:
|
||||
- rm composer.lock
|
||||
- composer update --no-scripts
|
||||
- cp .env.testing .env
|
||||
- php artisan clear-compiled
|
||||
- php artisan env
|
||||
- cp .env.testing .env
|
||||
- wget -q https://github.com/firefly-iii/test-data/raw/master/storage/database.sqlite -O storage/database/database.sqlite
|
||||
- mkdir -p build/logs
|
||||
|
||||
script:
|
||||
- ./vendor/bin/phpunit -c phpunit.coverage.xml
|
||||
|
||||
after_success:
|
||||
- travis_retry php vendor/bin/php-coveralls -x storage/build/clover-all.xml
|
||||
dist: xenial
|
||||
|
||||
# safelist
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
- master
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
script:
|
||||
# enable experimental features.
|
||||
- echo '{"experimental":true}' | sudo tee /etc/docker/daemon.json
|
||||
- mkdir $HOME/.docker
|
||||
- touch $HOME/.docker/config.json
|
||||
- echo '{"experimental":"enabled"}' | sudo tee $HOME/.docker/config.json
|
||||
- sudo service docker restart
|
||||
- docker version -f '{{.Server.Experimental}}'
|
||||
- docker version
|
||||
# build everything
|
||||
- .deploy/docker/build-amd64.sh
|
||||
- .deploy/docker/build-arm.sh
|
||||
- .deploy/docker/manifest.sh
|
||||
|
||||
77
Dockerfile
77
Dockerfile
@@ -1,61 +1,48 @@
|
||||
# use PHP 7.1 and Apache as a base.
|
||||
FROM php:7.1-apache
|
||||
FROM php:7.2-apache
|
||||
ENV FIREFLY_PATH=/var/www/firefly-iii COMPOSER_ALLOW_SUPERUSER=1
|
||||
LABEL version="1.5" maintainer="thegrumpydictator@gmail.com"
|
||||
|
||||
# set working dir
|
||||
ENV FIREFLY_PATH /var/www/firefly-iii
|
||||
# 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
|
||||
|
||||
# install packages
|
||||
RUN apt-get update -y && \
|
||||
apt-get install -y --no-install-recommends libcurl4-openssl-dev \
|
||||
zlib1g-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libpng12-dev \
|
||||
libicu-dev \
|
||||
libedit-dev \
|
||||
libtidy-dev \
|
||||
libxml2-dev \
|
||||
libsqlite3-dev \
|
||||
libpq-dev \
|
||||
libbz2-dev \
|
||||
gettext-base \
|
||||
locales && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
# 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
|
||||
|
||||
# Install PHP exentions.
|
||||
RUN docker-php-ext-install -j$(nproc) curl gd intl json readline tidy zip bcmath xml mbstring pdo_sqlite pdo_mysql bz2 pdo_pgsql
|
||||
|
||||
# Generate locales supported by Firefly III
|
||||
RUN echo "de_DE.UTF-8 UTF-8\nen_US.UTF-8 UTF-8\nfr_FR.UTF-8 UTF-8\nid_ID.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npl_PL.UTF-8 UTF-8" > /etc/locale.gen && locale-gen
|
||||
# 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 apache mod rewrite..
|
||||
RUN a2enmod rewrite
|
||||
|
||||
# Enable apache mod ssl..
|
||||
RUN a2enmod ssl
|
||||
|
||||
# Create volumes for several directories:
|
||||
VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload
|
||||
|
||||
# Setup the Composer installer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Enable default site (Firefly III)
|
||||
COPY ./.deploy/docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf
|
||||
|
||||
# Make sure we own Firefly III directory
|
||||
RUN chown -R www-data:www-data /var/www && chmod -R 775 $FIREFLY_PATH/storage
|
||||
|
||||
# Run composer
|
||||
RUN composer install --prefer-dist --no-dev --no-scripts --no-suggest
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
# Run entrypoint thing
|
||||
ENTRYPOINT [".deploy/docker/entrypoint.sh"]
|
||||
ENTRYPOINT [".deploy/docker/entrypoint.sh"]
|
||||
|
||||
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": [
|
||||
{
|
||||
"url": "heroku/php"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/heroku/heroku-buildpack-locale"
|
||||
}
|
||||
],
|
||||
"env": {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* AboutController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,33 +20,41 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use DB;
|
||||
use FireflyIII\Transformers\UserTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class AboutController
|
||||
* Returns basic information about this installation.
|
||||
* @codeCoverageIgnore
|
||||
* Class AboutController.
|
||||
*/
|
||||
class AboutController extends Controller
|
||||
{
|
||||
/**
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* Returns system information.
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function about()
|
||||
public function about(): JsonResponse
|
||||
{
|
||||
$search = ['~', '#'];
|
||||
$replace = ['\~', '# '];
|
||||
$phpVersion = str_replace($search, $replace, PHP_VERSION);
|
||||
$phpOs = str_replace($search, $replace, PHP_OS);
|
||||
$currentDriver = DB::getDriverName();
|
||||
|
||||
|
||||
$data
|
||||
= [
|
||||
= [
|
||||
'version' => config('firefly.version'),
|
||||
'api_version' => config('firefly.api_version'),
|
||||
'php_version' => $phpVersion,
|
||||
@@ -54,20 +62,26 @@ class AboutController extends Controller
|
||||
'driver' => $currentDriver,
|
||||
];
|
||||
|
||||
return response()->json(['data' => $data], 200)->header('Content-Type', 'application/vnd.api+json');
|
||||
return response()->json(['data' => $data])->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* Returns information about the user.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function user(Request $request)
|
||||
public function user(Request $request): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item(auth()->user(), new UserTransformer($this->parameters), 'users');
|
||||
|
||||
/** @var UserTransformer $transformer */
|
||||
$transformer = app(UserTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item(auth()->user(), $transformer, 'users');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* AccountController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,50 +19,57 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\AccountRequest;
|
||||
use FireflyIII\Api\V1\Requests\AccountStoreRequest;
|
||||
use FireflyIII\Api\V1\Requests\AccountUpdateRequest;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Preferences;
|
||||
|
||||
/**
|
||||
* Class AccountController
|
||||
* Class AccountController.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class AccountController extends Controller
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface */
|
||||
private $currencyRepository;
|
||||
/** @var AccountRepositoryInterface */
|
||||
use AccountFilter, TransactionFilter;
|
||||
/** @var AccountRepositoryInterface The account repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
// @var AccountRepositoryInterface repository
|
||||
$this->repository = app(AccountRepositoryInterface::class);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
||||
$this->currencyRepository->setUser(auth()->user());
|
||||
$this->repository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -73,11 +79,12 @@ class AccountController extends Controller
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \FireflyIII\Models\Account $account
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @codeCoverageIgnore
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function delete(Account $account)
|
||||
public function delete(Account $account): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($account, null);
|
||||
|
||||
@@ -89,12 +96,13 @@ class AccountController extends Controller
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager();
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// read type from URI
|
||||
@@ -102,8 +110,8 @@ class AccountController extends Controller
|
||||
$this->parameters->set('type', $type);
|
||||
|
||||
// types to get, page size:
|
||||
$types = $this->mapTypes($this->parameters->get('type'));
|
||||
$pageSize = (int)Preferences::getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$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.
|
||||
$collection = $this->repository->getAccountsByType($types);
|
||||
@@ -116,52 +124,158 @@ class AccountController extends Controller
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new FractalCollection($accounts, new AccountTransformer($this->parameters), 'accounts');
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($accounts, $transformer, 'accounts');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List all piggies.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(Request $request, Account $account)
|
||||
public function piggyBanks(Request $request, Account $account): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// 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.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Account $account
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(Request $request, Account $account): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
$resource = new Item($account, new AccountTransformer($this->parameters), 'accounts');
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($account, $transformer, 'accounts');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccountRequest $request
|
||||
* Store a new instance.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @param AccountStoreRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(AccountRequest $request)
|
||||
public function store(AccountStoreRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
// if currency ID is 0, find the currency by the code:
|
||||
if (0 === $data['currency_id']) {
|
||||
$currency = $this->currencyRepository->findByCodeNull($data['currency_code']);
|
||||
$data['currency_id'] = null === $currency ? 0 : $currency->id;
|
||||
}
|
||||
$data = $request->getAllAccountData();
|
||||
$account = $this->repository->store($data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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));
|
||||
|
||||
$resource = new Item($account, new AccountTransformer($this->parameters), 'accounts');
|
||||
/** @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');
|
||||
}
|
||||
@@ -169,93 +283,25 @@ class AccountController extends Controller
|
||||
/**
|
||||
* Update account.
|
||||
*
|
||||
* @param AccountRequest $request
|
||||
* @param Account $account
|
||||
* @param AccountUpdateRequest $request
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(AccountRequest $request, Account $account)
|
||||
public function update(AccountUpdateRequest $request, Account $account): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
// if currency ID is 0, find the currency by the code:
|
||||
if (0 === $data['currency_id']) {
|
||||
$currency = $this->currencyRepository->findByCodeNull($data['currency_code']);
|
||||
$data['currency_id'] = null === $currency ? 0 : $currency->id;
|
||||
}
|
||||
// set correct type:
|
||||
$data = $request->getAllAccountData();
|
||||
$data['type'] = config('firefly.shortNamesByFullName.' . $account->accountType->type);
|
||||
$this->repository->update($account, $data);
|
||||
$manager = new Manager();
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($account, new AccountTransformer($this->parameters), 'accounts');
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($account, $transformer, 'accounts');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mapTypes(string $type): array
|
||||
{
|
||||
$types = [
|
||||
'all' => [
|
||||
AccountType::DEFAULT,
|
||||
AccountType::CASH,
|
||||
AccountType::ASSET,
|
||||
AccountType::EXPENSE,
|
||||
AccountType::REVENUE,
|
||||
AccountType::INITIAL_BALANCE,
|
||||
AccountType::BENEFICIARY,
|
||||
AccountType::IMPORT,
|
||||
AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,
|
||||
],
|
||||
'asset' => [
|
||||
AccountType::DEFAULT,
|
||||
AccountType::ASSET,
|
||||
],
|
||||
'cash' => [
|
||||
AccountType::CASH,
|
||||
],
|
||||
'expense' => [
|
||||
AccountType::EXPENSE,
|
||||
AccountType::BENEFICIARY,
|
||||
],
|
||||
'revenue' => [
|
||||
AccountType::REVENUE,
|
||||
],
|
||||
'special' => [
|
||||
AccountType::CASH,
|
||||
AccountType::INITIAL_BALANCE,
|
||||
AccountType::IMPORT,
|
||||
AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,
|
||||
],
|
||||
'hidden' => [
|
||||
AccountType::INITIAL_BALANCE,
|
||||
AccountType::IMPORT,
|
||||
AccountType::RECONCILIATION,
|
||||
AccountType::LOAN,
|
||||
],
|
||||
AccountType::DEFAULT => [AccountType::DEFAULT],
|
||||
AccountType::CASH => [AccountType::CASH],
|
||||
AccountType::ASSET => [AccountType::ASSET],
|
||||
AccountType::EXPENSE => [AccountType::EXPENSE],
|
||||
AccountType::REVENUE => [AccountType::REVENUE],
|
||||
AccountType::INITIAL_BALANCE => [AccountType::INITIAL_BALANCE],
|
||||
AccountType::BENEFICIARY => [AccountType::BENEFICIARY],
|
||||
AccountType::IMPORT => [AccountType::IMPORT],
|
||||
AccountType::RECONCILIATION => [AccountType::RECONCILIATION],
|
||||
AccountType::LOAN => [AccountType::LOAN],
|
||||
];
|
||||
if (isset($types[$type])) {
|
||||
return $types[$type];
|
||||
}
|
||||
|
||||
return $types['all']; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
251
app/Api/V1/Controllers/AttachmentController.php
Normal file
251
app/Api/V1/Controllers/AttachmentController.php
Normal file
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
/**
|
||||
* AttachmentController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\AttachmentStoreRequest;
|
||||
use FireflyIII\Api\V1\Requests\AttachmentUpdateRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
|
||||
use FireflyIII\Models\Attachment;
|
||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response as LaravelResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use function strlen;
|
||||
|
||||
/**
|
||||
* Class AttachmentController.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class AttachmentController extends Controller
|
||||
{
|
||||
/** @var AttachmentRepositoryInterface The attachment repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$this->repository = app(AttachmentRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
* @codeCoverageIgnore
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function delete(Attachment $attachment): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($attachment);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download an attachment.
|
||||
*
|
||||
* @param Attachment $attachment
|
||||
* @codeCoverageIgnore
|
||||
* @return LaravelResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function download(Attachment $attachment): LaravelResponse
|
||||
{
|
||||
if (false === $attachment->uploaded) {
|
||||
throw new FireflyException('No file has been uploaded for this attachment (yet).');
|
||||
}
|
||||
if ($this->repository->exists($attachment)) {
|
||||
$content = $this->repository->getContent($attachment);
|
||||
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
|
||||
|
||||
/** @var LaravelResponse $response */
|
||||
$response = response($content);
|
||||
$response
|
||||
->header('Content-Description', 'File Transfer')
|
||||
->header('Content-Type', 'application/octet-stream')
|
||||
->header('Content-Disposition', 'attachment; filename=' . $quoted)
|
||||
->header('Content-Transfer-Encoding', 'binary')
|
||||
->header('Connection', 'Keep-Alive')
|
||||
->header('Expires', '0')
|
||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||
->header('Pragma', 'public')
|
||||
->header('Content-Length', strlen($content));
|
||||
|
||||
return $response;
|
||||
}
|
||||
throw new FireflyException('Could not find the indicated attachment. The file is no longer there.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @codeCoverageIgnore
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// get list of accounts. Count it and split it.
|
||||
$collection = $this->repository->get();
|
||||
$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.attachments.index') . $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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Attachment $attachment
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(Request $request, Attachment $attachment): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param AttachmentStoreRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function store(AttachmentStoreRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$attachment = $this->repository->store($data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param AttachmentUpdateRequest $request
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(AttachmentUpdateRequest $request, Attachment $attachment): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$this->repository->update($attachment, $data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload an attachment.
|
||||
* @codeCoverageIgnore
|
||||
* @param Request $request
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function upload(Request $request, Attachment $attachment): JsonResponse
|
||||
{
|
||||
/** @var AttachmentHelperInterface $helper */
|
||||
$helper = app(AttachmentHelperInterface::class);
|
||||
$body = $request->getContent();
|
||||
$helper->saveAttachmentFromApi($attachment, $body);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
}
|
||||
227
app/Api/V1/Controllers/AvailableBudgetController.php
Normal file
227
app/Api/V1/Controllers/AvailableBudgetController.php
Normal file
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
/**
|
||||
* AvailableBudgetController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\AvailableBudgetRequest;
|
||||
use FireflyIII\Factory\TransactionCurrencyFactory;
|
||||
use FireflyIII\Models\AvailableBudget;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Transformers\AvailableBudgetTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class AvailableBudgetController.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class AvailableBudgetController extends Controller
|
||||
{
|
||||
/** @var BudgetRepositoryInterface The budget repository */
|
||||
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);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param AvailableBudget $availableBudget
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function delete(AvailableBudget $availableBudget): JsonResponse
|
||||
{
|
||||
$this->repository->destroyAvailableBudget($availableBudget);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @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;
|
||||
|
||||
$start = $this->parameters->get('start');
|
||||
$end = $this->parameters->get('end');
|
||||
|
||||
// get list of available budgets. Count it and split it.
|
||||
$collection = $this->repository->getAvailableBudgetsByDate($start, $end);
|
||||
$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.available_budgets.index') . $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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param AvailableBudget $availableBudget
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, AvailableBudget $availableBudget): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param AvailableBudgetRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(AvailableBudgetRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
/** @var TransactionCurrencyFactory $factory */
|
||||
$factory = app(TransactionCurrencyFactory::class);
|
||||
$currency = $factory->find($data['currency_id'], $data['currency_code']);
|
||||
|
||||
if (null === $currency) {
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
}
|
||||
$availableBudget = $this->repository->setAvailableBudget($currency, $data['start'], $data['end'], $data['amount']);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var AvailableBudgetTransformer $transformer */
|
||||
$transformer = app(AvailableBudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($availableBudget, $transformer, 'available_budgets');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param AvailableBudgetRequest $request
|
||||
* @param AvailableBudget $availableBudget
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(AvailableBudgetRequest $request, AvailableBudget $availableBudget): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
|
||||
/** @var TransactionCurrencyFactory $factory */
|
||||
$factory = app(TransactionCurrencyFactory::class);
|
||||
/** @var TransactionCurrency $currency */
|
||||
$currency = $factory->find($data['currency_id'] ?? null, $data['currency_code'] ?? null);
|
||||
|
||||
if (null === $currency) {
|
||||
// use default currency:
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
}
|
||||
$currency->enabled = true;
|
||||
$currency->save();
|
||||
unset($data['currency_code']);
|
||||
$data['currency_id'] = $currency->id;
|
||||
|
||||
|
||||
$this->repository->updateAvailableBudget($availableBudget, $data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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');
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* BillController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,56 +20,111 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\BillRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\BillTransformer;
|
||||
use FireflyIII\Transformers\RuleTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Preferences;
|
||||
|
||||
/**
|
||||
* Class BillController
|
||||
* Class BillController.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class BillController extends Controller
|
||||
{
|
||||
/** @var BillRepositoryInterface */
|
||||
use TransactionFilter;
|
||||
/** @var BillRepositoryInterface The bill repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* BillController constructor.
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var BillRepositoryInterface repository */
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
$this->repository->setUser(auth()->user());
|
||||
$this->repository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @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 \FireflyIII\Models\Bill $bill
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(Bill $bill)
|
||||
public function delete(Bill $bill): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($bill);
|
||||
|
||||
@@ -81,11 +136,12 @@ class BillController extends Controller
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$pageSize = (int)Preferences::getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$paginator = $this->repository->getPaginator($pageSize);
|
||||
/** @var Collection $bills */
|
||||
$bills = $paginator->getCollection();
|
||||
@@ -94,60 +150,179 @@ class BillController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new FractalCollection($bills, new BillTransformer($this->parameters), 'bills');
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($bills, $transformer, 'bills');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Bill $bill)
|
||||
public function rules(Request $request, Bill $bill): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
// 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));
|
||||
|
||||
$resource = new Item($bill, new BillTransformer($this->parameters), 'bills');
|
||||
/** @var RuleTransformer $transformer */
|
||||
$transformer = app(RuleTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BillRequest $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function store(BillRequest $request)
|
||||
{
|
||||
$bill = $this->repository->store($request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($bill, new BillTransformer($this->parameters), 'bills');
|
||||
$resource = new FractalCollection($rules, $transformer, 'rules');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the specified bill.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Bill $bill): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($bill, $transformer, 'bills');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BillRequest $request
|
||||
* @param Bill $bill
|
||||
* Store a bill.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @param BillRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function update(BillRequest $request, Bill $bill)
|
||||
public function store(BillRequest $request): JsonResponse
|
||||
{
|
||||
$bill = $this->repository->store($request->getAll());
|
||||
if (null !== $bill) {
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($bill, $transformer, 'bills');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
throw new FireflyException('Could not store new bill.'); // @codeCoverageIgnore
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param BillRequest $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(BillRequest $request, Bill $bill): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$bill = $this->repository->update($bill, $data);
|
||||
@@ -155,7 +330,11 @@ class BillController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$resource = new Item($bill, new BillTransformer($this->parameters), 'bills');
|
||||
/** @var BillTransformer $transformer */
|
||||
$transformer = app(BillTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($bill, $transformer, 'bills');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
337
app/Api/V1/Controllers/BudgetController.php
Normal file
337
app/Api/V1/Controllers/BudgetController.php
Normal file
@@ -0,0 +1,337 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetController.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 Exception;
|
||||
use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
|
||||
use FireflyIII\Api\V1\Requests\BudgetRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||
use FireflyIII\Transformers\BudgetTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class BudgetController.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class BudgetController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var BudgetRepositoryInterface The budget repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* BudgetController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var BudgetRepositoryInterface repository */
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(Budget $budget): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($budget);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @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->getBudgets();
|
||||
$count = $collection->count();
|
||||
$budgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($budgets, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.budgets.index') . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var BudgetTransformer $transformer */
|
||||
$transformer = app(BudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($budgets, $transformer, 'budgets');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a budget.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Budget $budget): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var BudgetTransformer $transformer */
|
||||
$transformer = app(BudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($budget, $transformer, 'budgets');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a budget.
|
||||
*
|
||||
* @param BudgetRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*
|
||||
*/
|
||||
public function store(BudgetRequest $request): JsonResponse
|
||||
{
|
||||
$budget = $this->repository->store($request->getAll());
|
||||
if (null !== $budget) {
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var BudgetTransformer $transformer */
|
||||
$transformer = app(BudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($budget, $transformer, 'budgets');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
throw new FireflyException('Could not store new budget.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param BudgetLimitRequest $request
|
||||
* @param Budget $budget
|
||||
* @return JsonResponse
|
||||
* @throws Exception
|
||||
*/
|
||||
public function storeBudgetLimit(BudgetLimitRequest $request, Budget $budget): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$data['budget'] = $budget;
|
||||
$budgetLimit = $this->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.
|
||||
*
|
||||
* @param BudgetRequest $request
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(BudgetRequest $request, Budget $budget): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$budget = $this->repository->update($budget, $data);
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var BudgetTransformer $transformer */
|
||||
$transformer = app(BudgetTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($budget, $transformer, 'budgets');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
270
app/Api/V1/Controllers/BudgetLimitController.php
Normal file
270
app/Api/V1/Controllers/BudgetLimitController.php
Normal file
@@ -0,0 +1,270 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetLimitController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
|
||||
use FireflyIII\Api\V1\Requests\BudgetLimitRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class BudgetLimitController.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class BudgetLimitController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var BudgetRepositoryInterface The budget repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* BudgetLimitController 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);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param BudgetLimit $budgetLimit
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(BudgetLimit $budgetLimit): JsonResponse
|
||||
{
|
||||
$this->repository->destroyBudgetLimit($budgetLimit);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$budgetId = (int)($request->get('budget_id') ?? 0);
|
||||
$budget = $this->repository->findNull($budgetId);
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$this->parameters->set('budget_id', $budgetId);
|
||||
|
||||
$collection = new Collection;
|
||||
if (null === $budget) {
|
||||
$collection = $this->repository->getAllBudgetLimits($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
if (null !== $budget) {
|
||||
$collection = $this->repository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
|
||||
$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.budget_limits.index') . $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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param BudgetLimit $budgetLimit
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, BudgetLimit $budgetLimit): JsonResponse
|
||||
{
|
||||
$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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param BudgetLimitRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*
|
||||
*/
|
||||
public function store(BudgetLimitRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$budget = $this->repository->findNull($data['budget_id']);
|
||||
if (null === $budget) {
|
||||
throw new FireflyException('Unknown budget.');
|
||||
}
|
||||
$data['budget'] = $budget;
|
||||
$budgetLimit = $this->repository->storeBudgetLimit($data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param BudgetLimitRequest $request
|
||||
* @param BudgetLimit $budgetLimit
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(BudgetLimitRequest $request, BudgetLimit $budgetLimit): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$data['budget'] = $budgetLimit->budget;
|
||||
$budgetLimit = $this->repository->updateBudgetLimit($budgetLimit, $data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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');
|
||||
|
||||
}
|
||||
}
|
||||
268
app/Api/V1/Controllers/CategoryController.php
Normal file
268
app/Api/V1/Controllers/CategoryController.php
Normal file
@@ -0,0 +1,268 @@
|
||||
<?php
|
||||
/**
|
||||
* CategoryController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\CategoryRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\CategoryTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class CategoryController.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var CategoryRepositoryInterface The category repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* CategoryController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CategoryRepositoryInterface repository */
|
||||
$this->repository = app(CategoryRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param Category $category
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(Category $category): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($category);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @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->getCategories();
|
||||
$count = $collection->count();
|
||||
$categories = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($categories, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.categories.index') . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var CategoryTransformer $transformer */
|
||||
$transformer = app(CategoryTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
|
||||
$resource = new FractalCollection($categories, $transformer, 'categories');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the category.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Category $category
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Category $category): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var CategoryTransformer $transformer */
|
||||
$transformer = app(CategoryTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($category, $transformer, 'categories');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store new category.
|
||||
*
|
||||
* @param CategoryRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function store(CategoryRequest $request): JsonResponse
|
||||
{
|
||||
$category = $this->repository->store($request->getAll());
|
||||
if (null !== $category) {
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var CategoryTransformer $transformer */
|
||||
$transformer = app(CategoryTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($category, $transformer, 'categories');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
throw new FireflyException('Could not store new category.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @param Category $category
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function transactions(Request $request, Category $category): JsonResponse
|
||||
{
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$this->parameters->set('type', $type);
|
||||
|
||||
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||
$manager = 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.
|
||||
*
|
||||
* @param CategoryRequest $request
|
||||
* @param Category $category
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(CategoryRequest $request, Category $category): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$category = $this->repository->update($category, $data);
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var CategoryTransformer $transformer */
|
||||
$transformer = app(CategoryTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($category, $transformer, 'categories');
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
120
app/Api/V1/Controllers/ConfigurationController.php
Normal file
120
app/Api/V1/Controllers/ConfigurationController.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/**
|
||||
* ConfigurationController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\ConfigurationRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Configuration;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
* Class ConfigurationController.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ConfigurationController extends Controller
|
||||
{
|
||||
|
||||
|
||||
/** @var UserRepositoryInterface The user repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* ConfigurationController constructor.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @noinspection UnusedConstructorDependenciesInspection */
|
||||
$this->repository = app(UserRepositoryInterface::class);
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
if (!$this->repository->hasRole($admin, 'owner')) {
|
||||
throw new FireflyException('No access to method.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all configuration.
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
$configData = $this->getConfigData();
|
||||
|
||||
return response()->json(['data' => $configData])->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the configuration.
|
||||
*
|
||||
* @param ConfigurationRequest $request
|
||||
* @param string $name
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(ConfigurationRequest $request, string $name): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
app('fireflyconfig')->set($name, $data['value']);
|
||||
$configData = $this->getConfigData();
|
||||
|
||||
return response()->json(['data' => $configData])->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all config values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getConfigData(): array
|
||||
{
|
||||
/** @var Configuration $isDemoSite */
|
||||
$isDemoSite = app('fireflyconfig')->get('is_demo_site');
|
||||
/** @var Configuration $updateCheck */
|
||||
$updateCheck = app('fireflyconfig')->get('permission_update_check');
|
||||
/** @var Configuration $lastCheck */
|
||||
$lastCheck = app('fireflyconfig')->get('last_update_check');
|
||||
/** @var Configuration $singleUser */
|
||||
$singleUser = app('fireflyconfig')->get('single_user_mode');
|
||||
$data = [
|
||||
'is_demo_site' => null === $isDemoSite ? null : $isDemoSite->data,
|
||||
'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data,
|
||||
'last_update_check' => null === $lastCheck ? null : (int)$lastCheck->data,
|
||||
'single_user_mode' => null === $singleUser ? null : $singleUser->data,
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Controller.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,12 +20,12 @@ declare(strict_types=1);
|
||||
* 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 Carbon\Exceptions\InvalidDateException;
|
||||
use FireflyConfig;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
@@ -37,67 +37,60 @@ use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
* Class Controller.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
*/
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
|
||||
/** @var ParameterBag */
|
||||
/** @var ParameterBag Parameters from the URI are stored here. */
|
||||
protected $parameters;
|
||||
|
||||
/**
|
||||
* Controller constructor.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// is site a demo site?
|
||||
$isDemoSite = FireflyConfig::get('is_demo_site', config('firefly.configuration.is_demo_site'))->data;
|
||||
|
||||
// do not expose API on demo site:
|
||||
if (true === $isDemoSite) {
|
||||
throw new FireflyException('The API is not available on the demo site.');
|
||||
}
|
||||
|
||||
// get global parameters
|
||||
$this->parameters = $this->getParameters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to help build URI's.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
protected function buildParams(): string
|
||||
{
|
||||
$return = '?';
|
||||
$params = [];
|
||||
foreach ($this->parameters as $key => $value) {
|
||||
if ($key === 'page') {
|
||||
if ('page' === $key) {
|
||||
continue;
|
||||
}
|
||||
if ($value instanceof Carbon) {
|
||||
$params[$key] = $value->format('Y-m-d');
|
||||
continue;
|
||||
}
|
||||
if (!$value instanceof Carbon) {
|
||||
$params[$key] = $value;
|
||||
}
|
||||
$params[$key] = $value;
|
||||
}
|
||||
$return .= http_build_query($params);
|
||||
if (strlen($return) === 1) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to grab all parameters from the URI.
|
||||
*
|
||||
* @return ParameterBag
|
||||
*/
|
||||
private function getParameters(): ParameterBag
|
||||
{
|
||||
$bag = new ParameterBag;
|
||||
$page = (int)request()->get('page');
|
||||
if ($page === 0) {
|
||||
if (0 === $page) {
|
||||
$page = 1;
|
||||
}
|
||||
$bag->set('page', $page);
|
||||
@@ -105,11 +98,11 @@ class Controller extends BaseController
|
||||
// some date fields:
|
||||
$dates = ['start', 'end', 'date'];
|
||||
foreach ($dates as $field) {
|
||||
$date = request()->get($field);
|
||||
$date = request()->query->get($field);
|
||||
$obj = null;
|
||||
if (null !== $date) {
|
||||
try {
|
||||
$obj = new Carbon($date);
|
||||
$obj = Carbon::parse($date);
|
||||
} catch (InvalidDateException $e) {
|
||||
// don't care
|
||||
Log::error(sprintf('Invalid date exception in API controller: %s', $e->getMessage()));
|
||||
@@ -118,6 +111,15 @@ class Controller extends BaseController
|
||||
$bag->set($field, $obj);
|
||||
}
|
||||
|
||||
// integer fields:
|
||||
$integers = ['limit'];
|
||||
foreach ($integers as $integer) {
|
||||
$value = request()->query->get($integer);
|
||||
if (null !== $value) {
|
||||
$bag->set($integer, (int)$value);
|
||||
}
|
||||
}
|
||||
|
||||
return $bag;
|
||||
|
||||
}
|
||||
|
||||
749
app/Api/V1/Controllers/CurrencyController.php
Normal file
749
app/Api/V1/Controllers/CurrencyController.php
Normal file
@@ -0,0 +1,749 @@
|
||||
<?php
|
||||
/**
|
||||
* CurrencyController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\CurrencyRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Models\RecurrenceTransaction;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleTrigger;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\AvailableBudgetTransformer;
|
||||
use FireflyIII\Transformers\BillTransformer;
|
||||
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||
use FireflyIII\Transformers\CurrencyExchangeRateTransformer;
|
||||
use FireflyIII\Transformers\CurrencyTransformer;
|
||||
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||
use FireflyIII\Transformers\RuleTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use 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 CurrencyController.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class CurrencyController extends Controller
|
||||
{
|
||||
use AccountFilter, TransactionFilter;
|
||||
/** @var CurrencyRepositoryInterface The currency repository */
|
||||
private $repository;
|
||||
/** @var UserRepositoryInterface The user repository */
|
||||
private $userRepository;
|
||||
|
||||
/**
|
||||
* CurrencyRepository constructor.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CurrencyRepositoryInterface repository */
|
||||
$this->repository = app(CurrencyRepositoryInterface::class);
|
||||
$this->userRepository = app(UserRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
if (!$this->userRepository->hasRole($admin, 'owner')) {
|
||||
// access denied:
|
||||
throw new FireflyException('No access to method, user is not owner.'); // @codeCoverageIgnore
|
||||
}
|
||||
if ($this->repository->currencyInUse($currency)) {
|
||||
throw new FireflyException('No access to method, currency is in use.'); // @codeCoverageIgnore
|
||||
}
|
||||
$this->repository->destroy($currency);
|
||||
|
||||
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.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$collection = $this->repository->getAll();
|
||||
$count = $collection->count();
|
||||
// slice them:
|
||||
$currencies = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
$paginator = new LengthAwarePaginator($currencies, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.currencies.index') . $this->buildParams());
|
||||
|
||||
|
||||
$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 FractalCollection($currencies, $transformer, 'currencies');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the currency a default currency.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @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.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store new currency.
|
||||
*
|
||||
* @param CurrencyRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function store(CurrencyRequest $request): JsonResponse
|
||||
{
|
||||
$currency = $this->repository->store($request->getAll());
|
||||
|
||||
if (null !== $currency) {
|
||||
if (true === $request->boolean('default')) {
|
||||
app('preferences')->set('currencyPreference', $currency->code);
|
||||
app('preferences')->mark();
|
||||
}
|
||||
$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');
|
||||
}
|
||||
throw new FireflyException('Could not store new currency.'); // @codeCoverageIgnore
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param CurrencyRequest $request
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(CurrencyRequest $request, TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$currency = $this->repository->update($currency, $data);
|
||||
|
||||
if (true === $request->boolean('default')) {
|
||||
app('preferences')->set('currencyPreference', $currency->code);
|
||||
app('preferences')->mark();
|
||||
}
|
||||
|
||||
$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');
|
||||
|
||||
}
|
||||
}
|
||||
117
app/Api/V1/Controllers/CurrencyExchangeRateController.php
Normal file
117
app/Api/V1/Controllers/CurrencyExchangeRateController.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
/**
|
||||
* CurrencyExchangeRateController.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\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Services\Currency\ExchangeRateInterface;
|
||||
use FireflyIII\Transformers\CurrencyExchangeRateTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class CurrencyExchangeRateController
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class CurrencyExchangeRateController extends Controller
|
||||
{
|
||||
/** @var CurrencyRepositoryInterface The currency repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* CurrencyExchangeRateController constructor.
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
$this->repository = app(CurrencyRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an exchange rate.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$fromCurrency = $this->repository->findByCodeNull($request->get('from') ?? 'EUR');
|
||||
$toCurrency = $this->repository->findByCodeNull($request->get('to') ?? 'USD');
|
||||
|
||||
if (null === $fromCurrency) {
|
||||
throw new FireflyException('Unknown source currency.');
|
||||
}
|
||||
if (null === $toCurrency) {
|
||||
throw new FireflyException('Unknown destination currency.');
|
||||
}
|
||||
|
||||
/** @var Carbon $dateObj */
|
||||
$dateObj = Carbon::createFromFormat('Y-m-d', $request->get('date') ?? date('Y-m-d'));
|
||||
$this->parameters->set('from', $fromCurrency->code);
|
||||
$this->parameters->set('to', $toCurrency->code);
|
||||
$this->parameters->set('date', $dateObj->format('Y-m-d'));
|
||||
$this->parameters->set('amount', $request->get('amount'));
|
||||
|
||||
$rate = $this->repository->getExchangeRate($fromCurrency, $toCurrency, $dateObj);
|
||||
if (null === $rate) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
// create service:
|
||||
/** @var ExchangeRateInterface $service */
|
||||
$service = app(ExchangeRateInterface::class);
|
||||
$service->setUser($admin);
|
||||
$rate = $service->getRate($fromCurrency, $toCurrency, $dateObj);
|
||||
}
|
||||
/** @var CurrencyExchangeRateTransformer $transformer */
|
||||
$transformer = app(CurrencyExchangeRateTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($rate, $transformer, 'currency_exchange_rates');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
}
|
||||
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');
|
||||
}
|
||||
|
||||
}
|
||||
291
app/Api/V1/Controllers/LinkTypeController.php
Normal file
291
app/Api/V1/Controllers/LinkTypeController.php
Normal file
@@ -0,0 +1,291 @@
|
||||
<?php
|
||||
/**
|
||||
* LinkTypeController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\LinkTypeRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\LinkType;
|
||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\LinkTypeTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class LinkTypeController.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class LinkTypeController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var LinkTypeRepositoryInterface The link type repository */
|
||||
private $repository;
|
||||
|
||||
/** @var UserRepositoryInterface The user repository */
|
||||
private $userRepository;
|
||||
|
||||
/**
|
||||
* LinkTypeController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$this->repository = app(LinkTypeRepositoryInterface::class);
|
||||
$this->userRepository = app(UserRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the resource.
|
||||
*
|
||||
* @param LinkType $linkType
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(LinkType $linkType): JsonResponse
|
||||
{
|
||||
if (false === $linkType->editable) {
|
||||
throw new FireflyException(sprintf('You cannot delete this link type (#%d, "%s")', $linkType->id, $linkType->name));
|
||||
}
|
||||
$this->repository->destroy($linkType);
|
||||
|
||||
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';
|
||||
$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();
|
||||
$linkTypes = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($linkTypes, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.link_types.index') . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var LinkTypeTransformer $transformer */
|
||||
$transformer = app(LinkTypeTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($linkTypes, $transformer, 'link_types');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param LinkType $linkType
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, LinkType $linkType): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
/** @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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Store new object.
|
||||
*
|
||||
* @param LinkTypeRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function store(LinkTypeRequest $request): JsonResponse
|
||||
{
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
if (!$this->userRepository->hasRole($admin, 'owner')) {
|
||||
throw new FireflyException('You need the "owner"-role to do this.');
|
||||
}
|
||||
$data = $request->getAll();
|
||||
// if currency ID is 0, find the currency by the code:
|
||||
$linkType = $this->repository->store($data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var LinkTypeTransformer $transformer */
|
||||
$transformer = app(LinkTypeTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($linkType, $transformer, 'link_types');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param LinkType $linkType
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function transactions(Request $request, LinkType $linkType): JsonResponse
|
||||
{
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$this->parameters->set('type', $type);
|
||||
|
||||
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||
$manager = 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.
|
||||
*
|
||||
* @param LinkTypeRequest $request
|
||||
* @param LinkType $linkType
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function update(LinkTypeRequest $request, LinkType $linkType): JsonResponse
|
||||
{
|
||||
if (false === $linkType->editable) {
|
||||
throw new FireflyException(sprintf('You cannot edit this link type (#%d, "%s")', $linkType->id, $linkType->name));
|
||||
}
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
if (!$this->userRepository->hasRole($admin, 'owner')) {
|
||||
throw new FireflyException('You need the "owner"-role to do this.');
|
||||
}
|
||||
|
||||
$data = $request->getAll();
|
||||
$this->repository->update($linkType, $data);
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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');
|
||||
|
||||
}
|
||||
}
|
||||
243
app/Api/V1/Controllers/PiggyBankController.php
Normal file
243
app/Api/V1/Controllers/PiggyBankController.php
Normal file
@@ -0,0 +1,243 @@
|
||||
<?php
|
||||
/**
|
||||
* PiggyBankController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\PiggyBankRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Transformers\PiggyBankEventTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class PiggyBankController.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class PiggyBankController extends Controller
|
||||
{
|
||||
|
||||
/** @var PiggyBankRepositoryInterface The piggy bank repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* PiggyBankController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
$this->repository = app(PiggyBankRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the resource.
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($piggyBank);
|
||||
|
||||
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->getPiggyBanks();
|
||||
$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.piggy_banks.index') . $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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @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
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Store new object.
|
||||
*
|
||||
* @param PiggyBankRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function store(PiggyBankRequest $request): JsonResponse
|
||||
{
|
||||
$piggyBank = $this->repository->store($request->getAll());
|
||||
if (null !== $piggyBank) {
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var PiggyBankTransformer $transformer */
|
||||
$transformer = app(PiggyBankTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($piggyBank, $transformer, 'piggy_banks');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
throw new FireflyException('Could not store new piggy bank.');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update piggy bank.
|
||||
*
|
||||
* @param PiggyBankRequest $request
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(PiggyBankRequest $request, PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
$piggyBank = $this->repository->update($piggyBank, $request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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');
|
||||
|
||||
}
|
||||
}
|
||||
189
app/Api/V1/Controllers/PreferenceController.php
Normal file
189
app/Api/V1/Controllers/PreferenceController.php
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
/**
|
||||
* PreferencesController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\PreferenceRequest;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Transformers\PreferenceTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class PreferenceController
|
||||
*/
|
||||
class PreferenceController extends Controller
|
||||
{
|
||||
/**
|
||||
* LinkTypeController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
static function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser($user);
|
||||
|
||||
// an important fallback is that the frontPageAccount array gets refilled automatically
|
||||
// when it turns up empty.
|
||||
$frontPageAccounts = app('preferences')->getForUser($user, 'frontPageAccounts', [])->data;
|
||||
if (0 === count($frontPageAccounts)) {
|
||||
/** @var Collection $accounts */
|
||||
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
$accountIds = $accounts->pluck('id')->toArray();
|
||||
app('preferences')->setForUser($user, 'frontPageAccounts', $accountIds);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all of them.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$available = [
|
||||
'language', 'customFiscalYear', 'fiscalYearStart', 'currencyPreference',
|
||||
'transaction_journal_optional_fields', 'frontPageAccounts', 'viewRange',
|
||||
'listPageSize',
|
||||
];
|
||||
|
||||
$preferences = new Collection;
|
||||
foreach ($available as $name) {
|
||||
$pref = app('preferences')->getForUser($user, $name);
|
||||
if (null !== $pref) {
|
||||
$preferences->push($pref);
|
||||
}
|
||||
}
|
||||
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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 a single preference by name.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Preference $preference
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Preference $preference): JsonResponse
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
/** @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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a preference.
|
||||
*
|
||||
* @param PreferenceRequest $request
|
||||
* @param Preference $preference
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(PreferenceRequest $request, Preference $preference): JsonResponse
|
||||
{
|
||||
|
||||
$data = $request->getAll();
|
||||
$newValue = $data['data'];
|
||||
switch ($preference->name) {
|
||||
default:
|
||||
break;
|
||||
case 'transaction_journal_optional_fields':
|
||||
case 'frontPageAccounts':
|
||||
$newValue = explode(',', $data['data']);
|
||||
break;
|
||||
case 'listPageSize':
|
||||
$newValue = (int)$data['data'];
|
||||
break;
|
||||
case 'customFiscalYear':
|
||||
$newValue = 1 === (int)$data['data'];
|
||||
break;
|
||||
}
|
||||
$result = app('preferences')->set($preference->name, $newValue);
|
||||
|
||||
// create some objects:
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
/** @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');
|
||||
|
||||
}
|
||||
}
|
||||
290
app/Api/V1/Controllers/RecurrenceController.php
Normal file
290
app/Api/V1/Controllers/RecurrenceController.php
Normal file
@@ -0,0 +1,290 @@
|
||||
<?php
|
||||
/**
|
||||
* RecurrenceController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\RecurrenceStoreRequest;
|
||||
use FireflyIII\Api\V1\Requests\RecurrenceUpdateRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\Cronjobs\RecurringCronjob;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\RecurrenceTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RecurrenceController
|
||||
*/
|
||||
class RecurrenceController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
/** @var RecurringRepositoryInterface The recurring transaction repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* RecurrenceController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
/** @var RecurringRepositoryInterface repository */
|
||||
$this->repository = app(RecurringRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the resource.
|
||||
*
|
||||
* @param Recurrence $recurrence
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(Recurrence $recurrence): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($recurrence);
|
||||
|
||||
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->getAll();
|
||||
$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.recurrences.index') . $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 single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Recurrence $recurrence
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Recurrence $recurrence): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($recurrence, $transformer, 'recurrences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Store new object.
|
||||
*
|
||||
* @param RecurrenceStoreRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(RecurrenceStoreRequest $request): JsonResponse
|
||||
{
|
||||
$recurrence = $this->repository->store($request->getAllRecurrenceData());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($recurrence, $transformer, 'recurrences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show transactions for this recurrence.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Recurrence $recurrence
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function transactions(Request $request, Recurrence $recurrence): JsonResponse
|
||||
{
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$this->parameters->set('type', $type);
|
||||
|
||||
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||
$manager = 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.
|
||||
*
|
||||
* @param RecurrenceUpdateRequest $request
|
||||
* @param Recurrence $recurrence
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(RecurrenceUpdateRequest $request, Recurrence $recurrence): JsonResponse
|
||||
{
|
||||
$data = $request->getAllRecurrenceData();
|
||||
$category = $this->repository->update($recurrence, $data);
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
/** @var RecurrenceTransformer $transformer */
|
||||
$transformer = app(RecurrenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($category, $transformer, 'recurrences');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
}
|
||||
338
app/Api/V1/Controllers/RuleController.php
Normal file
338
app/Api/V1/Controllers/RuleController.php
Normal file
@@ -0,0 +1,338 @@
|
||||
<?php
|
||||
/**
|
||||
* RuleController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\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\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\TransactionRules\Engine\RuleEngine;
|
||||
use FireflyIII\TransactionRules\TransactionMatcher;
|
||||
use FireflyIII\Transformers\RuleTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RuleController
|
||||
*
|
||||
*/
|
||||
class RuleController extends Controller
|
||||
{
|
||||
/** @var AccountRepositoryInterface Account repository */
|
||||
private $accountRepository;
|
||||
/** @var RuleRepositoryInterface The rule repository */
|
||||
private $ruleRepository;
|
||||
|
||||
/**
|
||||
* RuleController constructor.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
$this->ruleRepository = app(RuleRepositoryInterface::class);
|
||||
$this->ruleRepository->setUser($user);
|
||||
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
$this->accountRepository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the resource.
|
||||
*
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(Rule $rule): JsonResponse
|
||||
{
|
||||
$this->ruleRepository->destroy($rule);
|
||||
|
||||
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->ruleRepository->getAll();
|
||||
$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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Rule $rule): JsonResponse
|
||||
{
|
||||
$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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Store new object.
|
||||
*
|
||||
* @param RuleRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(RuleRequest $request): JsonResponse
|
||||
{
|
||||
$rule = $this->ruleRepository->store($request->getAll());
|
||||
$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 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.
|
||||
*
|
||||
* @param RuleRequest $request
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(RuleRequest $request, Rule $rule): JsonResponse
|
||||
{
|
||||
$rule = $this->ruleRepository->update($rule, $request->getAll());
|
||||
|
||||
$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 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');
|
||||
|
||||
}
|
||||
}
|
||||
400
app/Api/V1/Controllers/RuleGroupController.php
Normal file
400
app/Api/V1/Controllers/RuleGroupController.php
Normal file
@@ -0,0 +1,400 @@
|
||||
<?php
|
||||
/**
|
||||
* RuleGroupController.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 Exception;
|
||||
use FireflyIII\Api\V1\Requests\RuleGroupRequest;
|
||||
use FireflyIII\Api\V1\Requests\RuleGroupTestRequest;
|
||||
use FireflyIII\Api\V1\Requests\RuleGroupTriggerRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
use FireflyIII\TransactionRules\Engine\RuleEngine;
|
||||
use FireflyIII\TransactionRules\TransactionMatcher;
|
||||
use FireflyIII\Transformers\RuleGroupTransformer;
|
||||
use FireflyIII\Transformers\RuleTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RuleGroupController
|
||||
*/
|
||||
class RuleGroupController extends Controller
|
||||
{
|
||||
/** @var AccountRepositoryInterface Account repository */
|
||||
private $accountRepository;
|
||||
/** @var RuleGroupRepositoryInterface The rule group repository */
|
||||
private $ruleGroupRepository;
|
||||
|
||||
/**
|
||||
* RuleGroupController constructor.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
$this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
|
||||
$this->ruleGroupRepository->setUser($user);
|
||||
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
$this->accountRepository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the resource.
|
||||
*
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(RuleGroup $ruleGroup): JsonResponse
|
||||
{
|
||||
$this->ruleGroupRepository->destroy($ruleGroup, null);
|
||||
|
||||
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 rule groups. Count it and split it.
|
||||
$collection = $this->ruleGroupRepository->get();
|
||||
$count = $collection->count();
|
||||
$ruleGroups = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($ruleGroups, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.rule_groups.index') . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var RuleGroupTransformer $transformer */
|
||||
$transformer = app(RuleGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($ruleGroups, $transformer, 'rule_groups');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param RuleGroup $group
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @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.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, RuleGroup $ruleGroup): JsonResponse
|
||||
{
|
||||
$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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Store new object.
|
||||
*
|
||||
* @param RuleGroupRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(RuleGroupRequest $request): JsonResponse
|
||||
{
|
||||
$ruleGroup = $this->ruleGroupRepository->store($request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var RuleGroupTransformer $transformer */
|
||||
$transformer = app(RuleGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($ruleGroup, $transformer, 'rule_groups');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RuleGroupTestRequest $request
|
||||
* @param RuleGroup $group
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*
|
||||
*/
|
||||
public function testGroup(RuleGroupTestRequest $request, RuleGroup $group): JsonResponse
|
||||
{
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
Log::debug('Now in testGroup()');
|
||||
/** @var Collection $rules */
|
||||
$rules = $this->ruleGroupRepository->getActiveRules($group);
|
||||
if (0 === $rules->count()) {
|
||||
throw new FireflyException('No rules in this rule group.');
|
||||
}
|
||||
$parameters = $request->getTestParameters();
|
||||
$matchingTransactions = [];
|
||||
|
||||
Log::debug(sprintf('Going to test %d rules', $rules->count()));
|
||||
/** @var Rule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
Log::debug(sprintf('Now testing rule #%d, "%s"', $rule->id, $rule->title));
|
||||
/** @var TransactionMatcher $matcher */
|
||||
$matcher = app(TransactionMatcher::class);
|
||||
// set all parameters:
|
||||
$matcher->setRule($rule);
|
||||
$matcher->setStartDate($parameters['start_date']);
|
||||
$matcher->setEndDate($parameters['end_date']);
|
||||
$matcher->setSearchLimit($parameters['search_limit']);
|
||||
$matcher->setTriggeredLimit($parameters['trigger_limit']);
|
||||
$matcher->setAccounts($parameters['accounts']);
|
||||
|
||||
$result = $matcher->findTransactionsByRule();
|
||||
/** @noinspection AdditionOperationOnArraysInspection */
|
||||
$matchingTransactions = $result + $matchingTransactions;
|
||||
}
|
||||
|
||||
// make paginator out of results.
|
||||
$count = count($matchingTransactions);
|
||||
$transactions = array_slice($matchingTransactions, ($parameters['page'] - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($transactions, $count, $pageSize, $parameters['page']);
|
||||
$paginator->setPath(route('api.v1.rule_groups.test', [$group->id]) . $this->buildParams());
|
||||
|
||||
// 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.
|
||||
*
|
||||
* @param RuleGroupRequest $request
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(RuleGroupRequest $request, RuleGroup $ruleGroup): JsonResponse
|
||||
{
|
||||
$ruleGroup = $this->ruleGroupRepository->update($ruleGroup, $request->getAll());
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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 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;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* TransactionController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,315 +20,339 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\TransactionRequest;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
use FireflyIII\Helpers\Filter\NegativeAmountFilter;
|
||||
use FireflyIII\Helpers\Filter\PositiveAmountFilter;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Api\V1\Requests\TransactionStoreRequest;
|
||||
use FireflyIII\Api\V1\Requests\TransactionUpdateRequest;
|
||||
use FireflyIII\Events\StoredTransactionGroup;
|
||||
use FireflyIII\Events\UpdatedTransactionGroup;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Journal\JournalAPIRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Transformers\TransactionTransformer;
|
||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankEventTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Log;
|
||||
use Preferences;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* Class TransactionController
|
||||
*/
|
||||
class TransactionController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
|
||||
/** @var JournalRepositoryInterface */
|
||||
/** @var TransactionGroupRepositoryInterface Group repository. */
|
||||
private $groupRepository;
|
||||
/** @var JournalRepositoryInterface The journal repository */
|
||||
private $repository;
|
||||
|
||||
/** @var JournalAPIRepositoryInterface Journal API repos */
|
||||
private $journalAPIRepository;
|
||||
|
||||
/**
|
||||
* TransactionController constructor.
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var JournalRepositoryInterface repository */
|
||||
$this->repository = app(JournalRepositoryInterface::class);
|
||||
$this->repository->setUser(auth()->user());
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
$this->repository = app(JournalRepositoryInterface::class);
|
||||
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
|
||||
$this->journalAPIRepository = app(JournalAPIRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->groupRepository->setUser($admin);
|
||||
$this->journalAPIRepository->setUser($admin);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param TransactionJournal $transactionJournal
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function attachments(Request $request, TransactionJournal $transactionJournal): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$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 \FireflyIII\Models\Transaction $transaction
|
||||
* @param TransactionGroup $transactionGroup
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(Transaction $transaction)
|
||||
public function delete(TransactionGroup $transactionGroup): JsonResponse
|
||||
{
|
||||
$journal = $transaction->transactionJournal;
|
||||
$this->repository->destroy($journal);
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all transactions.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$pageSize = (int)Preferences::getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// read type from URI
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$this->parameters->set('type', $type);
|
||||
|
||||
// types to get, page size:
|
||||
$types = $this->mapTypes($this->parameters->get('type'));
|
||||
|
||||
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// collect transactions using the journal collector
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setUser(auth()->user());
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
$collector->setAllAssetAccounts();
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
// set page size:
|
||||
->setLimit($pageSize)
|
||||
// set page to retrieve
|
||||
->setPage($this->parameters->get('page'))
|
||||
// set types of transactions to return.
|
||||
->setTypes($types);
|
||||
|
||||
// remove internal transfer filter:
|
||||
if (in_array(TransactionType::TRANSFER, $types)) {
|
||||
$collector->removeFilter(InternalTransferFilter::class);
|
||||
}
|
||||
|
||||
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
|
||||
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
|
||||
}
|
||||
$collector->setLimit($pageSize)->setPage($this->parameters->get('page'));
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedJournals();
|
||||
$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, new TransactionTransformer($this->parameters), 'transactions');
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Transaction $transaction
|
||||
* @param Request $request
|
||||
* @param TransactionJournal $transactionJournal
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, Transaction $transaction)
|
||||
public function piggyBankEvents(Request $request, TransactionJournal $transactionJournal): JsonResponse
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
$events = $this->journalAPIRepository->getPiggyBankEvents($transactionJournal);
|
||||
|
||||
// collect transactions using the journal collector
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setUser(auth()->user());
|
||||
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
|
||||
// filter on specific journals.
|
||||
$collector->setJournals(new Collection([$transaction->transactionJournal]));
|
||||
/** @var PiggyBankEventTransformer $transformer */
|
||||
$transformer = app(PiggyBankEventTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
// add filter to remove transactions:
|
||||
$transactionType = $transaction->transactionJournal->transactionType->type;
|
||||
if ($transactionType === TransactionType::WITHDRAWAL) {
|
||||
$collector->addFilter(PositiveAmountFilter::class);
|
||||
}
|
||||
if (!($transactionType === TransactionType::WITHDRAWAL)) {
|
||||
$collector->addFilter(NegativeAmountFilter::class);
|
||||
}
|
||||
|
||||
$transactions = $collector->getJournals();
|
||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
||||
$resource = new FractalCollection($events, $transformer, 'piggy_bank_events');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionRequest $request
|
||||
* Show a single transaction.
|
||||
*
|
||||
* @param JournalRepositoryInterface $repository
|
||||
* @param Request $request
|
||||
* @param TransactionGroup $transactionGroup
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function store(TransactionRequest $request, JournalRepositoryInterface $repository)
|
||||
public function show(Request $request, TransactionGroup $transactionGroup): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$data['user'] = auth()->user()->id;
|
||||
$journal = $repository->store($data);
|
||||
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
/** @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();
|
||||
|
||||
// collect transactions using the journal collector
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setUser(auth()->user());
|
||||
$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);
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
if (null === $selectedGroup) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
if (!($transactionType === TransactionType::WITHDRAWAL)) {
|
||||
$collector->addFilter(NegativeAmountFilter::class);
|
||||
}
|
||||
|
||||
$transactions = $collector->getJournals();
|
||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param TransactionRequest $request
|
||||
* @param JournalRepositoryInterface $repository
|
||||
* @param Transaction $transaction
|
||||
* Store a new transaction.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @param TransactionStoreRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function update(TransactionRequest $request, JournalRepositoryInterface $repository, Transaction $transaction)
|
||||
public function store(TransactionStoreRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$data['user'] = auth()->user()->id;
|
||||
|
||||
Log::debug('Inside transaction update');
|
||||
Log::channel('audit')
|
||||
->info('Store new transaction over API.', $data);
|
||||
|
||||
$journal = $repository->update($transaction->transactionJournal, $data);
|
||||
$transactionGroup = $this->groupRepository->store($data);
|
||||
|
||||
event(new StoredTransactionGroup($transactionGroup));
|
||||
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
/** @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();
|
||||
|
||||
// needs a lot of extra data to match the journal collector. Or just expand that one.
|
||||
// collect transactions using the journal collector
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setUser(auth()->user());
|
||||
$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);
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
if (null === $selectedGroup) {
|
||||
throw new NotFoundHttpException(); // @codeCoverageIgnore
|
||||
}
|
||||
if (!($transactionType === TransactionType::WITHDRAWAL)) {
|
||||
$collector->addFilter(NegativeAmountFilter::class);
|
||||
}
|
||||
|
||||
$transactions = $collector->getJournals();
|
||||
$resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions');
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @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,
|
||||
],
|
||||
];
|
||||
if (isset($types[$type])) {
|
||||
return $types[$type];
|
||||
}
|
||||
|
||||
return $types['default']; // @codeCoverageIgnore
|
||||
/**
|
||||
* Update a transaction.
|
||||
*
|
||||
* @param TransactionUpdateRequest $request
|
||||
* @param TransactionGroup $transactionGroup
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(TransactionUpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
||||
{
|
||||
Log::debug('Now in update routine.');
|
||||
$data = $request->getAll();
|
||||
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
event(new UpdatedTransactionGroup($transactionGroup));
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// filter on transaction group.
|
||||
->setTransactionGroup($transactionGroup)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation();
|
||||
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
if (null === $selectedGroup) {
|
||||
throw new NotFoundHttpException(); // @codeCoverageIgnore
|
||||
}
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
223
app/Api/V1/Controllers/TransactionLinkController.php
Normal file
223
app/Api/V1/Controllers/TransactionLinkController.php
Normal file
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
/**
|
||||
* TransactionLinkController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\TransactionLinkRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionJournalLink;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\TransactionLinkTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
|
||||
/**
|
||||
* Class TransactionLinkController
|
||||
*/
|
||||
class TransactionLinkController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
|
||||
/** @var JournalRepositoryInterface The journal repository */
|
||||
private $journalRepository;
|
||||
/** @var LinkTypeRepositoryInterface The link type repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* TransactionLinkController constructor.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
$this->repository = app(LinkTypeRepositoryInterface::class);
|
||||
$this->journalRepository = app(JournalRepositoryInterface::class);
|
||||
|
||||
$this->repository->setUser($user);
|
||||
$this->journalRepository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the resource.
|
||||
*
|
||||
* @param TransactionJournalLink $link
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(TransactionJournalLink $link): JsonResponse
|
||||
{
|
||||
$this->repository->destroyLink($link);
|
||||
|
||||
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';
|
||||
|
||||
// read type from URI
|
||||
$name = $request->get('name');
|
||||
|
||||
// types to get, page size:
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$linkType = $this->repository->findByName($name);
|
||||
|
||||
// get list of transaction links. Count it and split it.
|
||||
$collection = $this->repository->getJournalLinks($linkType);
|
||||
$count = $collection->count();
|
||||
$journalLinks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($journalLinks, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.transaction_links.index') . $this->buildParams());
|
||||
|
||||
// present to user.
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @var TransactionLinkTransformer $transformer */
|
||||
$transformer = app(TransactionLinkTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($journalLinks, $transformer, 'transaction_links');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List single resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param TransactionJournalLink $journalLink
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, TransactionJournalLink $journalLink): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
/** @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');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Store new object.
|
||||
*
|
||||
* @param TransactionLinkRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function store(TransactionLinkRequest $request): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$data = $request->getAll();
|
||||
$inward = $this->journalRepository->findNull($data['inward_id'] ?? 0);
|
||||
$outward = $this->journalRepository->findNull($data['outward_id'] ?? 0);
|
||||
if (null === $inward || null === $outward) {
|
||||
throw new FireflyException('Source or destination is NULL.');
|
||||
}
|
||||
$data['direction'] = 'inward';
|
||||
|
||||
$journalLink = $this->repository->storeLink($data, $inward, $outward);
|
||||
|
||||
/** @var TransactionLinkTransformer $transformer */
|
||||
$transformer = app(TransactionLinkTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($journalLink, $transformer, 'transaction_links');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object.
|
||||
*
|
||||
* @param TransactionLinkRequest $request
|
||||
* @param TransactionJournalLink $journalLink
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function update(TransactionLinkRequest $request, TransactionJournalLink $journalLink): JsonResponse
|
||||
{
|
||||
$manager = new Manager;
|
||||
$data = $request->getAll();
|
||||
$data['inward'] = $this->journalRepository->findNull($data['inward_id'] ?? 0);
|
||||
$data['outward'] = $this->journalRepository->findNull($data['outward_id'] ?? 0);
|
||||
if (null === $data['inward'] || null === $data['outward']) {
|
||||
throw new FireflyException('Source or destination is NULL.');
|
||||
}
|
||||
$data['direction'] = 'inward';
|
||||
$journalLink = $this->repository->updateLink($journalLink, $data);
|
||||
|
||||
/** @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');
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* UserController.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,13 +20,16 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\UserRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Transformers\UserTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Manager;
|
||||
@@ -34,22 +37,22 @@ use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Preferences;
|
||||
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
|
||||
|
||||
|
||||
/**
|
||||
* Class UserController
|
||||
* Class UserController.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class UserController extends Controller
|
||||
{
|
||||
|
||||
/** @var UserRepositoryInterface */
|
||||
/** @var UserRepositoryInterface The user repository */
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* UserController constructor.
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
@@ -67,19 +70,22 @@ class UserController extends Controller
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \FireflyIII\User $user
|
||||
* @param User $user
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @throws \Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function delete(User $user)
|
||||
public function delete(User $user): JsonResponse
|
||||
{
|
||||
if (auth()->user()->hasRole('owner')) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
if ($admin->id !== $user->id && $this->repository->hasRole($admin, 'owner')) {
|
||||
$this->repository->destroy($user);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
throw new AccessDeniedException(''); // @codeCoverageIgnore
|
||||
throw new FireflyException('No access to method.'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,12 +93,13 @@ class UserController extends Controller
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
// user preferences
|
||||
$pageSize = (int)Preferences::getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
$pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
|
||||
|
||||
// make manager
|
||||
$manager = new Manager();
|
||||
@@ -109,41 +116,50 @@ class UserController extends Controller
|
||||
$paginator->setPath(route('api.v1.users.index') . $this->buildParams());
|
||||
|
||||
// make resource
|
||||
$resource = new FractalCollection($users, new UserTransformer($this->parameters), 'users');
|
||||
/** @var UserTransformer $transformer */
|
||||
$transformer = app(UserTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($users, $transformer, 'users');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param User $user
|
||||
* Show a single user.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @param Request $request
|
||||
* @param User $user
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function show(Request $request, User $user)
|
||||
public function show(Request $request, User $user): JsonResponse
|
||||
{
|
||||
// make manager
|
||||
$manager = new Manager();
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
// 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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new user.
|
||||
*
|
||||
* @param UserRequest $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(UserRequest $request)
|
||||
public function store(UserRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$user = $this->repository->store($data);
|
||||
@@ -153,23 +169,26 @@ class UserController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
// make resource
|
||||
$resource = new Item($user, new UserTransformer($this->parameters), 'users');
|
||||
|
||||
/** @var UserTransformer $transformer */
|
||||
$transformer = app(UserTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($user, $transformer, 'users');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserRequest $request
|
||||
* @param User $user
|
||||
* Update a user.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @param UserRequest $request
|
||||
* @param User $user
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(UserRequest $request, User $user)
|
||||
public function update(UserRequest $request, User $user): JsonResponse
|
||||
{
|
||||
$data = $request->getAll();
|
||||
$user = $this->repository->update($user, $data);
|
||||
@@ -179,12 +198,12 @@ class UserController extends Controller
|
||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// add include parameter:
|
||||
$include = $request->get('include') ?? '';
|
||||
$manager->parseIncludes($include);
|
||||
|
||||
// make resource
|
||||
$resource = new Item($user, new UserTransformer($this->parameters), 'users');
|
||||
/** @var UserTransformer $transformer */
|
||||
$transformer = app(UserTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($user, $transformer, 'users');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
|
||||
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
/**
|
||||
* Class AccountRequest
|
||||
*/
|
||||
class AccountRequest extends Request
|
||||
{
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$data = [
|
||||
'name' => $this->string('name'),
|
||||
'active' => $this->boolean('active'),
|
||||
'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'),
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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',
|
||||
'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',
|
||||
];
|
||||
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;
|
||||
}
|
||||
}
|
||||
88
app/Api/V1/Requests/AttachmentStoreRequest.php
Normal file
88
app/Api/V1/Requests/AttachmentStoreRequest.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* AttachmentStoreRequest.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\Bill;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Rules\IsValidAttachmentModel;
|
||||
|
||||
/**
|
||||
* Class AttachmentStoreRequest
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AttachmentStoreRequest 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
|
||||
{
|
||||
$models = implode(
|
||||
',',
|
||||
[
|
||||
str_replace('FireflyIII\\Models\\', '', Bill::class),
|
||||
str_replace('FireflyIII\\Models\\', '', ImportJob::class),
|
||||
str_replace('FireflyIII\\Models\\', '', TransactionJournal::class),
|
||||
]
|
||||
);
|
||||
$model = $this->string('model');
|
||||
return [
|
||||
'filename' => 'required|between:1,255',
|
||||
'title' => 'between:1,255',
|
||||
'notes' => 'between:1,65000',
|
||||
'model' => sprintf('required|in:%s', $models),
|
||||
'model_id' => ['required', 'numeric', new IsValidAttachmentModel($model)],
|
||||
];
|
||||
}
|
||||
}
|
||||
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',
|
||||
];
|
||||
}
|
||||
}
|
||||
79
app/Api/V1/Requests/AvailableBudgetRequest.php
Normal file
79
app/Api/V1/Requests/AvailableBudgetRequest.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* AvailableBudgetRequest.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 AvailableBudgetRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class AvailableBudgetRequest 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 [
|
||||
'currency_id' => $this->integer('currency_id'),
|
||||
'currency_code' => $this->string('currency_code'),
|
||||
'amount' => $this->string('amount'),
|
||||
'start' => $this->date('start'),
|
||||
'end' => $this->date('end'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
'amount' => 'required|numeric|more:0',
|
||||
'start' => 'required|date|before:end',
|
||||
'end' => 'required|date|after:start',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* BillRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,18 +20,26 @@ declare(strict_types=1);
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
* Class BillRequest
|
||||
*
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class BillRequest extends Request
|
||||
{
|
||||
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
@@ -41,55 +49,60 @@ class BillRequest extends Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$active = true;
|
||||
if (null !== $this->get('active')) {
|
||||
$active = $this->boolean('active');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'name' => $this->string('name'),
|
||||
'match' => $this->string('match'),
|
||||
'amount_min' => $this->string('amount_min'),
|
||||
'amount_max' => $this->string('amount_max'),
|
||||
//'currency_id' => $this->integer('currency_id'),
|
||||
//'currency_code' => $this->string('currency_code'),
|
||||
'date' => $this->date('date'),
|
||||
'repeat_freq' => $this->string('repeat_freq'),
|
||||
'skip' => $this->integer('skip'),
|
||||
'automatch' => $this->boolean('automatch'),
|
||||
'active' => $this->boolean('active'),
|
||||
'notes' => $this->string('notes'),
|
||||
'name' => $this->string('name'),
|
||||
'amount_min' => $this->string('amount_min'),
|
||||
'amount_max' => $this->string('amount_max'),
|
||||
'currency_id' => $this->integer('currency_id'),
|
||||
'currency_code' => $this->string('currency_code'),
|
||||
'date' => $this->date('date'),
|
||||
'repeat_freq' => $this->string('repeat_freq'),
|
||||
'skip' => $this->integer('skip'),
|
||||
'active' => $active,
|
||||
'notes' => $this->string('notes'),
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required|between:1,255|uniqueObjectForUser:bills,name',
|
||||
'match' => 'required|between:1,255|uniqueObjectForUser:bills,match',
|
||||
'amount_min' => 'required|numeric|more:0',
|
||||
'amount_max' => 'required|numeric|more:0',
|
||||
//'currency_id' => 'numeric|exists:transaction_currencies,id|required_without:currency_code',
|
||||
//'currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:currency_id',
|
||||
'date' => 'required|date',
|
||||
'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly',
|
||||
'skip' => 'required|between:0,31',
|
||||
'automatch' => 'required|boolean',
|
||||
'active' => 'required|boolean',
|
||||
'notes' => 'between:1,65536',
|
||||
'name' => 'required|between:1,255|uniqueObjectForUser:bills,name',
|
||||
'amount_min' => 'required|numeric|more:0',
|
||||
'amount_max' => 'required|numeric|more:0',
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
'date' => 'required|date',
|
||||
'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly',
|
||||
'skip' => 'between:0,31',
|
||||
'active' => [new IsBoolean],
|
||||
'notes' => 'between:1,65536',
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
$bill = $this->route()->parameter('bill');
|
||||
$rules['name'] .= ',' . $bill->id;
|
||||
$rules['match'] .= ',' . $bill->id;
|
||||
$bill = $this->route()->parameter('bill');
|
||||
$rules['name'] .= ',' . $bill->id;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -99,19 +112,19 @@ class BillRequest extends Request
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
static function (Validator $validator) {
|
||||
$data = $validator->getData();
|
||||
$min = (float)($data['amount_min'] ?? 0);
|
||||
$max = (float)($data['amount_max'] ?? 0);
|
||||
if ($min > $max) {
|
||||
$validator->errors()->add('amount_min', trans('validation.amount_min_over_max'));
|
||||
$validator->errors()->add('amount_min', (string)trans('validation.amount_min_over_max'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
95
app/Api/V1/Requests/BudgetLimitRequest.php
Normal file
95
app/Api/V1/Requests/BudgetLimitRequest.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetLimitRequest.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 BudgetLimitRequest
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class BudgetLimitRequest 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 [
|
||||
'budget_id' => $this->integer('budget_id'),
|
||||
'start' => $this->date('start'),
|
||||
'end' => $this->date('end'),
|
||||
'amount' => $this->string('amount'),
|
||||
'currency_id' => $this->integer('currency_id'),
|
||||
'currency_code' => $this->string('currency_code'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'budget_id' => 'required|exists:budgets,id|belongsToUser:budgets,id',
|
||||
'start' => 'required|before:end|date',
|
||||
'end' => 'required|after:start|date',
|
||||
'amount' => 'required|more:0',
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
$rules['budget_id'] = 'required|exists:budgets,id|belongsToUser:budgets,id';
|
||||
break;
|
||||
}
|
||||
// if request has a budget already, drop the rule.
|
||||
$budget = $this->route()->parameter('budget');
|
||||
if (null !== $budget) {
|
||||
unset($rules['budget_id']);
|
||||
}
|
||||
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
}
|
||||
90
app/Api/V1/Requests/BudgetRequest.php
Normal file
90
app/Api/V1/Requests/BudgetRequest.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* BudgetRequest.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\Budget;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
|
||||
/**
|
||||
* Class BudgetRequest
|
||||
* @codeCoverageIgnore
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class BudgetRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$active = true;
|
||||
if (null !== $this->get('active')) {
|
||||
$active = $this->boolean('active');
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
'active' => $active,
|
||||
'order' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name',
|
||||
'active' => [new IsBoolean],
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
/** @var Budget $budget */
|
||||
$budget = $this->route()->parameter('budget');
|
||||
$rules['name'] = sprintf('required|between:1,100|uniqueObjectForUser:budgets,name,%d', $budget->id);
|
||||
break;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
81
app/Api/V1/Requests/CategoryRequest.php
Normal file
81
app/Api/V1/Requests/CategoryRequest.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* CategoryRequest.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\Category;
|
||||
|
||||
/**
|
||||
* Class CategoryRequest
|
||||
* @codeCoverageIgnore
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class CategoryRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required|between:1,100|uniqueObjectForUser:categories,name',
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
/** @var Category $category */
|
||||
$category = $this->route()->parameter('category');
|
||||
$rules['name'] = sprintf('required|between:1,100|uniqueObjectForUser:categories,name,%d', $category->id);
|
||||
break;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
105
app/Api/V1/Requests/CurrencyRequest.php
Normal file
105
app/Api/V1/Requests/CurrencyRequest.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/**
|
||||
* CurrencyRequest.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 CurrencyRequest
|
||||
* @codeCoverageIgnore
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class CurrencyRequest 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
|
||||
{
|
||||
$enabled = true;
|
||||
$default = false;
|
||||
if (null !== $this->get('enabled')) {
|
||||
$enabled = $this->boolean('enabled');
|
||||
}
|
||||
if (null !== $this->get('default')) {
|
||||
$default = $this->boolean('default');
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
'code' => $this->string('code'),
|
||||
'symbol' => $this->string('symbol'),
|
||||
'decimal_places' => $this->integer('decimal_places'),
|
||||
'default' => $default,
|
||||
'enabled' => $enabled,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required|between:1,255|unique:transaction_currencies,name',
|
||||
'code' => 'required|between:3,3|unique:transaction_currencies,code',
|
||||
'symbol' => 'required|between:1,5|unique:transaction_currencies,symbol',
|
||||
'decimal_places' => 'between:0,20|numeric|min:0|max:20',
|
||||
'enabled' => [new IsBoolean()],
|
||||
'default' => [new IsBoolean()],
|
||||
|
||||
];
|
||||
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
$currency = $this->route()->parameter('currency_code');
|
||||
$rules['name'] = 'required|between:1,255|unique:transaction_currencies,name,' . $currency->id;
|
||||
$rules['code'] = 'required|between:1,255|unique:transaction_currencies,code,' . $currency->id;
|
||||
$rules['symbol'] = 'required|between:1,255|unique:transaction_currencies,symbol,' . $currency->id;
|
||||
break;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ReconciliationUpdateRequest.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* DateRequest.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@@ -18,50 +19,53 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Requests;
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
|
||||
/**
|
||||
* Class ReconciliationUpdateRequest.
|
||||
* Request class for end points that require date parameters.
|
||||
*
|
||||
* Class DateRequest
|
||||
*/
|
||||
class ReconciliationUpdateRequest extends Request
|
||||
class DateRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow logged in users
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns and validates the data required to update a reconciliation.
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getJournalData()
|
||||
public function getAll(): array
|
||||
{
|
||||
$data = [
|
||||
'tags' => explode(',', $this->string('tags')),
|
||||
'amount' => $this->string('amount'),
|
||||
'category' => $this->string('category'),
|
||||
return [
|
||||
'start' => $this->date('start'),
|
||||
'end' => $this->date('end'),
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'amount' => 'numeric|required',
|
||||
'category' => 'between:1,255|nullable',
|
||||
return [
|
||||
'start' => 'required|date',
|
||||
'end' => 'required|date|after:start',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
93
app/Api/V1/Requests/LinkTypeRequest.php
Normal file
93
app/Api/V1/Requests/LinkTypeRequest.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* LinkTypeRequest.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\LinkType;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class LinkTypeRequest
|
||||
* @codeCoverageIgnore
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class LinkTypeRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
'outward' => $this->string('outward'),
|
||||
'inward' => $this->string('inward'),
|
||||
];
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required|unique:link_types,name|min:1',
|
||||
'outward' => 'required|unique:link_types,outward|min:1|different:inward',
|
||||
'inward' => 'required|unique:link_types,inward|min:1|different:outward',
|
||||
];
|
||||
|
||||
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
/** @var LinkType $linkType */
|
||||
$linkType = $this->route()->parameter('linkType');
|
||||
$rules['name'] = ['required', Rule::unique('link_types', 'name')->ignore($linkType->id), 'min:1'];
|
||||
$rules['outward'] = ['required', 'different:inward', Rule::unique('link_types', 'outward')->ignore($linkType->id), 'min:1'];
|
||||
$rules['inward'] = ['required', 'different:outward', Rule::unique('link_types', 'inward')->ignore($linkType->id), 'min:1'];
|
||||
break;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
102
app/Api/V1/Requests/PiggyBankRequest.php
Normal file
102
app/Api/V1/Requests/PiggyBankRequest.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* PiggyBankRequest.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\PiggyBank;
|
||||
use FireflyIII\Rules\IsAssetAccountId;
|
||||
use FireflyIII\Rules\ZeroOrMore;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class PiggyBankRequest
|
||||
* @codeCoverageIgnore
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class PiggyBankRequest 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
|
||||
{
|
||||
$current = $this->string('current_amount');
|
||||
$current = '' === $current ? '0' : $current;
|
||||
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
'account_id' => $this->integer('account_id'),
|
||||
'targetamount' => $this->string('target_amount'),
|
||||
'current_amount' => $current,
|
||||
'startdate' => $this->date('start_date'),
|
||||
'targetdate' => $this->date('target_date'),
|
||||
'notes' => $this->string('notes'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'name' => 'required|between:1,255|uniquePiggyBankForUser',
|
||||
'account_id' => ['required', 'belongsToUser:accounts', new IsAssetAccountId],
|
||||
'target_amount' => 'required|numeric|more:0',
|
||||
'current_amount' => ['numeric', new ZeroOrMore, 'lte:target_amount'],
|
||||
'start_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable|after:start_date',
|
||||
'notes' => 'max:65000',
|
||||
];
|
||||
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
/** @var PiggyBank $piggyBank */
|
||||
$piggyBank = $this->route()->parameter('piggyBank');
|
||||
$rules['name'] = 'required|between:1,255|uniquePiggyBankForUser:' . $piggyBank->id;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* BunqId.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* PreferenceRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
@@ -19,53 +18,53 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Bunq\Id;
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
/**
|
||||
* Class BunqId.
|
||||
*
|
||||
* Class PreferenceRequest
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class BunqId
|
||||
class PreferenceRequest extends Request
|
||||
{
|
||||
/** @var int */
|
||||
private $id = 0;
|
||||
|
||||
|
||||
/**
|
||||
* BunqId constructor.
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @param null $data
|
||||
* @return bool
|
||||
*/
|
||||
public function __construct($data = null)
|
||||
public function authorize(): bool
|
||||
{
|
||||
if (null !== $data) {
|
||||
$this->id = $data['id'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId(): int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*/
|
||||
public function setId(int $id)
|
||||
{
|
||||
$this->id = $id;
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array
|
||||
public function getAll(): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'data' => $this->get('data'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'data' => 'required|between:1,65000',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
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);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Request.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
@@ -20,14 +20,209 @@ declare(strict_types=1);
|
||||
* 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\Http\Requests\Request as FireflyIIIRequest;
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
|
||||
/**
|
||||
* Class Request.
|
||||
*
|
||||
* Technically speaking this class does not have to be extended like this but who knows what the future brings.
|
||||
*
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
93
app/Api/V1/Requests/RuleGroupRequest.php
Normal file
93
app/Api/V1/Requests/RuleGroupRequest.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* RuleGroupRequest.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\RuleGroup;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* Class RuleGroupRequest
|
||||
* TODO AFTER 4.8,0: split this into two request classes.
|
||||
*/
|
||||
class RuleGroupRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$active = true;
|
||||
|
||||
if (null !== $this->get('active')) {
|
||||
$active = $this->boolean('active');
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => $this->string('title'),
|
||||
'description' => $this->string('description'),
|
||||
'active' => $active,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'title' => 'required|between:1,100|uniqueObjectForUser:rule_groups,title',
|
||||
'description' => 'between:1,5000|nullable',
|
||||
'active' => [new IsBoolean],
|
||||
];
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
/** @var RuleGroup $ruleGroup */
|
||||
$ruleGroup = $this->route()->parameter('ruleGroup');
|
||||
$rules['title'] = 'required|between:1,100|uniqueObjectForUser:rule_groups,title,' . $ruleGroup->id;
|
||||
break;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
207
app/Api/V1/Requests/RuleRequest.php
Normal file
207
app/Api/V1/Requests/RuleRequest.php
Normal file
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
/**
|
||||
* RuleRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use Illuminate\Validation\Validator;
|
||||
use function is_array;
|
||||
|
||||
|
||||
/**
|
||||
* Class RuleRequest
|
||||
*
|
||||
*/
|
||||
class RuleRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$strict = true;
|
||||
$active = true;
|
||||
$stopProcessing = false;
|
||||
if (null !== $this->get('active')) {
|
||||
$active = $this->boolean('active');
|
||||
}
|
||||
if (null !== $this->get('strict')) {
|
||||
$strict = $this->boolean('strict');
|
||||
}
|
||||
if (null !== $this->get('stop_processing')) {
|
||||
$stopProcessing = $this->boolean('stop_processing');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'title' => $this->string('title'),
|
||||
'description' => $this->string('description'),
|
||||
'rule_group_id' => $this->integer('rule_group_id'),
|
||||
'rule_group_title' => $this->string('rule_group_title'),
|
||||
'trigger' => $this->string('trigger'),
|
||||
'strict' => $strict,
|
||||
'stop_processing' => $stopProcessing,
|
||||
'active' => $active,
|
||||
'triggers' => $this->getRuleTriggers(),
|
||||
'actions' => $this->getRuleActions(),
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$validTriggers = array_keys(config('firefly.rule-triggers'));
|
||||
$validActions = array_keys(config('firefly.rule-actions'));
|
||||
|
||||
// some triggers and actions require text:
|
||||
$contextTriggers = implode(',', config('firefly.context-rule-triggers'));
|
||||
$contextActions = implode(',', config('firefly.context-rule-actions'));
|
||||
$rules = [
|
||||
'title' => 'required|between:1,100|uniqueObjectForUser:rules,title',
|
||||
'description' => 'between:1,5000|nullable',
|
||||
'rule_group_id' => 'required|belongsToUser:rule_groups|required_without:rule_group_title',
|
||||
'rule_group_title' => 'nullable|between:1,255|required_without:rule_group_id|belongsToUser:rule_groups,title',
|
||||
'trigger' => 'required|in:store-journal,update-journal',
|
||||
'triggers.*.type' => 'required|in:' . implode(',', $validTriggers),
|
||||
'triggers.*.value' => 'required_if:actions.*.type,' . $contextTriggers . '|min:1|ruleTriggerValue',
|
||||
'triggers.*.stop_processing' => [new IsBoolean],
|
||||
'triggers.*.active' => [new IsBoolean],
|
||||
'actions.*.type' => 'required|in:' . implode(',', $validActions),
|
||||
'actions.*.value' => 'required_if:actions.*.type,' . $contextActions . '|ruleActionValue',
|
||||
'actions.*.stop_processing' => [new IsBoolean],
|
||||
'actions.*.active' => [new IsBoolean],
|
||||
'strict' => [new IsBoolean],
|
||||
'stop_processing' => [new IsBoolean],
|
||||
'active' => [new IsBoolean],
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
$this->atLeastOneTrigger($validator);
|
||||
$this->atLeastOneAction($validator);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no repetitions in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function atLeastOneTrigger(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$triggers = $data['triggers'] ?? [];
|
||||
// need at least one trigger
|
||||
if (0 === count($triggers)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no repetitions in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function atLeastOneAction(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$actions = $data['actions'] ?? [];
|
||||
// need at least one trigger
|
||||
if (0 === count($actions)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getRuleTriggers(): array
|
||||
{
|
||||
$triggers = $this->get('triggers');
|
||||
$return = [];
|
||||
if (is_array($triggers)) {
|
||||
foreach ($triggers as $trigger) {
|
||||
$return[] = [
|
||||
'type' => $trigger['type'],
|
||||
'value' => $trigger['value'],
|
||||
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'false')),
|
||||
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getRuleActions(): array
|
||||
{
|
||||
$actions = $this->get('actions');
|
||||
$return = [];
|
||||
if (is_array($actions)) {
|
||||
foreach ($actions as $action) {
|
||||
$return[] = [
|
||||
'type' => $action['type'],
|
||||
'value' => $action['value'],
|
||||
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
|
||||
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
138
app/Api/V1/Requests/TransactionLinkRequest.php
Normal file
138
app/Api/V1/Requests/TransactionLinkRequest.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
/**
|
||||
* TransactionLinkRequest.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
*
|
||||
* Class TransactionLinkRequest
|
||||
*/
|
||||
class TransactionLinkRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Authorize logged in users.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
return [
|
||||
'link_type_id' => $this->integer('link_type_id'),
|
||||
'link_type_name' => $this->string('link_type_name'),
|
||||
'inward_id' => $this->integer('inward_id'),
|
||||
'outward_id' => $this->integer('outward_id'),
|
||||
'notes' => $this->string('notes'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The rules that the incoming request must be matched against.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'link_type_id' => 'exists:link_types,id|required_without:link_type_name',
|
||||
'link_type_name' => 'exists:link_types,name|required_without:link_type_id',
|
||||
'inward_id' => 'required|belongsToUser:transaction_journals,id|different:outward_id',
|
||||
'outward_id' => 'required|belongsToUser:transaction_journals,id|different:inward_id',
|
||||
'notes' => 'between:0,65000',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
$this->validateExistingLink($validator);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Validator $validator
|
||||
*/
|
||||
private function validateExistingLink(Validator $validator): void
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
/** @var LinkTypeRepositoryInterface $repository */
|
||||
$repository = app(LinkTypeRepositoryInterface::class);
|
||||
$repository->setUser($user);
|
||||
|
||||
/** @var JournalRepositoryInterface $journalRepos */
|
||||
$journalRepos = app(JournalRepositoryInterface::class);
|
||||
$journalRepos->setUser($user);
|
||||
|
||||
$data = $validator->getData();
|
||||
$inwardId = (int)($data['inward_id'] ?? 0);
|
||||
$outwardId = (int)($data['outward_id'] ?? 0);
|
||||
$inward = $journalRepos->findNull($inwardId);
|
||||
$outward = $journalRepos->findNull($outwardId);
|
||||
|
||||
if (null === $inward) {
|
||||
$validator->errors()->add('inward_id', 'Invalid inward ID.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (null === $outward) {
|
||||
$validator->errors()->add('outward_id', 'Invalid outward ID.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($repository->findLink($inward, $outward)) {
|
||||
// only if not updating:
|
||||
$link = $this->route()->parameter('journalLink');
|
||||
if (null === $link) {
|
||||
$validator->errors()->add('outward_id', 'Already have a link between inward and outward.');
|
||||
$validator->errors()->add('inward_id', 'Already have a link between inward and outward.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,514 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
|
||||
/**
|
||||
* Class TransactionRequest
|
||||
*/
|
||||
class TransactionRequest extends Request
|
||||
{
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// Only allow authenticated users
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$data = [
|
||||
// basic fields for journal:
|
||||
'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')),
|
||||
|
||||
// then, custom fields for journal
|
||||
'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'),
|
||||
|
||||
// then, transactions (see below).
|
||||
'transactions' => [],
|
||||
|
||||
];
|
||||
foreach ($this->get('transactions') as $index => $transaction) {
|
||||
$array = [
|
||||
'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,
|
||||
];
|
||||
$data['transactions'][] = $array;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
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',
|
||||
];
|
||||
|
||||
switch ($this->method()) {
|
||||
default:
|
||||
break;
|
||||
case 'PUT':
|
||||
case 'PATCH':
|
||||
unset($rules['type'], $rules['piggy_bank_id'], $rules['piggy_bank_name']);
|
||||
break;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @return void
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
$this->atLeastOneTransaction($validator);
|
||||
$this->checkValidDescriptions($validator);
|
||||
$this->equalToJournalDescription($validator);
|
||||
$this->emptySplitDescriptions($validator);
|
||||
$this->foreignCurrencyInformation($validator);
|
||||
$this->validateAccountInformation($validator);
|
||||
$this->validateSplitAccounts($validator);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an error when this asset account is invalid.
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @param int|null $accountId
|
||||
* @param null|string $accountName
|
||||
* @param string $idField
|
||||
* @param string $nameField
|
||||
*
|
||||
* @return null|Account
|
||||
*/
|
||||
protected function assetAccountExists(Validator $validator, ?int $accountId, ?string $accountName, string $idField, string $nameField): ?Account
|
||||
{
|
||||
|
||||
$accountId = (int)$accountId;
|
||||
$accountName = (string)$accountName;
|
||||
// both empty? hard exit.
|
||||
if ($accountId < 1 && strlen($accountName) === 0) {
|
||||
$validator->errors()->add($idField, trans('validation.filled', ['attribute' => $idField]));
|
||||
|
||||
return null;
|
||||
}
|
||||
// ID belongs to user and is asset account:
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$set = $repository->getAccountsById([$accountId]);
|
||||
if ($set->count() === 1) {
|
||||
/** @var Account $first */
|
||||
$first = $set->first();
|
||||
if ($first->accountType->type !== AccountType::ASSET) {
|
||||
$validator->errors()->add($idField, trans('validation.belongs_user'));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// we ignore the account name at this point.
|
||||
return $first;
|
||||
}
|
||||
|
||||
$account = $repository->findByNameNull($accountName, [AccountType::ASSET]);
|
||||
if (null === $account) {
|
||||
$validator->errors()->add($nameField, trans('validation.belongs_user'));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when there are no transactions in the array of data.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function atLeastOneTransaction(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
// need at least one transaction
|
||||
if (count($transactions) === 0) {
|
||||
$validator->errors()->add('description', trans('validation.at_least_one_transaction'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the "description" field when the user has submitted no descriptions and no
|
||||
* journal description.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function checkValidDescriptions(Validator $validator)
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
$journalDescription = (string)($data['description'] ?? '');
|
||||
$validDescriptions = 0;
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
if (strlen((string)($transaction['description'] ?? '')) > 0) {
|
||||
$validDescriptions++;
|
||||
}
|
||||
}
|
||||
|
||||
// no valid descriptions and empty journal description? error.
|
||||
if ($validDescriptions === 0 && strlen($journalDescription) === 0) {
|
||||
$validator->errors()->add('description', trans('validation.filled', ['attribute' => trans('validation.attributes.description')]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when the user submits a split transaction (more than 1 transactions)
|
||||
* but does not give them a description.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function emptySplitDescriptions(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
$description = (string)($transaction['description'] ?? '');
|
||||
// filled description is mandatory for split transactions.
|
||||
if (count($transactions) > 1 && strlen($description) === 0) {
|
||||
$validator->errors()->add(
|
||||
'transactions.' . $index . '.description',
|
||||
trans('validation.filled', ['attribute' => trans('validation.attributes.transaction_description')])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error to the validator when any transaction descriptions are equal to the journal description.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function equalToJournalDescription(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
$journalDescription = (string)($data['description'] ?? '');
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
$description = (string)($transaction['description'] ?? '');
|
||||
// description cannot be equal to journal description.
|
||||
if ($description === $journalDescription) {
|
||||
$validator->errors()->add('transactions.' . $index . '.description', trans('validation.equal_description'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the transactions contain foreign amounts, there must also be foreign currency information.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*/
|
||||
protected function foreignCurrencyInformation(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
// must have currency info.
|
||||
if (isset($transaction['foreign_amount'])
|
||||
&& !(isset($transaction['foreign_currency_id'])
|
||||
|| isset($transaction['foreign_currency_code']))) {
|
||||
$validator->errors()->add(
|
||||
'transactions.' . $index . '.foreign_amount',
|
||||
trans('validation.require_currency_info')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an error when the given opposing account (of type $type) is invalid.
|
||||
* Empty data is allowed, system will default to cash.
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @param string $type
|
||||
* @param int|null $accountId
|
||||
* @param null|string $accountName
|
||||
* @param string $idField
|
||||
*
|
||||
* @return null|Account
|
||||
*/
|
||||
protected function opposingAccountExists(Validator $validator, string $type, ?int $accountId, ?string $accountName, string $idField): ?Account
|
||||
{
|
||||
$accountId = (int)$accountId;
|
||||
$accountName = (string)$accountName;
|
||||
// both empty? done!
|
||||
if ($accountId < 1 && strlen($accountName) === 0) {
|
||||
return null;
|
||||
}
|
||||
if ($accountId !== 0) {
|
||||
// ID belongs to user and is $type account:
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$set = $repository->getAccountsById([$accountId]);
|
||||
if ($set->count() === 1) {
|
||||
/** @var Account $first */
|
||||
$first = $set->first();
|
||||
if ($first->accountType->type !== $type) {
|
||||
$validator->errors()->add($idField, trans('validation.belongs_user'));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// we ignore the account name at this point.
|
||||
return $first;
|
||||
}
|
||||
}
|
||||
|
||||
// not having an opposing account by this name is NOT a problem.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the given account information. Switches on given transaction type.
|
||||
*
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
protected function validateAccountInformation(Validator $validator): void
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
if (!isset($data['type'])) {
|
||||
// the journal may exist in the request:
|
||||
/** @var Transaction $transaction */
|
||||
$transaction = $this->route()->parameter('transaction');
|
||||
if (null === $transaction) {
|
||||
return; // @codeCoverageIgnore
|
||||
}
|
||||
$data['type'] = strtolower($transaction->transactionJournal->transactionType->type);
|
||||
}
|
||||
foreach ($transactions as $index => $transaction) {
|
||||
$sourceId = isset($transaction['source_id']) ? (int)$transaction['source_id'] : null;
|
||||
$sourceName = $transaction['source_name'] ?? null;
|
||||
$destinationId = isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null;
|
||||
$destinationName = $transaction['destination_name'] ?? null;
|
||||
$sourceAccount = null;
|
||||
$destinationAccount = null;
|
||||
switch ($data['type']) {
|
||||
case 'withdrawal':
|
||||
$idField = 'transactions.' . $index . '.source_id';
|
||||
$nameField = 'transactions.' . $index . '.source_name';
|
||||
$sourceAccount = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField);
|
||||
$idField = 'transactions.' . $index . '.destination_id';
|
||||
$destinationAccount = $this->opposingAccountExists($validator, AccountType::EXPENSE, $destinationId, $destinationName, $idField);
|
||||
break;
|
||||
case 'deposit':
|
||||
$idField = 'transactions.' . $index . '.source_id';
|
||||
$sourceAccount = $this->opposingAccountExists($validator, AccountType::REVENUE, $sourceId, $sourceName, $idField);
|
||||
|
||||
$idField = 'transactions.' . $index . '.destination_id';
|
||||
$nameField = 'transactions.' . $index . '.destination_name';
|
||||
$destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField);
|
||||
break;
|
||||
case 'transfer':
|
||||
$idField = 'transactions.' . $index . '.source_id';
|
||||
$nameField = 'transactions.' . $index . '.source_name';
|
||||
$sourceAccount = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField);
|
||||
|
||||
$idField = 'transactions.' . $index . '.destination_id';
|
||||
$nameField = 'transactions.' . $index . '.destination_name';
|
||||
$destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField);
|
||||
break;
|
||||
default:
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new FireflyException(
|
||||
sprintf('The validator cannot handle transaction type "%s" in validateAccountInformation().', $data['type'])
|
||||
);
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
}
|
||||
// add some errors in case of same account submitted:
|
||||
if (null !== $sourceAccount && null !== $destinationAccount && $sourceAccount->id === $destinationAccount->id) {
|
||||
$validator->errors()->add($idField, trans('validation.source_equals_destination'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Validator $validator
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
protected function validateSplitAccounts(Validator $validator)
|
||||
{
|
||||
$data = $validator->getData();
|
||||
$count = isset($data['transactions']) ? count($data['transactions']) : 0;
|
||||
if ($count < 2) {
|
||||
return;
|
||||
}
|
||||
// this is pretty much impossible:
|
||||
// @codeCoverageIgnoreStart
|
||||
if (!isset($data['type'])) {
|
||||
// the journal may exist in the request:
|
||||
/** @var Transaction $transaction */
|
||||
$transaction = $this->route()->parameter('transaction');
|
||||
if (null === $transaction) {
|
||||
return;
|
||||
}
|
||||
$data['type'] = strtolower($transaction->transactionJournal->transactionType->type);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// collect all source ID's and destination ID's, if present:
|
||||
$sources = [];
|
||||
$destinations = [];
|
||||
|
||||
foreach ($data['transactions'] as $transaction) {
|
||||
$sources[] = isset($transaction['source_id']) ? (int)$transaction['source_id'] : 0;
|
||||
$destinations[] = isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : 0;
|
||||
}
|
||||
$destinations = array_unique($destinations);
|
||||
$sources = array_unique($sources);
|
||||
// switch on type:
|
||||
switch ($data['type']) {
|
||||
case 'withdrawal':
|
||||
if (count($sources) > 1) {
|
||||
$validator->errors()->add('transactions.0.source_id', trans('validation.all_accounts_equal'));
|
||||
}
|
||||
break;
|
||||
case 'deposit':
|
||||
if (count($destinations) > 1) {
|
||||
$validator->errors()->add('transactions.0.destination_id', trans('validation.all_accounts_equal'));
|
||||
}
|
||||
break;
|
||||
case 'transfer':
|
||||
if (count($sources) > 1 || count($destinations) > 1) {
|
||||
$validator->errors()->add('transactions.0.source_id', trans('validation.all_accounts_equal'));
|
||||
$validator->errors()->add('transactions.0.destination_id', trans('validation.all_accounts_equal'));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new FireflyException(
|
||||
sprintf('The validator cannot handle transaction type "%s" in validateSplitAccounts().', $data['type'])
|
||||
);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user