mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-08-16 10:54:39 +00:00
Compare commits
922 Commits
develop-20
...
develop-20
Author | SHA1 | Date | |
---|---|---|---|
|
145e8d23f0 | ||
|
d0ba0583a5 | ||
|
17d8b54280 | ||
|
2cf0bfe3c4 | ||
|
070a8cf148 | ||
|
f94c21446a | ||
|
1ef1873016 | ||
|
32e4e29e7c | ||
|
65ca0dd9e0 | ||
|
3385e12c01 | ||
|
3566a4afa3 | ||
|
68ff033342 | ||
|
f141b0be5c | ||
|
d399dd160f | ||
|
4c8ed784cd | ||
|
fb3402acd4 | ||
|
8cad430816 | ||
|
01502b456e | ||
|
9b6314066b | ||
|
e61dadcbc6 | ||
|
f7baf5b2fd | ||
|
0545826d57 | ||
|
a29904704c | ||
|
899d374222 | ||
|
07ff2305fd | ||
|
ee96dd3ab6 | ||
|
a766d3a133 | ||
|
67545b0371 | ||
|
6b86d825ea | ||
|
31dbc57e8b | ||
|
00050f629c | ||
|
3760aabf13 | ||
|
22e092b513 | ||
|
a4f7c90e09 | ||
|
4b92ab46a3 | ||
|
0573bf2402 | ||
|
e28e538272 | ||
|
6f8f175890 | ||
|
fbf9ab6c5f | ||
|
3c67175e68 | ||
|
b0d25a1d33 | ||
|
9ea8709835 | ||
|
ae22c59f21 | ||
|
12b8ba68b3 | ||
|
6b086c9bff | ||
|
546a1198a1 | ||
|
1001e04b63 | ||
|
2c96729d76 | ||
|
194d22ad90 | ||
|
51e86448c7 | ||
|
e42107c03c | ||
|
abd9260193 | ||
|
042e2ba97d | ||
|
d5240f7afd | ||
|
cda90df995 | ||
|
446e855b74 | ||
|
fb31f25d71 | ||
|
ba43d8c3f5 | ||
|
3924781797 | ||
|
b99a6a9fc9 | ||
|
2967f4d4c7 | ||
|
285eeb1d12 | ||
|
6374215ebc | ||
|
8f0c0f215c | ||
|
5fc764e72b | ||
|
b330313c55 | ||
|
aa9ce73758 | ||
|
d97fda41b2 | ||
|
945ad79c03 | ||
|
6273807525 | ||
|
50803a2c24 | ||
|
a0e9b05680 | ||
|
41e74cd816 | ||
|
b379c8e36b | ||
|
76e893f86e | ||
|
5da1599959 | ||
|
1d997e7c86 | ||
|
35e2eba303 | ||
|
b50f8f8ecd | ||
|
c16d3be85f | ||
|
bd1232644f | ||
|
37ca460ff2 | ||
|
478acdc847 | ||
|
f9ec94ea97 | ||
|
576c5f242c | ||
|
dba8bba41a | ||
|
55a00aa6fe | ||
|
22133f64cf | ||
|
2efb2377b6 | ||
|
9f75a96ad6 | ||
|
d0be9bb957 | ||
|
c25adf0a56 | ||
|
0ca79fd843 | ||
|
efc516eb3b | ||
|
dca3ac9250 | ||
|
33668a3688 | ||
|
5414a70abb | ||
|
85aee63d1e | ||
|
ad09c851f6 | ||
|
c57f36820b | ||
|
6bb2702e07 | ||
|
b1dbd3ee17 | ||
|
2d41db349a | ||
|
6b73b9327a | ||
|
e3ea54329d | ||
|
686a76f32c | ||
|
cdafb82a49 | ||
|
0075f10f98 | ||
|
b70c0e4ab3 | ||
|
01aca092a1 | ||
|
8e6449ec12 | ||
|
984c4e2449 | ||
|
002c5485f5 | ||
|
12d74f15c0 | ||
|
2e87e179f0 | ||
|
a861126c0f | ||
|
8f5e58e8ad | ||
|
6c26f1f677 | ||
|
d7caaca5e4 | ||
|
835c81f329 | ||
|
1615b0cb29 | ||
|
c07a279c81 | ||
|
1478dae316 | ||
|
83a1e6616a | ||
|
66bd786842 | ||
|
33d73d8be8 | ||
|
75e190ba64 | ||
|
820569a52b | ||
|
05005eac32 | ||
|
5aa677c6fb | ||
|
456a3a9216 | ||
|
be25a7596f | ||
|
59a07e5dde | ||
|
6946a815e2 | ||
|
4a84e94022 | ||
|
5ba5d1f90e | ||
|
beb2bbcdc9 | ||
|
805fd5ae08 | ||
|
96093e313a | ||
|
afe9e88f9a | ||
|
b43048c674 | ||
|
11c38a599b | ||
|
0ce245f480 | ||
|
aef15cf3d3 | ||
|
d1880de30e | ||
|
9d900a69ed | ||
|
1653f77b15 | ||
|
9418436d51 | ||
|
1c9a6a194a | ||
|
11cfb5a962 | ||
|
7d21467447 | ||
|
5ce9f32deb | ||
|
337440259f | ||
|
c483e0768f | ||
|
fd9b0d9417 | ||
|
c3165f4937 | ||
|
a5c9adc872 | ||
|
59cc007931 | ||
|
8b0b12b521 | ||
|
6ae1cfd82e | ||
|
4d7eb27fd0 | ||
|
fe0b8d0128 | ||
|
04f0fcfbf7 | ||
|
7e182cf070 | ||
|
ad78c302ef | ||
|
36b4c69491 | ||
|
30bd0711f4 | ||
|
d847827584 | ||
|
786c1fcd58 | ||
|
90e7f0c0f7 | ||
|
63f334abe5 | ||
|
2466cd942f | ||
|
ea37db87f4 | ||
|
c168fb6960 | ||
|
03fb707b93 | ||
|
db226c2584 | ||
|
1c6ec82c91 | ||
|
40eb77ffde | ||
|
17ddb01cd1 | ||
|
ca56c7af70 | ||
|
55c428070f | ||
|
574eec1c08 | ||
|
15cde8173e | ||
|
ccb581b4ee | ||
|
c5f8db5b50 | ||
|
611748fbaf | ||
|
b57dfa9432 | ||
|
253982d579 | ||
|
94c7a19aa0 | ||
|
e9b360a721 | ||
|
ebf7f5932a | ||
|
4427f2fb99 | ||
|
6626dfbac3 | ||
|
093a6387a2 | ||
|
21ddde9e0d | ||
|
44d4e4e6da | ||
|
e34e53eeb3 | ||
|
07fb45bb34 | ||
|
d381669733 | ||
|
fb9eb15ae1 | ||
|
a2127c382b | ||
|
e10d39c093 | ||
|
a933b49e7c | ||
|
38bcd610df | ||
|
5beb476a28 | ||
|
3a43ce6546 | ||
|
c11fddb097 | ||
|
98f79cd9bf | ||
|
a3d3fe758b | ||
|
93587cf1b6 | ||
|
361e95f102 | ||
|
be212e7d1d | ||
|
003a30727f | ||
|
27b662e2dc | ||
|
0b4d7ad95e | ||
|
7acbfb230a | ||
|
b974310798 | ||
|
e391725eed | ||
|
f505580b33 | ||
|
270f932a48 | ||
|
b9afa908e3 | ||
|
6dcc78b9e5 | ||
|
7b0e7e8612 | ||
|
1ece4abd9d | ||
|
07c03b672b | ||
|
27ea50ec16 | ||
|
e1195e6663 | ||
|
faeb17f319 | ||
|
db91b1b127 | ||
|
b5b511c86b | ||
|
8c805fe0c9 | ||
|
b0672eb294 | ||
|
750019808c | ||
|
7f4510467f | ||
|
a46f8430df | ||
|
5e1ecb2b11 | ||
|
4fff59f16b | ||
|
eea8f5e07e | ||
|
a3fcd636e7 | ||
|
de6dc19077 | ||
|
7a8e3aca03 | ||
|
076047ad24 | ||
|
a4e1c8c24f | ||
|
3bf1c0075e | ||
|
1821ade319 | ||
|
dcd4f072d5 | ||
|
1734c7f545 | ||
|
aef3d340ae | ||
|
e39d4bc288 | ||
|
ed35b0f81a | ||
|
4805c9e1c9 | ||
|
eebcbe0f67 | ||
|
61e2b79357 | ||
|
fd3b03d3de | ||
|
9423a28158 | ||
|
55062068fd | ||
|
542b6f670d | ||
|
5b163b42b4 | ||
|
613dce51fb | ||
|
40adb5b203 | ||
|
fba796fa84 | ||
|
db4c3f9bfa | ||
|
d960cc6ad7 | ||
|
c620ec1f24 | ||
|
2d78bba6f4 | ||
|
b7a3f5d740 | ||
|
96def3c5d4 | ||
|
e1941d9d87 | ||
|
a30cf03678 | ||
|
aa0dcd3b7e | ||
|
810e92f7a3 | ||
|
5dd49fc1e1 | ||
|
8517af105d | ||
|
442cf7f9b3 | ||
|
82878b5214 | ||
|
b0f1102540 | ||
|
2efee7e6de | ||
|
abcecc7476 | ||
|
c28005f649 | ||
|
a369e61f18 | ||
|
05d82b6c05 | ||
|
68ca8fd250 | ||
|
b55b565ee5 | ||
|
fc98d66ef4 | ||
|
f6642c075d | ||
|
458a337521 | ||
|
37d2299a1d | ||
|
f69cffc50b | ||
|
fd77a17ba5 | ||
|
b481cf53e7 | ||
|
a4a4590c45 | ||
|
9e398beb07 | ||
|
38ae3df423 | ||
|
2f17701b68 | ||
|
4c797c1d4c | ||
|
a8e1c22c93 | ||
|
b60021e0ce | ||
|
453ccd3271 | ||
|
08f13aebe3 | ||
|
26df1be871 | ||
|
fe2def9684 | ||
|
db2cab3cef | ||
|
d84405191f | ||
|
349d32a268 | ||
|
30b7e17b6f | ||
|
2d3d3bc0a4 | ||
|
a4f887921a | ||
|
710732d7f5 | ||
|
cd08c16dee | ||
|
a8f36a2490 | ||
|
7f12d06989 | ||
|
8eb0313841 | ||
|
113eb84461 | ||
|
cdf42e50f0 | ||
|
e59cf03d80 | ||
|
0bd0e6caeb | ||
|
605623a7af | ||
|
042d055d85 | ||
|
cc29d0a850 | ||
|
7dede49aee | ||
|
775282ae02 | ||
|
e49806078a | ||
|
71d8c0d219 | ||
|
0031c5a5ad | ||
|
3ce111550e | ||
|
58af83cc8c | ||
|
422a23e700 | ||
|
8c2672cdf8 | ||
|
764e49985b | ||
|
84251f8f10 | ||
|
3d878cb5dd | ||
|
8b4740d28c | ||
|
0845e265c2 | ||
|
b4455a3802 | ||
|
8d12d47691 | ||
|
3dc01b0d5c | ||
|
b442645280 | ||
|
eda2b5f822 | ||
|
d9593db5e2 | ||
|
9dcb8e2680 | ||
|
56bac9fc97 | ||
|
f7ad9c56c8 | ||
|
0086a0ddc8 | ||
|
25ebfd6978 | ||
|
de8149137a | ||
|
79ae110368 | ||
|
60aef0de1a | ||
|
8d464962a8 | ||
|
b93cfc5de2 | ||
|
d41f5b1090 | ||
|
40322813c9 | ||
|
4a98927e32 | ||
|
193e529803 | ||
|
fbf20ef2c2 | ||
|
54de829c8a | ||
|
131b987561 | ||
|
dce6754c62 | ||
|
f4bca90080 | ||
|
b2960b1ed9 | ||
|
33f87bce23 | ||
|
23aa45609b | ||
|
b098952f82 | ||
|
68c3e14b0c | ||
|
19d08137a5 | ||
|
73776e7869 | ||
|
bf04ca12c1 | ||
|
a4637debe9 | ||
|
48c1b525be | ||
|
56470bfbba | ||
|
0f732ca874 | ||
|
e452ba938d | ||
|
9921c5a925 | ||
|
58fab75681 | ||
|
54990308f6 | ||
|
f95758ff47 | ||
|
8d830e178f | ||
|
334a521ca1 | ||
|
12629a1955 | ||
|
2e3669a32f | ||
|
ea337607c4 | ||
|
f7f317a3b2 | ||
|
adbf6defe5 | ||
|
e0709f2975 | ||
|
30007b05cb | ||
|
13fc7f0d8d | ||
|
7c85138115 | ||
|
2c25f65f7f | ||
|
7eaba962e8 | ||
|
7c38393cde | ||
|
153fd2ae74 | ||
|
c0204c810c | ||
|
944c107e26 | ||
|
18e05c06fd | ||
|
fb79dbf17c | ||
|
31a8163c61 | ||
|
8bcd729250 | ||
|
80c4e69528 | ||
|
7f6d8fdb87 | ||
|
c8e301326e | ||
|
4820ef6580 | ||
|
4cb775cf4b | ||
|
c371662c51 | ||
|
ffaa164aa5 | ||
|
344bfbe059 | ||
|
6c38b87ec5 | ||
|
dfcd5d79be | ||
|
07631eea28 | ||
|
26c4fe36cc | ||
|
90fc4b44f2 | ||
|
f755dd2d48 | ||
|
d2647f96e7 | ||
|
9f94ec067a | ||
|
a795755618 | ||
|
8457a1c881 | ||
|
fc9429bf3e | ||
|
b6e8b66035 | ||
|
7504b21c3e | ||
|
b7dad8166d | ||
|
2da1b43c37 | ||
|
a606315884 | ||
|
295feedd77 | ||
|
d3b2748c8f | ||
|
1b4655fd70 | ||
|
05f67ef584 | ||
|
04ab7ba07d | ||
|
5806323970 | ||
|
ee260a3df7 | ||
|
7cb41fb333 | ||
|
d38adbfdc2 | ||
|
e6a6766ef1 | ||
|
a1e596491c | ||
|
9c920908a6 | ||
|
0014bffeb8 | ||
|
63c17f99b2 | ||
|
ec1e0e2807 | ||
|
2f16419a7b | ||
|
02c13859e7 | ||
|
57ec9b8e36 | ||
|
41ad35880d | ||
|
3aa946e028 | ||
|
53e46895aa | ||
|
c61389037d | ||
|
6172d60e00 | ||
|
f909f1d9ff | ||
|
55018ca046 | ||
|
19c746a865 | ||
|
503d2aa786 | ||
|
70d83ab501 | ||
|
edab602bb7 | ||
|
f9bcc4b1fa | ||
|
f3fe86167c | ||
|
2189fb46a2 | ||
|
7ff4178c8b | ||
|
fffd695ef8 | ||
|
ee592de035 | ||
|
7394e50ae2 | ||
|
f42fcff04a | ||
|
4eb3ce7c14 | ||
|
a977c567ce | ||
|
785bd7e905 | ||
|
df19f699d4 | ||
|
5e6e932e7e | ||
|
5bc397f01a | ||
|
42209e367f | ||
|
d53b1670d3 | ||
|
a6d450ba18 | ||
|
e8c1a95128 | ||
|
edb201f210 | ||
|
fe57367a8c | ||
|
134194a95b | ||
|
41c0e6fe2d | ||
|
c07914e733 | ||
|
52e2302f4f | ||
|
0a6b34b4f2 | ||
|
1e06b4dd0b | ||
|
5701f95e0b | ||
|
60d3572d37 | ||
|
ffa6e6a571 | ||
|
d6453cd735 | ||
|
fd79f9df44 | ||
|
4587340293 | ||
|
90bfdc7573 | ||
|
eca12f661f | ||
|
f85878b843 | ||
|
6499b5eaab | ||
|
7e4fece63d | ||
|
512eddf8be | ||
|
f0fa93a811 | ||
|
3c8de21709 | ||
|
81173e8340 | ||
|
35a8fa5f02 | ||
|
443036936d | ||
|
ac88007593 | ||
|
2297589dca | ||
|
6ada5fa560 | ||
|
8f6eefb5e7 | ||
|
b36a50381b | ||
|
51f84b3060 | ||
|
72132a19b0 | ||
|
065d165211 | ||
|
cabedf39b2 | ||
|
5d3806fcd4 | ||
|
01695b3342 | ||
|
71fb5fe077 | ||
|
3bec106840 | ||
|
fb01c36be1 | ||
|
26d851e69e | ||
|
28c18c046b | ||
|
318cef7e3b | ||
|
e8dc8f25be | ||
|
10ccc30240 | ||
|
5adc877d5e | ||
|
30923afb2b | ||
|
4eb6813b43 | ||
|
7521a31619 | ||
|
fc05beb452 | ||
|
1103428a83 | ||
|
d06d521bf0 | ||
|
8f64f1c0eb | ||
|
d11c232171 | ||
|
93c73248de | ||
|
5bed081ab9 | ||
|
c5188c503e | ||
|
98ffcac7b6 | ||
|
df1e81d611 | ||
|
9711170b08 | ||
|
e43264bdce | ||
|
e0643bed7a | ||
|
7f0eb3b064 | ||
|
f38e510526 | ||
|
25f99b23b2 | ||
|
44281fc8a0 | ||
|
eed3902cb7 | ||
|
94a3bb0443 | ||
|
8dcc36880e | ||
|
695bb31894 | ||
|
f8ded66869 | ||
|
8e4bdbc584 | ||
|
f7b14b01bc | ||
|
705b9bf0f2 | ||
|
f0226dbc54 | ||
|
1b1dfb0d7b | ||
|
8ed5092a76 | ||
|
d609821be6 | ||
|
cd0201074c | ||
|
1d8feec7bc | ||
|
d941472c84 | ||
|
674a118fac | ||
|
1334d793f6 | ||
|
60354c0202 | ||
|
22081d3f0a | ||
|
4b3f8fc78d | ||
|
4bd1aab86d | ||
|
60362cb60c | ||
|
27f740bf98 | ||
|
5e15747a5b | ||
|
8a6eaad2bb | ||
|
5ab52d9f66 | ||
|
21a327bf08 | ||
|
15dd175394 | ||
|
3f35305beb | ||
|
768d8b1515 | ||
|
1c19428a12 | ||
|
c204533195 | ||
|
6d89485792 | ||
|
949d818bad | ||
|
a12e200a0a | ||
|
b4039b1f13 | ||
|
32921e15b1 | ||
|
4f7cc7d53b | ||
|
0986bfbc34 | ||
|
663202bfc6 | ||
|
6f63ddf5b0 | ||
|
a9805b144a | ||
|
e1b8b9b3ae | ||
|
d57327fd11 | ||
|
15ac69bfad | ||
|
a5bd28f8d4 | ||
|
b2516ca1b4 | ||
|
053b46ae63 | ||
|
6e836aceec | ||
|
0e8bcd2e79 | ||
|
bd1f8b2497 | ||
|
19dfcf7139 | ||
|
ef7a3287bb | ||
|
2900049498 | ||
|
04d1e8fd59 | ||
|
9d2f57e40a | ||
|
ae366341cc | ||
|
3766128cb8 | ||
|
950c60d55c | ||
|
4b2807de48 | ||
|
649736cb31 | ||
|
6a121a8a78 | ||
|
f69b9ac9da | ||
|
23d70a2fac | ||
|
d178ff9de0 | ||
|
3ecad3457f | ||
|
fa6c621968 | ||
|
df863b6cff | ||
|
9316ff3e51 | ||
|
bfd91f8ee6 | ||
|
13e5d25cfe | ||
|
b13030420b | ||
|
44d1e8181c | ||
|
63b34c1853 | ||
|
facd0144cb | ||
|
115e3435af | ||
|
d44cd50768 | ||
|
1afcaea4c6 | ||
|
2bd1b37717 | ||
|
2d37177316 | ||
|
abb25e2015 | ||
|
d08d075e30 | ||
|
b4c67c02a7 | ||
|
04fb6a953e | ||
|
5dce0bec8e | ||
|
481bb3fb0a | ||
|
b6960dc299 | ||
|
73104aae1f | ||
|
10a284848b | ||
|
fd6560bdd0 | ||
|
0810f617c7 | ||
|
c3ffd39450 | ||
|
0f69e0d672 | ||
|
1aa8ebe57f | ||
|
23178614d5 | ||
|
d2b6829574 | ||
|
5602715c96 | ||
|
54d0433dd4 | ||
|
f4bc313d0b | ||
|
5617de3a79 | ||
|
2d62f0ff06 | ||
|
1c79f6b1b6 | ||
|
bf01153c6b | ||
|
c43b37baef | ||
|
d4942efd8e | ||
|
ea9f635b1a | ||
|
7eaa0e16b3 | ||
|
1b97d8fd48 | ||
|
89a29b9b10 | ||
|
2baac1a6d7 | ||
|
cd296aa9ac | ||
|
959d168352 | ||
|
6cd60951ba | ||
|
3898c0c0ef | ||
|
fe4d139817 | ||
|
d95f3ca59f | ||
|
7f6c03ce17 | ||
|
394d0eabef | ||
|
a8ae496fda | ||
|
1787f4421b | ||
|
36351a5dd9 | ||
|
d009ce31ca | ||
|
44eafeeae5 | ||
|
21165eb3e0 | ||
|
2ef3a33fbf | ||
|
f74be0402f | ||
|
a60cb366b2 | ||
|
58e2ef187d | ||
|
ae80fd8578 | ||
|
c17f2efca6 | ||
|
4a185639b9 | ||
|
dae7e7d507 | ||
|
e33e3cc40f | ||
|
36ec1daf3a | ||
|
50aff9cfb6 | ||
|
058a0f9fb2 | ||
|
0c955efa8b | ||
|
a62916a63d | ||
|
af7a4b5d3d | ||
|
2ae3929dd6 | ||
|
ebd30f4861 | ||
|
afc9ea08f3 | ||
|
78f9f7e2dd | ||
|
c44b827922 | ||
|
fb30f7ec8f | ||
|
e878d5ce07 | ||
|
f727a38b69 | ||
|
c11a5384da | ||
|
ed92cbd4b8 | ||
|
a9ea32772f | ||
|
92f5cca65b | ||
|
57b064f590 | ||
|
9729434926 | ||
|
9d9dffee74 | ||
|
b3f374f4ea | ||
|
50e07d422f | ||
|
631ed4956a | ||
|
0eca1c8d03 | ||
|
e38e4574ad | ||
|
be2d3f3637 | ||
|
0e3d779e24 | ||
|
4d25336d87 | ||
|
74f76a2835 | ||
|
84560a6f44 | ||
|
6fde693e7a | ||
|
2e46d9ba33 | ||
|
e36f8deb08 | ||
|
1631b422f1 | ||
|
b58d809063 | ||
|
9e34314dbc | ||
|
e4aa218b5f | ||
|
31722477d4 | ||
|
ec82105433 | ||
|
146e164f04 | ||
|
7d37c93988 | ||
|
73dffacd9a | ||
|
d37304fa68 | ||
|
62f4da6063 | ||
|
760da08ab7 | ||
|
e68c4d4408 | ||
|
46a200aa1f | ||
|
c422039335 | ||
|
0579c8565d | ||
|
9f25880a59 | ||
|
05f1819f7d | ||
|
fa2149f957 | ||
|
c21a79e029 | ||
|
03e31ebb5e | ||
|
3c20e5f3af | ||
|
9a9dd9e075 | ||
|
7189986c03 | ||
|
b407d8d315 | ||
|
41fa2a6208 | ||
|
fe00c4c373 | ||
|
7248a76c63 | ||
|
ee3c618797 | ||
|
a1241ebedb | ||
|
af78d998db | ||
|
d96c235ffe | ||
|
79ca1b5f4e | ||
|
0f68735e1c | ||
|
82abee37de | ||
|
507040f1fd | ||
|
42dc8486e9 | ||
|
6c655634bc | ||
|
f2166b97b8 | ||
|
da88e02be0 | ||
|
0d56b7d251 | ||
|
0a089efcac | ||
|
89ab360391 | ||
|
2bd97d9a99 | ||
|
103b9056e4 | ||
|
23c4352c18 | ||
|
2dddaa36d5 | ||
|
8ab7cf2388 | ||
|
f191086adb | ||
|
68b446db18 | ||
|
3d49d81856 | ||
|
96493425d1 | ||
|
419975285c | ||
|
aa5bde122e | ||
|
0fa3c2bd8d | ||
|
b9249a4d96 | ||
|
6638ca270f | ||
|
9bfef892f8 | ||
|
32e5efec7c | ||
|
36457455ca | ||
|
062c148e43 | ||
|
2314ce8004 | ||
|
a3ff73903a | ||
|
7c8445707e | ||
|
291e73da4b | ||
|
286a29ca3e | ||
|
71cf6c6a5e | ||
|
1e8f0adaf8 | ||
|
33531244aa | ||
|
06049a9a28 | ||
|
d313f5fdf5 | ||
|
f4868126c1 | ||
|
00147e98dd | ||
|
6d22663ca2 | ||
|
756bb9cf5e | ||
|
399d7968f5 | ||
|
966b68f42e | ||
|
134c551c12 | ||
|
9aeca15355 | ||
|
6c6d31830b | ||
|
e8cc321898 | ||
|
e73fe06f7e | ||
|
98b579c042 | ||
|
7b3a5c1afd | ||
|
7e2e49e129 | ||
|
e8ef630424 | ||
|
8805bcf6f6 | ||
|
ff5c9a3aa0 | ||
|
3a274dcaa7 | ||
|
ddfededf02 | ||
|
e1785898ba | ||
|
ae09200f42 | ||
|
847984f678 | ||
|
5971d155ef | ||
|
42305672ac | ||
|
25a56d9f72 | ||
|
cea52c0ac7 | ||
|
1b33ff9c25 | ||
|
8f9f08b96f | ||
|
594ba205bb | ||
|
3c65b46aa5 | ||
|
1cf9c76329 | ||
|
495f5c71c3 | ||
|
7e80f607b7 | ||
|
d93732e451 | ||
|
1b57bc7889 | ||
|
c0499df4ec | ||
|
d90ac519f7 | ||
|
a0e92b6969 | ||
|
df49dd23e2 | ||
|
d4525da6bc | ||
|
25b11bd20b | ||
|
9e373a9b0d | ||
|
705aac419a | ||
|
4fb61646b4 | ||
|
f6e642f72e | ||
|
565bd87959 | ||
|
5751f7e5a3 | ||
|
f5a755d4fc | ||
|
a500de8ab1 | ||
|
303548a5fe | ||
|
68de905698 | ||
|
9240b9868b | ||
|
0e2e155cc6 | ||
|
bffa0088b4 | ||
|
2e993857e8 | ||
|
117a376fc3 | ||
|
1daffedde0 | ||
|
0e8fdd76a6 | ||
|
7ff4f29bcb | ||
|
9e4cff2b23 | ||
|
4aaea89f2c | ||
|
4fbf7b38fb | ||
|
76075401f9 | ||
|
e2a20dd63d | ||
|
b52a1f3eb1 | ||
|
7fd5a88122 | ||
|
1a1baa5cda | ||
|
577d671a0c | ||
|
380029ffd8 | ||
|
e2f1fc307f | ||
|
76cc27a267 | ||
|
e8a6f30e4e | ||
|
fe6021a3d6 | ||
|
563c54702b | ||
|
4d67d27ba0 | ||
|
edf3876a57 | ||
|
2d10f255c2 | ||
|
ee76cc6761 | ||
|
f197e6623b | ||
|
42a9809450 | ||
|
444f80a933 | ||
|
4b985c818a | ||
|
2e62fe7b72 | ||
|
ccd182aed9 | ||
|
615eef3fdd | ||
|
d4e4907363 | ||
|
c205e93876 | ||
|
3b24bb99bb | ||
|
2814cd1b2a | ||
|
5285e1ac14 | ||
|
48a999cf91 | ||
|
3117c8846e | ||
|
6bb297e76f | ||
|
bc698f67ea | ||
|
f1c859aaa3 | ||
|
2d0aa207d4 | ||
|
4a75e9c262 | ||
|
ee7c4b8863 | ||
|
f782979d6c | ||
|
53cce6510c | ||
|
53252b84fd | ||
|
8f3cf38f77 | ||
|
f33766a062 | ||
|
ac5e62c65d | ||
|
e2289ce1e6 | ||
|
f0e2913802 | ||
|
1fa928b98f | ||
|
1c691cca33 | ||
|
69e1eb3eff | ||
|
90794cb515 | ||
|
28d7e24d30 | ||
|
6a62f781e9 | ||
|
fb6c67fa04 | ||
|
03e9e3dbdb | ||
|
5520992861 | ||
|
5f1502eea7 | ||
|
b3560ff525 | ||
|
8030167ffc | ||
|
fd2c1615cf | ||
|
b976239580 | ||
|
7d8d773f8f | ||
|
b930ad4da7 | ||
|
abad7cdf16 | ||
|
0e5eb036b0 | ||
|
d995bfc081 | ||
|
c920070ce2 | ||
|
277f5e538f | ||
|
89f197b9d4 | ||
|
c35ff3174a | ||
|
94085ee940 | ||
|
c841fa3620 | ||
|
69b2c1f4d2 | ||
|
2f7a1c941e | ||
|
c06fb8daf6 | ||
|
26948a058a | ||
|
1220564f30 | ||
|
ea4be9dd0c | ||
|
1ccda0b598 | ||
|
eb3b67ffd6 | ||
|
4819b5ac5d | ||
|
591b795aa3 | ||
|
ac21ed7d18 | ||
|
d9c66a2db0 | ||
|
d740814f88 | ||
|
cdf1ebf3f7 | ||
|
f2fab5d4ee | ||
|
21a6927279 | ||
|
92190bbc54 | ||
|
9ad005e31f | ||
|
f5c56e02da | ||
|
c25c0d37c5 | ||
|
4ba1c5bcfc |
@@ -29,7 +29,7 @@ $paths = [
|
||||
$current . '/../../database',
|
||||
$current . '/../../routes',
|
||||
$current . '/../../tests',
|
||||
$current . '/../../resources/lang',
|
||||
$current . '/../../resources/lang/en_US',
|
||||
];
|
||||
|
||||
$finder = PhpCsFixer\Finder::create()
|
||||
@@ -61,6 +61,7 @@ return $config->setRules(
|
||||
'comment_to_phpdoc' => false, // breaks phpstan lines in combination with PHPStorm.
|
||||
'type_declaration_spaces' => false,
|
||||
'cast_spaces' => false,
|
||||
'phpdoc_to_comment' => false, // do not overrule single line comment style, breaks phpstan.
|
||||
|
||||
// complex rules
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
|
290
.ci/php-cs-fixer/composer.lock
generated
290
.ci/php-cs-fixer/composer.lock
generated
@@ -97,13 +97,13 @@
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.x-dev"
|
||||
},
|
||||
"phpstan": {
|
||||
"includes": [
|
||||
"extension.neon"
|
||||
]
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -406,16 +406,16 @@
|
||||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v3.65.0",
|
||||
"version": "v3.75.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||
"reference": "79d4f3e77b250a7d8043d76c6af8f0695e8a469f"
|
||||
"reference": "399a128ff2fdaf4281e4e79b755693286cdf325c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/79d4f3e77b250a7d8043d76c6af8f0695e8a469f",
|
||||
"reference": "79d4f3e77b250a7d8043d76c6af8f0695e8a469f",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/399a128ff2fdaf4281e4e79b755693286cdf325c",
|
||||
"reference": "399a128ff2fdaf4281e4e79b755693286cdf325c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -423,6 +423,7 @@
|
||||
"composer/semver": "^3.4",
|
||||
"composer/xdebug-handler": "^3.0.3",
|
||||
"ext-filter": "*",
|
||||
"ext-hash": "*",
|
||||
"ext-json": "*",
|
||||
"ext-tokenizer": "*",
|
||||
"fidry/cpu-core-counter": "^1.2",
|
||||
@@ -432,31 +433,31 @@
|
||||
"react/promise": "^2.0 || ^3.0",
|
||||
"react/socket": "^1.0",
|
||||
"react/stream": "^1.0",
|
||||
"sebastian/diff": "^4.0 || ^5.0 || ^6.0",
|
||||
"symfony/console": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/filesystem": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/finder": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/options-resolver": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/polyfill-mbstring": "^1.28",
|
||||
"symfony/polyfill-php80": "^1.28",
|
||||
"symfony/polyfill-php81": "^1.28",
|
||||
"symfony/process": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/stopwatch": "^5.4 || ^6.0 || ^7.0"
|
||||
"sebastian/diff": "^4.0 || ^5.1 || ^6.0 || ^7.0",
|
||||
"symfony/console": "^5.4 || ^6.4 || ^7.0",
|
||||
"symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0",
|
||||
"symfony/filesystem": "^5.4 || ^6.4 || ^7.0",
|
||||
"symfony/finder": "^5.4 || ^6.4 || ^7.0",
|
||||
"symfony/options-resolver": "^5.4 || ^6.4 || ^7.0",
|
||||
"symfony/polyfill-mbstring": "^1.31",
|
||||
"symfony/polyfill-php80": "^1.31",
|
||||
"symfony/polyfill-php81": "^1.31",
|
||||
"symfony/process": "^5.4 || ^6.4 || ^7.2",
|
||||
"symfony/stopwatch": "^5.4 || ^6.4 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"facile-it/paraunit": "^1.3.1 || ^2.4",
|
||||
"infection/infection": "^0.29.8",
|
||||
"justinrainbow/json-schema": "^5.3 || ^6.0",
|
||||
"facile-it/paraunit": "^1.3.1 || ^2.6",
|
||||
"infection/infection": "^0.29.14",
|
||||
"justinrainbow/json-schema": "^5.3 || ^6.2",
|
||||
"keradus/cli-executor": "^2.1",
|
||||
"mikey179/vfsstream": "^1.6.12",
|
||||
"php-coveralls/php-coveralls": "^2.7",
|
||||
"php-cs-fixer/accessible-object": "^1.1",
|
||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.5",
|
||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.5",
|
||||
"phpunit/phpunit": "^9.6.21 || ^10.5.38 || ^11.4.3",
|
||||
"symfony/var-dumper": "^5.4.47 || ^6.4.15 || ^7.1.8",
|
||||
"symfony/yaml": "^5.4.45 || ^6.4.13 || ^7.1.6"
|
||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6",
|
||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6",
|
||||
"phpunit/phpunit": "^9.6.22 || ^10.5.45 || ^11.5.12",
|
||||
"symfony/var-dumper": "^5.4.48 || ^6.4.18 || ^7.2.3",
|
||||
"symfony/yaml": "^5.4.45 || ^6.4.18 || ^7.2.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "For handling output formats in XML",
|
||||
@@ -497,7 +498,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.65.0"
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.75.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -505,7 +506,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-25T00:39:24+00:00"
|
||||
"time": "2025-03-31T18:40:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
@@ -734,33 +735,33 @@
|
||||
},
|
||||
{
|
||||
"name": "react/child-process",
|
||||
"version": "v0.6.5",
|
||||
"version": "v0.6.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/reactphp/child-process.git",
|
||||
"reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43"
|
||||
"reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/reactphp/child-process/zipball/e71eb1aa55f057c7a4a0d08d06b0b0a484bead43",
|
||||
"reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43",
|
||||
"url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159",
|
||||
"reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"evenement/evenement": "^3.0 || ^2.0 || ^1.0",
|
||||
"php": ">=5.3.0",
|
||||
"react/event-loop": "^1.2",
|
||||
"react/stream": "^1.2"
|
||||
"react/stream": "^1.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35",
|
||||
"react/socket": "^1.8",
|
||||
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36",
|
||||
"react/socket": "^1.16",
|
||||
"sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"React\\ChildProcess\\": "src"
|
||||
"React\\ChildProcess\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
@@ -797,19 +798,15 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/reactphp/child-process/issues",
|
||||
"source": "https://github.com/reactphp/child-process/tree/v0.6.5"
|
||||
"source": "https://github.com/reactphp/child-process/tree/v0.6.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/WyriHaximus",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/clue",
|
||||
"type": "github"
|
||||
"url": "https://opencollective.com/reactphp",
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2022-09-16T13:41:56+00:00"
|
||||
"time": "2025-01-01T16:37:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "react/dns",
|
||||
@@ -1192,29 +1189,29 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/diff",
|
||||
"version": "6.0.2",
|
||||
"version": "7.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/diff.git",
|
||||
"reference": "b4ccd857127db5d41a5b676f24b51371d76d8544"
|
||||
"reference": "7ab1ea946c012266ca32390913653d844ecd085f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544",
|
||||
"reference": "b4ccd857127db5d41a5b676f24b51371d76d8544",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f",
|
||||
"reference": "7ab1ea946c012266ca32390913653d844ecd085f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2"
|
||||
"php": ">=8.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^11.0",
|
||||
"symfony/process": "^4.2 || ^5"
|
||||
"phpunit/phpunit": "^12.0",
|
||||
"symfony/process": "^7.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "6.0-dev"
|
||||
"dev-main": "7.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1247,7 +1244,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/diff/issues",
|
||||
"security": "https://github.com/sebastianbergmann/diff/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/6.0.2"
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/7.0.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1255,20 +1252,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-03T04:53:05+00:00"
|
||||
"time": "2025-02-07T04:55:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v7.1.8",
|
||||
"version": "v7.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5"
|
||||
"reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/ff04e5b5ba043d2badfb308197b9e6b42883fcd5",
|
||||
"reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/0e2e3f38c192e93e622e41ec37f4ca70cfedf218",
|
||||
"reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1332,7 +1329,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v7.1.8"
|
||||
"source": "https://github.com/symfony/console/tree/v7.2.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1348,7 +1345,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-06T14:23:19+00:00"
|
||||
"time": "2025-04-07T19:09:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
@@ -1369,12 +1366,12 @@
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/contracts",
|
||||
"name": "symfony/contracts"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "3.5-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
"url": "https://github.com/symfony/contracts"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1419,16 +1416,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v7.1.6",
|
||||
"version": "v7.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "87254c78dd50721cfd015b62277a8281c5589702"
|
||||
"reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/87254c78dd50721cfd015b62277a8281c5589702",
|
||||
"reference": "87254c78dd50721cfd015b62277a8281c5589702",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1",
|
||||
"reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1479,7 +1476,7 @@
|
||||
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v7.1.6"
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1495,7 +1492,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-25T14:20:29+00:00"
|
||||
"time": "2024-09-25T14:21:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher-contracts",
|
||||
@@ -1517,12 +1514,12 @@
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/contracts",
|
||||
"name": "symfony/contracts"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "3.5-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
"url": "https://github.com/symfony/contracts"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1575,16 +1572,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v7.1.6",
|
||||
"version": "v7.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4"
|
||||
"reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/c835867b3c62bb05c7fe3d637c871c7ae52024d4",
|
||||
"reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
|
||||
"reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1621,7 +1618,7 @@
|
||||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v7.1.6"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v7.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1637,20 +1634,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-10-25T15:11:02+00:00"
|
||||
"time": "2024-10-25T15:15:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v7.1.6",
|
||||
"version": "v7.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8"
|
||||
"reference": "87a71856f2f56e4100373e92529eed3171695cfb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/2cb89664897be33f78c65d3d2845954c8d7a43b8",
|
||||
"reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb",
|
||||
"reference": "87a71856f2f56e4100373e92529eed3171695cfb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1685,7 +1682,7 @@
|
||||
"description": "Finds files and directories via an intuitive fluent interface",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/finder/tree/v7.1.6"
|
||||
"source": "https://github.com/symfony/finder/tree/v7.2.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1701,20 +1698,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-10-01T08:31:23+00:00"
|
||||
"time": "2024-12-30T19:00:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
"version": "v7.1.9",
|
||||
"version": "v7.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/options-resolver.git",
|
||||
"reference": "0f4099f5306a92487d13b2a4589068c36a93c447"
|
||||
"reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/0f4099f5306a92487d13b2a4589068c36a93c447",
|
||||
"reference": "0f4099f5306a92487d13b2a4589068c36a93c447",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50",
|
||||
"reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1752,7 +1749,7 @@
|
||||
"options"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/options-resolver/tree/v7.1.9"
|
||||
"source": "https://github.com/symfony/options-resolver/tree/v7.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1768,11 +1765,11 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-20T11:08:58+00:00"
|
||||
"time": "2024-11-20T11:17:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
@@ -1796,8 +1793,8 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1831,7 +1828,7 @@
|
||||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1851,7 +1848,7 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
|
||||
@@ -1872,8 +1869,8 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1909,7 +1906,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1929,7 +1926,7 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
@@ -1950,8 +1947,8 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1990,7 +1987,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2010,19 +2007,20 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
|
||||
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341",
|
||||
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
|
||||
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-iconv": "*",
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"provide": {
|
||||
@@ -2034,8 +2032,8 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -2070,7 +2068,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2086,20 +2084,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
"time": "2024-12-23T08:48:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8"
|
||||
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
|
||||
"reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
|
||||
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2108,8 +2106,8 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -2150,7 +2148,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2166,11 +2164,11 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
"time": "2025-01-02T08:10:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php81",
|
||||
"version": "v1.31.0",
|
||||
"version": "v1.32.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php81.git",
|
||||
@@ -2188,8 +2186,8 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -2226,7 +2224,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0"
|
||||
"source": "https://github.com/symfony/polyfill-php81/tree/v1.32.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2246,16 +2244,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v7.1.8",
|
||||
"version": "v7.2.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892"
|
||||
"reference": "87b7c93e57df9d8e39a093d32587702380ff045d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/42783370fda6e538771f7c7a36e9fa2ee3a84892",
|
||||
"reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d",
|
||||
"reference": "87b7c93e57df9d8e39a093d32587702380ff045d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2287,7 +2285,7 @@
|
||||
"description": "Executes commands in sub-processes",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/process/tree/v7.1.8"
|
||||
"source": "https://github.com/symfony/process/tree/v7.2.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2303,7 +2301,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-06T14:23:19+00:00"
|
||||
"time": "2025-03-13T12:21:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
@@ -2329,12 +2327,12 @@
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/contracts",
|
||||
"name": "symfony/contracts"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "3.5-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
"url": "https://github.com/symfony/contracts"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -2390,16 +2388,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/stopwatch",
|
||||
"version": "v7.1.6",
|
||||
"version": "v7.2.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/stopwatch.git",
|
||||
"reference": "8b4a434e6e7faf6adedffb48783a5c75409a1a05"
|
||||
"reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/8b4a434e6e7faf6adedffb48783a5c75409a1a05",
|
||||
"reference": "8b4a434e6e7faf6adedffb48783a5c75409a1a05",
|
||||
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd",
|
||||
"reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2432,7 +2430,7 @@
|
||||
"description": "Provides a way to profile code",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/stopwatch/tree/v7.1.6"
|
||||
"source": "https://github.com/symfony/stopwatch/tree/v7.2.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2448,20 +2446,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-25T14:20:29+00:00"
|
||||
"time": "2025-02-24T10:49:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v7.1.8",
|
||||
"version": "v7.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "591ebd41565f356fcd8b090fe64dbb5878f50281"
|
||||
"reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/591ebd41565f356fcd8b090fe64dbb5878f50281",
|
||||
"reference": "591ebd41565f356fcd8b090fe64dbb5878f50281",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/a214fe7d62bd4df2a76447c67c6b26e1d5e74931",
|
||||
"reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2519,7 +2517,7 @@
|
||||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v7.1.8"
|
||||
"source": "https://github.com/symfony/string/tree/v7.2.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2535,7 +2533,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-13T13:31:21+00:00"
|
||||
"time": "2025-04-20T20:18:16+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
|
@@ -26,10 +26,9 @@ SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
cd $SCRIPT_DIR/php-cs-fixer
|
||||
composer update --quiet
|
||||
rm -f .php-cs-fixer.cache
|
||||
PHP_CS_FIXER_IGNORE_ENV=true
|
||||
./vendor/bin/php-cs-fixer fix \
|
||||
PHP_CS_FIXER_IGNORE_ENV=true ./vendor/bin/php-cs-fixer fix \
|
||||
--config $SCRIPT_DIR/php-cs-fixer/.php-cs-fixer.php \
|
||||
--format=txt \
|
||||
--format=txt -v \
|
||||
--allow-risky=yes
|
||||
|
||||
EXIT_CODE=$?
|
||||
|
@@ -1,61 +1,36 @@
|
||||
parameters:
|
||||
scanFiles:
|
||||
- ../_ide_helper_models.php
|
||||
universalObjectCratesClasses:
|
||||
- Illuminate\Database\Eloquent\Model
|
||||
# TODO: slowly remove these parameters and fix the issues found.
|
||||
reportUnmatchedIgnoredErrors: false
|
||||
ignoreErrors:
|
||||
# TODO: slowly remove these exceptions and fix the issues found.
|
||||
- '#Dynamic call to static method#' # all the Laravel ORM things depend on this.
|
||||
- '#Control structures using switch should not be used.#' # switch is fine in some cases.
|
||||
- '#with no value type specified in iterable type array#' # remove this rule when all other issues are solved.
|
||||
- '#has no value type specified in iterable type array#' # remove this rule when all other issues are solved.
|
||||
- '#is not allowed to extend#'
|
||||
- '#does not specify its types#'
|
||||
- '#switch is forbidden to use#'
|
||||
- '#is neither abstract nor final#'
|
||||
- '#on left side of \?\?\= always exists and is not nullable#'
|
||||
- '#has a nullable return type declaration#' # perhaps throw errors instead?
|
||||
- '#with a nullable type declaration#' # decide what action should be if param is null.
|
||||
- '#with null as default value#'
|
||||
-
|
||||
message: '#Constructor in [a-zA-Z0-9\\_]+ has parameter \$[a-zA-Z0-9\\_]+ with default value#'
|
||||
paths:
|
||||
- ../app/Exceptions/IntervalException.php
|
||||
- ../app/Support/Navigation.php
|
||||
-
|
||||
message: '#but containers should not be injected#'
|
||||
paths:
|
||||
- ../app/Support/Authentication/RemoteUserGuard.php
|
||||
-
|
||||
message: '#Function compact\(\) should not be used#' # too useful in template rendering.
|
||||
paths:
|
||||
- ../app/Generator/Report/Account/MonthReportGenerator.php
|
||||
- ../app/Generator/Report/Audit/MonthReportGenerator.php
|
||||
- ../app/Generator/Report/Budget/MonthReportGenerator.php
|
||||
- ../app/Generator/Report/Category/MonthReportGenerator.php
|
||||
- ../app/Generator/Report/Standard/MonthReportGenerator.php
|
||||
- ../app/Generator/Report/Standard/MultiYearReportGenerator.php
|
||||
- ../app/Generator/Report/Standard/YearReportGenerator.php
|
||||
- ../app/Generator/Report/Tag/MonthReportGenerator.php
|
||||
- ../app/Http/Controllers/Account/*.php
|
||||
- ../app/Http/Controllers/Admin/*.php
|
||||
- ../app/Http/Controllers/*.php
|
||||
- ../app/Support/ExpandedForm.php
|
||||
- ../app/Support/Form/AccountForm.php
|
||||
- ../app/Support/Form/CurrencyForm.php
|
||||
- ../app/Support/Form/FormSupport.php
|
||||
-
|
||||
message: '#Either catch a more specific exception#'
|
||||
paths:
|
||||
- ../app/Support/Form/FormSupport.php
|
||||
- ../_ide_helper
|
||||
paths:
|
||||
- ../app
|
||||
- ../database
|
||||
- ../routes
|
||||
- ../config
|
||||
- ../bootstrap/app.php
|
||||
universalObjectCratesClasses:
|
||||
- Illuminate\Database\Eloquent\Model
|
||||
# TODO: slowly remove these parameters and fix the issues found.
|
||||
reportUnmatchedIgnoredErrors: true
|
||||
ignoreErrors:
|
||||
# TODO: slowly remove these exceptions and fix the issues found.
|
||||
- '#Dynamic call to static method#' # all the Laravel ORM things depend on this.
|
||||
- identifier: varTag.nativeType
|
||||
- identifier: varTag.type
|
||||
-
|
||||
identifier: larastan.noEnvCallsOutsideOfConfig
|
||||
path: ../app/Console/Commands/System/CreatesDatabase.php
|
||||
- identifier: missingType.iterableValue # not interesting enough to fix.
|
||||
- identifier: missingType.generics # not interesting enough to fix.
|
||||
- "#Parameter \\#[1-2] \\$num[1-2] of function bc[a-z]+ expects numeric-string, [a-z\\-|&]+ given#"
|
||||
- '#expects view-string, string given#'
|
||||
- '#expects view-string\|null, string given#'
|
||||
|
||||
# phpstan can't handle this so we ignore them.
|
||||
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::before#'
|
||||
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::after#'
|
||||
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::withTrashed#'
|
||||
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::accountTypeIn#'
|
||||
- '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\BelongsTo::withTrashed#'
|
||||
|
||||
# The level 8 is the highest level. original was 5
|
||||
# 7 is more than enough, higher just leaves NULL things.
|
||||
|
21
.ci/rector.php
Normal file
21
.ci/rector.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Config\RectorConfig;
|
||||
|
||||
return RectorConfig::configure()
|
||||
->withPaths([
|
||||
__DIR__ . '/../app',
|
||||
__DIR__ . '/../bootstrap',
|
||||
__DIR__ . '/../config',
|
||||
__DIR__ . '/../public',
|
||||
__DIR__ . '/../resources',
|
||||
__DIR__ . '/../routes',
|
||||
__DIR__ . '/../tests',
|
||||
])
|
||||
// uncomment to reach your current PHP version
|
||||
->withPhpSets()
|
||||
->withTypeCoverageLevel(0)
|
||||
->withDeadCodeLevel(0)
|
||||
->withCodeQualityLevel(0);
|
28
.ci/rector.sh
Executable file
28
.ci/rector.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#
|
||||
# phpstan.sh
|
||||
# Copyright (c) 2021 james@firefly-iii.org
|
||||
#
|
||||
# This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# Install composer packages
|
||||
#composer install --no-scripts --no-ansi
|
||||
|
||||
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
|
||||
$SCRIPT_DIR/../vendor/bin/rector --config $SCRIPT_DIR/rector.php
|
24
.env.example
24
.env.example
@@ -19,7 +19,7 @@ SITE_OWNER=mail@example.com
|
||||
APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
|
||||
# Firefly III will launch using this language (for new users and unauthenticated visitors)
|
||||
# For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/main/resources/lang
|
||||
# For a list of available languages: https://github.com/firefly-iii/firefly-iii/blob/main/config/firefly.php#L123
|
||||
#
|
||||
# If text is still in English, remember that not everything may have been translated.
|
||||
DEFAULT_LANGUAGE=en_US
|
||||
@@ -164,6 +164,13 @@ MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_SENDMAIL_COMMAND=
|
||||
|
||||
#
|
||||
# If you use self-signed certificates for your STMP server, you can use the following settings.
|
||||
#
|
||||
MAIL_ALLOW_SELF_SIGNED=false
|
||||
MAIL_VERIFY_PEER=true
|
||||
MAIL_VERIFY_PEER_NAME=true
|
||||
|
||||
# Other mail drivers:
|
||||
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
|
||||
MAILGUN_DOMAIN=
|
||||
@@ -189,7 +196,7 @@ SEND_REPORT_JOURNALS=true
|
||||
ENABLE_EXTERNAL_MAP=false
|
||||
|
||||
#
|
||||
# Enable or disable exchange rate conversion. This function isn't used yet by Firefly III
|
||||
# Enable or disable exchange rate conversion.
|
||||
#
|
||||
ENABLE_EXCHANGE_RATES=false
|
||||
|
||||
@@ -289,13 +296,6 @@ STATIC_CRON_TOKEN=
|
||||
# However if you know what you're doing you can significantly speed up container start times.
|
||||
# Set each value to true to enable, or false to disable.
|
||||
|
||||
# Set this to true to build all locales supported by Firefly III.
|
||||
# This may take quite some time (several minutes) and is generally not recommended.
|
||||
# If you wish to change or alter the list of locales, start your Docker container with
|
||||
# `docker run -v locale.gen:/etc/locale.gen -e DKR_BUILD_LOCALE=true`
|
||||
# and make sure your preferred locales are in your own locale.gen.
|
||||
DKR_BUILD_LOCALE=false
|
||||
|
||||
# Check if the SQLite database exists. Can be skipped if you're not using SQLite.
|
||||
# Won't significantly speed up things.
|
||||
DKR_CHECK_SQLITE=true
|
||||
@@ -325,6 +325,12 @@ USE_RUNNING_BALANCE=false
|
||||
#
|
||||
FIREFLY_III_LAYOUT=v1
|
||||
|
||||
#
|
||||
# Which Query Parser implementation to use for the search engine and rules
|
||||
# 'new' is experimental, 'legacy' is the classic one
|
||||
#
|
||||
QUERY_PARSER_IMPLEMENTATION=legacy
|
||||
|
||||
#
|
||||
# Please make sure this URL matches the external URL of your Firefly III installation.
|
||||
# It is used to validate specific requests and to generate URLs in emails.
|
||||
|
33
.github/label-actions.yml
vendored
33
.github/label-actions.yml
vendored
@@ -1,16 +1,29 @@
|
||||
# Configuration for Label Actions - https://github.com/dessant/label-actions
|
||||
|
||||
# The `feature` label is added to issues
|
||||
fixed:
|
||||
issues:
|
||||
# Post a comment, `{issue-author}` is an optional placeholder
|
||||
comment: |
|
||||
Hi there!
|
||||
|
||||
This is an automatic reply. `Share and enjoy`
|
||||
|
||||
This issue has been marked as fixed. Thanks for reporting! A new version will be released in due time. Unfortunately, [I cannot give an estimate](https://docs.firefly-iii.org/references/faq/firefly-iii/general/#when-will-you-release-version-the-next-version), but [the roadmap](https://roadmap.firefly-iii.org/) is available for your reading pleasure.
|
||||
|
||||
There is no need to close the issue. It will be closed automatically.
|
||||
|
||||
Thank you for your contributions.
|
||||
feature:
|
||||
issues:
|
||||
# Post a comment, `{issue-author}` is an optional placeholder
|
||||
unlabel: feature
|
||||
comment: |
|
||||
Hi there!
|
||||
Hi there!
|
||||
|
||||
This is an automatic reply. `Share and enjoy`
|
||||
|
||||
This issue has been marked as a feature request. The requested (new) feature will become a part of Firefly III or the data importer in due course.
|
||||
This issue has been marked as a feature request.
|
||||
|
||||
If you come across this issue, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted. You can subscribe to this issue to get updates.
|
||||
|
||||
@@ -20,13 +33,13 @@ epic:
|
||||
issues:
|
||||
# Post a comment, `{issue-author}` is an optional placeholder
|
||||
comment: |
|
||||
Hi there!
|
||||
Hi there!
|
||||
|
||||
This is an automatic reply. `Share and enjoy`
|
||||
|
||||
This issue has been marked as an epic. In epics, large amounts of works are collected that will be part of a major new feature. If you have more ideas that could be a part of this epic, feel free to reply.
|
||||
|
||||
*However*, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted.
|
||||
*However*, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted.
|
||||
|
||||
If you are merely interested in this epic's progress, you can subscribe to this issue to get updates.
|
||||
|
||||
@@ -37,11 +50,11 @@ enhancement:
|
||||
issues:
|
||||
# Post a comment, `{issue-author}` is an optional placeholder
|
||||
comment: |
|
||||
Hi there!
|
||||
Hi there!
|
||||
|
||||
This is an automatic reply. `Share and enjoy`
|
||||
|
||||
This issue has been marked as an enhancement. The requested enhancement to an existing feature will become a part of Firefly III or the data importer in due course.
|
||||
This issue has been marked as an enhancement.
|
||||
|
||||
If you come across this issue, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted. You can subscribe to this issue to get updates.
|
||||
|
||||
@@ -51,7 +64,7 @@ triage:
|
||||
issues:
|
||||
# Post a comment, `{issue-author}` is an optional placeholder
|
||||
comment: |
|
||||
Hi there!
|
||||
Hi there!
|
||||
|
||||
This is an automatic reply. `Share and enjoy`
|
||||
|
||||
@@ -62,7 +75,7 @@ triage:
|
||||
needs-moar-debug:
|
||||
issues:
|
||||
comment: |
|
||||
Hi there!
|
||||
Hi there!
|
||||
|
||||
This is an automatic reply. `Share and enjoy`
|
||||
|
||||
@@ -80,7 +93,7 @@ needs-moar-debug:
|
||||
needs-moar-logs:
|
||||
issues:
|
||||
comment: |
|
||||
Hi there!
|
||||
Hi there!
|
||||
|
||||
This is an automatic reply. `Share and enjoy`
|
||||
|
||||
@@ -96,7 +109,7 @@ needs-moar-logs:
|
||||
v2-layout-issue:
|
||||
issues:
|
||||
comment: |
|
||||
Hi there!
|
||||
Hi there!
|
||||
|
||||
This is an automatic reply. `Share and enjoy`
|
||||
|
||||
|
61
.github/mergify.yml
vendored
61
.github/mergify.yml
vendored
@@ -1,5 +1,11 @@
|
||||
---
|
||||
pull_request_rules:
|
||||
- name: Make sure PR are up to date before merging
|
||||
description: This automatically updates PRs when they are out-of-date with the
|
||||
base branch to avoid semantic conflicts (next step is using a merge
|
||||
queue).
|
||||
conditions: []
|
||||
actions:
|
||||
update:
|
||||
- name: Close all on main
|
||||
conditions:
|
||||
- base=main
|
||||
@@ -8,56 +14,3 @@ pull_request_rules:
|
||||
close:
|
||||
message: Please do not open PR's on the `main` branch, but on the `develop`
|
||||
branch only. Thank you!
|
||||
- name: No translations
|
||||
conditions:
|
||||
- -author~=^dependabot(|-preview)\[bot\]$
|
||||
- base=develop
|
||||
- or:
|
||||
- files~=^resources/lang/bg_BG
|
||||
- files~=^resources/lang/ca_ES
|
||||
- files~=^resources/lang/cs_CZ
|
||||
- files~=^resources/lang/da_DK
|
||||
- files~=^resources/lang/de_DE
|
||||
- files~=^resources/lang/el_GR
|
||||
- files~=^resources/lang/en_GB
|
||||
- files~=^resources/lang/es_ES
|
||||
- files~=^resources/lang/et_EE
|
||||
- files~=^resources/lang/fa_IR
|
||||
- files~=^resources/lang/fi_FI
|
||||
- files~=^resources/lang/fr_FR
|
||||
- files~=^resources/lang/he_IL
|
||||
- files~=^resources/lang/hu_HU
|
||||
- files~=^resources/lang/id_ID
|
||||
- files~=^resources/lang/is_IS
|
||||
- files~=^resources/lang/it_IT
|
||||
- files~=^resources/lang/ja_JP
|
||||
- files~=^resources/lang/ko_KR
|
||||
- files~=^resources/lang/lt_LT
|
||||
- files~=^resources/lang/nb_NO
|
||||
- files~=^resources/lang/nl_NL
|
||||
- files~=^resources/lang/pl_PL
|
||||
- files~=^resources/lang/pt_BR
|
||||
- files~=^resources/lang/pt_PT
|
||||
- files~=^resources/lang/ro_RO
|
||||
- files~=^resources/lang/ru_RU
|
||||
- files~=^resources/lang/si_LK
|
||||
- files~=^resources/lang/sk_SK
|
||||
- files~=^resources/lang/sl_SI
|
||||
- files~=^resources/lang/sr_CS
|
||||
- files~=^resources/lang/sv_SE
|
||||
- files~=^resources/lang/th_TH
|
||||
- files~=^resources/lang/tlh_AA
|
||||
- files~=^resources/lang/tr_TR
|
||||
- files~=^resources/lang/uk_UA
|
||||
- files~=^resources/lang/vi_VN
|
||||
- files~=^resources/lang/zh_CN
|
||||
- files~=^resources/lang/zh_TW
|
||||
actions:
|
||||
comment:
|
||||
message: >
|
||||
Please do not submit translated strings in your PR. If you need new
|
||||
sentences to be translated, add them to the `en_US` language strings.
|
||||
New or changed translations for other languages can be submitted at
|
||||
https://crowdin.com/project/firefly-iii
|
||||
|
||||
Thank you!
|
||||
|
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -21,5 +21,3 @@ Changes in this pull request:
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
@JC5
|
||||
|
2
.github/workflows/close-duplicates.yml
vendored
2
.github/workflows/close-duplicates.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
close_duplicates:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: github/command@v1.2.2
|
||||
- uses: github/command@v2.0.0
|
||||
id: command
|
||||
with:
|
||||
allowed_contexts: "issue"
|
||||
|
2
.github/workflows/closed-issues.yml
vendored
2
.github/workflows/closed-issues.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
command_and_close:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: aws-actions/closed-issue-message@v1
|
||||
- uses: aws-actions/closed-issue-message@v2
|
||||
with:
|
||||
message: |
|
||||
Hi there! This is an automatic reply. `Share and enjoy`
|
||||
|
453
.github/workflows/release.yml
vendored
453
.github/workflows/release.yml
vendored
@@ -4,9 +4,13 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Release "v1.2.3" or "develop"'
|
||||
description: 'Release "v1.2.3" or "develop" or "branch-abc"'
|
||||
required: true
|
||||
default: 'develop'
|
||||
phpversion:
|
||||
description: 'PHP version'
|
||||
required: true
|
||||
default: '8.4'
|
||||
schedule:
|
||||
- cron: '0 3 * * MON'
|
||||
|
||||
@@ -18,27 +22,65 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Switch branch
|
||||
run: |
|
||||
if [[ "develop" == "$version" ]]; then
|
||||
git checkout --track origin/develop
|
||||
git pull
|
||||
else
|
||||
git config user.name github-actions
|
||||
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
||||
git checkout --track origin/develop
|
||||
git pull
|
||||
git checkout main
|
||||
git merge develop
|
||||
fi
|
||||
env:
|
||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
||||
- name: Import GPG key
|
||||
uses: crazy-max/ghaction-import-gpg@v6
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
passphrase: ${{ secrets.PASSPHRASE }}
|
||||
git_user_signingkey: true
|
||||
git_commit_gpgsign: true
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.3'
|
||||
php-version: ${{ github.event.inputs.phpversion }}
|
||||
extensions: mbstring, intl, zip, bcmath
|
||||
- name: crowdin action
|
||||
- name: Switch and pull
|
||||
run: |
|
||||
#
|
||||
# Always check out origin/develop, unless its a branch release.
|
||||
#
|
||||
BRANCH_TO_PULL=origin/develop
|
||||
if [[ "$version" == branch* ]]; then
|
||||
BRANCH_TO_PULL=origin/$version
|
||||
fi
|
||||
|
||||
echo "Version is '$version', check out '$BRANCH_TO_PULL'-branch"
|
||||
|
||||
git checkout --track $BRANCH_TO_PULL
|
||||
git pull
|
||||
echo "Current branch is $(git branch --show-current)"
|
||||
env:
|
||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
||||
- name: Configure Git
|
||||
run: |
|
||||
# do some configuration
|
||||
sudo timedatectl set-timezone Europe/Amsterdam
|
||||
git config user.name JC5
|
||||
git config user.email release@firefly-iii.org
|
||||
git config advice.addIgnoredFile false
|
||||
git config push.autoSetupRemote true
|
||||
- name: Lint PHP
|
||||
run: |
|
||||
php_lint_file()
|
||||
{
|
||||
local php_file="$1"
|
||||
php -l "$php_file" &> /dev/null
|
||||
if [ "$?" -ne 0 ]
|
||||
then
|
||||
echo -e "[FAIL] $php_file"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
export -f php_lint_file
|
||||
|
||||
find . -path ./vendor -prune -o -name '*.php' | parallel -j 4 php_lint_file {}
|
||||
|
||||
if [ "$?" -ne 0 ]
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
- name: Crowdin action
|
||||
uses: crowdin/github-action@v2
|
||||
with:
|
||||
upload_sources: true
|
||||
@@ -49,15 +91,6 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
CROWDIN_PROJECT_NR: ${{ secrets.CROWDIN_PROJECT_NR }}
|
||||
CROWDIN_TOKEN: ${{ secrets.CROWDIN_TOKEN }}
|
||||
- name: Cleanup translations
|
||||
id: cleanup-transactions
|
||||
uses: JC5/firefly-iii-dev@main
|
||||
with:
|
||||
action: 'ff3:crowdin-warning'
|
||||
output: ''
|
||||
env:
|
||||
FIREFLY_III_ROOT: /github/workspace
|
||||
GH_TOKEN: ''
|
||||
- name: Cleanup changelog
|
||||
id: cleanup-changelog
|
||||
uses: JC5/firefly-iii-dev@main
|
||||
@@ -76,15 +109,6 @@ jobs:
|
||||
env:
|
||||
FIREFLY_III_ROOT: /github/workspace
|
||||
GH_TOKEN: ''
|
||||
- name: Extract changelog
|
||||
id: extract-changelog
|
||||
uses: JC5/firefly-iii-dev@main
|
||||
with:
|
||||
action: 'ff3:extract-changelog'
|
||||
output: 'output'
|
||||
env:
|
||||
FIREFLY_III_ROOT: /github/workspace
|
||||
GH_TOKEN: ""
|
||||
- name: Replace version
|
||||
id: replace-version
|
||||
uses: JC5/firefly-iii-dev@main
|
||||
@@ -133,19 +157,9 @@ jobs:
|
||||
rm -rf vendor composer.lock
|
||||
composer update --no-dev --no-scripts --no-plugins -q
|
||||
sudo chown -R runner:docker resources/lang
|
||||
.ci/phpcs.sh
|
||||
- name: Import GPG key
|
||||
uses: crazy-max/ghaction-import-gpg@v6
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
passphrase: ${{ secrets.PASSPHRASE }}
|
||||
- name: Release
|
||||
.ci/phpcs.sh || true
|
||||
- name: Calculate variables
|
||||
run: |
|
||||
# do some configuration
|
||||
sudo timedatectl set-timezone Europe/Amsterdam
|
||||
git config user.name github-actions
|
||||
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
||||
git config advice.addIgnoredFile false
|
||||
|
||||
# set some variables
|
||||
releaseName=$version
|
||||
@@ -153,19 +167,25 @@ jobs:
|
||||
zipName=FireflyIII-$version.zip
|
||||
tarName=FireflyIII-$version.tar.gz
|
||||
|
||||
# update composer (again)
|
||||
composer update --no-dev --no-scripts --no-plugins
|
||||
composer dump-autoload
|
||||
|
||||
# if this is a develop build, slightly different variable names.
|
||||
if [[ "develop" == "$version" ]]; then
|
||||
[[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0;
|
||||
#[[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0;
|
||||
releaseName=$version-$(date +'%Y%m%d')
|
||||
originalName=$releaseName
|
||||
zipName=FireflyIII-develop.zip
|
||||
tarName=FireflyIII-develop.tar.gz
|
||||
fi
|
||||
|
||||
# if this is a branch build, also slightly different variable names.
|
||||
if [[ "$version" == branch* ]]; then
|
||||
#[[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0;
|
||||
# branch builds overrule develop
|
||||
releaseName=$version-$(date +'%Y%m%d')
|
||||
originalName=$releaseName
|
||||
zipName=FireflyIII-$version.zip
|
||||
tarName=FireflyIII-$version.tar.gz
|
||||
fi
|
||||
|
||||
# in both cases, if the release or tag already exists, add ".1" until it no longer exists.
|
||||
tagFound=true
|
||||
tagCount=1
|
||||
@@ -181,23 +201,191 @@ jobs:
|
||||
tagFound=false
|
||||
fi
|
||||
done
|
||||
echo "Will use tag and release name $releaseName."
|
||||
|
||||
# set some variables
|
||||
echo "Release name is $releaseName."
|
||||
echo "Original name is $originalName."
|
||||
echo "Zip name is $zipName."
|
||||
echo "Tar name is $tarName."
|
||||
|
||||
# create a new branch to store the difference in.
|
||||
BRANCH_NAME=release-$(date +'%s')
|
||||
git checkout -b $BRANCH_NAME
|
||||
|
||||
echo "Temporary branch name is '$BRANCH_NAME'."
|
||||
|
||||
# share variables with next step.
|
||||
echo "releaseName=$releaseName" >> "$GITHUB_ENV"
|
||||
echo "originalName=$originalName" >> "$GITHUB_ENV"
|
||||
echo "zipName=$zipName" >> "$GITHUB_ENV"
|
||||
echo "tarName=$tarName" >> "$GITHUB_ENV"
|
||||
echo "BRANCH_NAME=$BRANCH_NAME" >> "$GITHUB_ENV"
|
||||
env:
|
||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
||||
- name: Commit all changes
|
||||
run: |
|
||||
# add all content, except output.txt (this contains the changelog and/or the download instructions)
|
||||
echo 'Add all and reset output.txt'
|
||||
echo 'Add all'
|
||||
git add -A
|
||||
if test -f "output.txt"; then
|
||||
git reset output.txt
|
||||
fi
|
||||
git commit -m "Auto commit for release '$version' on $(date +'%Y-%m-%d')" || true
|
||||
# push to a new branch.
|
||||
echo "Auto commit on branch '$(git branch --show-current)'."
|
||||
git commit -m "🤖 Auto commit for release '$version' on $(date +'%Y-%m-%d')" || true
|
||||
git push
|
||||
env:
|
||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
||||
- name: Extract changelog
|
||||
id: extract-changelog
|
||||
uses: JC5/firefly-iii-dev@main
|
||||
with:
|
||||
action: 'ff3:extract-changelog'
|
||||
output: 'output'
|
||||
env:
|
||||
FIREFLY_III_ROOT: /github/workspace
|
||||
GH_TOKEN: ""
|
||||
- name: Describe new release
|
||||
run: |
|
||||
|
||||
# zip and tar everything
|
||||
echo 'Zip and tar...'
|
||||
zip -rq $zipName . -x "*.git*" "*.ci*" "*.github*" "*node_modules*" "*output.txt*"
|
||||
# describe the development release.
|
||||
if [[ "develop" == "$version" ]]; then
|
||||
echo 'Describe the latest develop release'
|
||||
rm -f output.txt
|
||||
touch output.txt
|
||||
sudo chown -R runner:docker output.txt
|
||||
echo "Weekly development release of Firefly III with the latest fixes, translations and features. Docker users can find this release under the \`develop\` tag." >> output.txt
|
||||
echo "" >> output.txt
|
||||
echo "This release was created on **$(date +'%Y-%m-%d %H:%M')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
echo "" >> output.txt
|
||||
echo "* Please read the installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
|
||||
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
|
||||
echo "" >> output.txt
|
||||
echo ":warning: Please be careful with this pre-release, as it may not work as expected." >> output.txt
|
||||
fi
|
||||
# describe a branch release
|
||||
if [[ "$version" == branch* ]]; then
|
||||
echo 'Describe a branch release'
|
||||
rm -f output.txt
|
||||
touch output.txt
|
||||
sudo chown -R runner:docker output.txt
|
||||
echo "Irregular BRANCH release of Firefly III. This release contains specific features or changes. Docker users can find this release under the \`$version\` tag." >> output.txt
|
||||
echo "" >> output.txt
|
||||
echo "This release was created on **$(date +'%Y-%m-%d %H:%M')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
echo "" >> output.txt
|
||||
echo "* Please read the installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
|
||||
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
|
||||
echo "" >> output.txt
|
||||
echo ":warning: Please be careful with this branch pre-release, as it may not work as expected." >> output.txt
|
||||
fi
|
||||
# describe the main release
|
||||
if [[ "develop" != "$version" ]] && [[ "$version" != branch* ]] && [[ "$version" != *alpha* ]] && [[ "$version" != *beta* ]]; then
|
||||
echo 'Describe the latest release'
|
||||
sudo chown -R runner:docker output.txt
|
||||
touch output.txt
|
||||
echo '' >> output.txt
|
||||
echo "Welcome to release $version of Firefly III. It contains the the latest fixes, translations and features. Docker users can find this release under the \`latest\` tag." >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo '### Instructions' >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
|
||||
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
|
||||
echo "* The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
|
||||
fi
|
||||
|
||||
# describe alpha release
|
||||
if [[ "$version" == *alpha* ]]; then
|
||||
echo 'Describe an ALPHA release'
|
||||
rm -f output.txt
|
||||
touch output.txt
|
||||
sudo chown -R runner:docker output.txt
|
||||
echo "Very early ALPHA release of Firefly III. This release contains specific features or changes. Docker users can find this release under the \`$version\` tag." >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo "This release was created on **$(date +'%Y-%m-%d %H:%M')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo '### Instructions' >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
|
||||
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
|
||||
echo "* The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
|
||||
fi
|
||||
|
||||
# describe beta release
|
||||
if [[ "$version" == *beta* ]]; then
|
||||
echo 'Describe a BETA release'
|
||||
rm -f output.txt
|
||||
touch output.txt
|
||||
sudo chown -R runner:docker output.txt
|
||||
echo "Very early BETA release of Firefly III. This release contains specific features or changes. Docker users can find this release under the \`$version\` tag." >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo "This release was created on **$(date +'%Y-%m-%d %H:%M')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo '### Instructions' >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
|
||||
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
|
||||
echo "* The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
|
||||
fi
|
||||
env:
|
||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
||||
- name: Merge all into working branch
|
||||
run: |
|
||||
MERGE_INTO=develop
|
||||
if [[ "$version" == branch* ]]; then
|
||||
MERGE_INTO=$version
|
||||
fi
|
||||
|
||||
echo "Merge all changes from $BRANCH_NAME back into '$MERGE_INTO' using a PR"
|
||||
PR_URL=$(gh pr create -B $MERGE_INTO -H $BRANCH_NAME --title "🤖 Automatic PR to merge all changes into the '$MERGE_INTO' branch." --body '🤖 Created by GitHub action')
|
||||
echo "PR URL is '$PR_URL'"
|
||||
IFS='/' read -ra parts <<< "$PR_URL"
|
||||
PR_NR=$(printf %s\\n "${parts[@]:(-1)}")
|
||||
echo "PR number is '$PR_NR'"
|
||||
gh pr merge $PR_NR -b "🤖 Automatically merge the PR into the $MERGE_INTO branch." -d --merge
|
||||
|
||||
# pull the changes from the $MERGE_INTO branch.
|
||||
git checkout $MERGE_INTO
|
||||
git merge origin/$MERGE_INTO
|
||||
git pull
|
||||
git status
|
||||
echo "Current branch '$(git branch --show-current)'."
|
||||
|
||||
if [[ "develop" != "$version" ]] && [[ "$version" != branch* ]]; then
|
||||
git checkout main
|
||||
git merge origin/main
|
||||
git pull
|
||||
git status
|
||||
|
||||
echo "Also merge everything into main since this is a release."
|
||||
echo 'create PR'
|
||||
PR_URL=$(gh pr create -B main -H develop --title "🤖 Automatic PR to merge all changes into the main branch." --body "🤖 Created by GitHub action")
|
||||
echo "PR URL is '$PR_URL'"
|
||||
|
||||
IFS='/' read -ra parts <<< "$PR_URL"
|
||||
PR_NR=$(printf %s\\n "${parts[@]:(-1)}")
|
||||
echo "PR number is '$PR_NR'"
|
||||
|
||||
echo 'Merge PR'
|
||||
gh pr merge $PR_NR -b "🤖 Automatically merge the PR into the main branch." --merge
|
||||
git checkout main
|
||||
git merge origin/main
|
||||
git pull
|
||||
git status
|
||||
echo "Current branch '$(git branch --show-current)'."
|
||||
|
||||
fi
|
||||
echo "DONE!"
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
||||
- name: Create archives
|
||||
run: |
|
||||
echo "Create zip file $zipName"
|
||||
zip -rq $zipName . -x "*.git*" "*.ci*" "*.github*" "*node_modules*" "*output.txt*" "*Procfile*" "*crowdin.yml*" "*sonar-project.properties*"
|
||||
touch $tarName
|
||||
tar --exclude=$tarName --exclude=$zipName --exclude='./.git' --exclude='./.ci' --exclude='./.github' --exclude='./node_modules' --exclude='./output.txt' -czf $tarName .
|
||||
|
||||
echo "Create tar file $tarName"
|
||||
tar --exclude=$tarName --exclude=$zipName --exclude='./.git' --exclude='./.ci' --exclude='./.github' --exclude='./node_modules' --exclude='./output.txt' --exclude='./Procfile' --exclude='../crowdin.yml' --exclude='./sonar-project.properties' -czf $tarName .
|
||||
# add sha256 sum
|
||||
echo 'Sha sum ...'
|
||||
sha256sum -b $zipName > $zipName.sha256
|
||||
@@ -206,91 +394,100 @@ jobs:
|
||||
# add signatures:
|
||||
gpg --armor --detach-sign $zipName
|
||||
gpg --armor --detach-sign $tarName
|
||||
- name: Create release
|
||||
run: |
|
||||
|
||||
# create a development (nightly) release:
|
||||
# create a development release:
|
||||
if [[ "develop" == "$version" ]]; then
|
||||
echo 'Develop release.'
|
||||
# add text to output.txt (instructions)
|
||||
rm output.txt
|
||||
echo "Bi-weekly development release of Firefly III with the latest fixes, translations and features. Docker users can find this release under the \`develop\` tag." >> output.txt
|
||||
echo "" >> output.txt
|
||||
echo "This release was created on **$(date +'%Y-%m-%d')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
echo "" >> output.txt
|
||||
echo "* Please read the installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
|
||||
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
|
||||
echo "" >> output.txt
|
||||
echo ":warning: Please be careful with this pre-release, as it may not work as expected." >> output.txt
|
||||
# pull the changes from the develop branch.
|
||||
git checkout develop
|
||||
git merge origin/develop
|
||||
git pull
|
||||
|
||||
# create the release:
|
||||
echo "Create nightly release."
|
||||
git tag -a $releaseName -m "Nightly development release '$version' on $(date +'%Y-%m-%d')"
|
||||
echo "Create develop release under tag '$releaseName'."
|
||||
git tag -a $releaseName -m "🤖 Development release '$version' on $(date +'%Y-%m-%d')"
|
||||
git push origin $releaseName
|
||||
|
||||
gh release create $releaseName -p --verify-tag \
|
||||
-t "Development release for $(date +'%Y-%m-%d')" \
|
||||
--latest=false \
|
||||
-F output.txt
|
||||
|
||||
# add zip file to release.
|
||||
gh release upload $releaseName $zipName
|
||||
gh release upload $releaseName $tarName
|
||||
fi
|
||||
|
||||
# add sha256 sum to release
|
||||
gh release upload $releaseName $zipName.sha256
|
||||
gh release upload $releaseName $tarName.sha256
|
||||
# create a branch release:
|
||||
if [[ "$version" == branch* ]]; then
|
||||
|
||||
# add signatures to release
|
||||
gh release upload $releaseName $zipName.asc
|
||||
gh release upload $releaseName $tarName.asc
|
||||
# pull the changes from the branch-* branch.
|
||||
git checkout $version
|
||||
git merge origin/$version
|
||||
git pull
|
||||
|
||||
# get current HEAD and add as file to the release
|
||||
HEAD=$(git rev-parse HEAD)
|
||||
echo $HEAD > HEAD.txt
|
||||
gh release upload $releaseName HEAD.txt
|
||||
else
|
||||
echo 'MAIN (real) release'
|
||||
sudo chown -R runner:docker output.txt
|
||||
# add text to output.txt (more instructions)
|
||||
echo '' >> output.txt
|
||||
echo '### Instructions' >> output.txt
|
||||
echo '' >> output.txt
|
||||
echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
|
||||
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
|
||||
echo "* The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||
|
||||
echo "Create default release."
|
||||
git tag -a $releaseName -m "Here be changelog"
|
||||
# create the release:
|
||||
echo "Create branch release."
|
||||
git tag -a $releaseName -m "Branch release '$version' on $(date +'%Y-%m-%d')"
|
||||
git push origin $releaseName
|
||||
gh release create $releaseName -F output.txt -t "$releaseName" --verify-tag
|
||||
|
||||
# add archive files to release
|
||||
gh release upload $releaseName $zipName
|
||||
gh release upload $releaseName $tarName
|
||||
gh release create $releaseName -p --verify-tag \
|
||||
-t "Branch release for $(date +'%Y-%m-%d')" \
|
||||
--latest=false \
|
||||
-F output.txt
|
||||
|
||||
# add sha256 sums to release
|
||||
gh release upload $releaseName $zipName.sha256
|
||||
gh release upload $releaseName $tarName.sha256
|
||||
fi
|
||||
|
||||
# add signatures to release
|
||||
gh release upload $releaseName $zipName.asc
|
||||
gh release upload $releaseName $tarName.asc
|
||||
# Create a production release.
|
||||
if [[ "develop" != "$version" ]] && [[ "$version" != branch* ]]; then
|
||||
git checkout main
|
||||
git merge origin/main
|
||||
git pull
|
||||
git status
|
||||
|
||||
# get current HEAD and add as file to the release
|
||||
HEAD=$(git rev-parse HEAD)
|
||||
echo $HEAD > HEAD.txt
|
||||
gh release upload $releaseName HEAD.txt
|
||||
echo "Create prod release."
|
||||
git tag -a $releaseName -m "Release $version"
|
||||
git push origin $releaseName
|
||||
|
||||
# remove all temporary files
|
||||
rm output.txt
|
||||
rm HEAD.txt
|
||||
rm $zipName
|
||||
rm $zipName.sha256
|
||||
rm $tarName
|
||||
rm $tarName.sha256
|
||||
# do not tag as latest when alpha or beta.
|
||||
if [[ "$version" == *alpha* ]] || [[ "$version" == *beta* ]]; then
|
||||
echo 'Mark alpha or beta as NOT the latest.'
|
||||
gh release create $releaseName -F output.txt -t "$releaseName" --verify-tag --latest=false
|
||||
fi
|
||||
|
||||
# merge main back into develop
|
||||
git checkout develop
|
||||
git merge main
|
||||
git push
|
||||
# tag as latest when NOT alpha or beta.
|
||||
if [[ "$version" != *alpha* ]] && [[ "$version" != *beta* ]]; then
|
||||
echo 'Mark prod as the latest.'
|
||||
gh release create $releaseName -F output.txt -t "$releaseName" --verify-tag --latest=true
|
||||
fi
|
||||
fi
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
||||
- name: Upload artifacts
|
||||
run: |
|
||||
# add zip file to release.
|
||||
gh release upload $releaseName $zipName
|
||||
gh release upload $releaseName $tarName
|
||||
|
||||
# add sha256 sum to release
|
||||
gh release upload $releaseName $zipName.sha256
|
||||
gh release upload $releaseName $tarName.sha256
|
||||
|
||||
# add signatures to release
|
||||
gh release upload $releaseName $zipName.asc
|
||||
gh release upload $releaseName $tarName.asc
|
||||
|
||||
# get current HEAD and add as file to the release
|
||||
HEAD=$(git rev-parse HEAD)
|
||||
echo $HEAD > HEAD.txt
|
||||
gh release upload $releaseName HEAD.txt
|
||||
|
||||
# remove all temporary files
|
||||
rm -f output.txt
|
||||
rm -f HEAD.txt
|
||||
rm -f $zipName
|
||||
rm -f $zipName.sha256
|
||||
rm -f $tarName
|
||||
rm -f $tarName.sha256
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
||||
|
8
.github/workflows/sonarcloud.yml
vendored
8
.github/workflows/sonarcloud.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
- develop
|
||||
env:
|
||||
DB_CONNECTION: sqlite
|
||||
APP_KEY: UfpBqqeXx7zpNodsC6yjYQcRfDdm4Bxh
|
||||
APP_KEY: TestTestTestTestTestTestTestTest
|
||||
jobs:
|
||||
sonarcloud:
|
||||
name: SonarCloud
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
- name: Setup PHP with Xdebug
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.3'
|
||||
php-version: '8.4'
|
||||
coverage: xdebug
|
||||
extensions: >-
|
||||
bcmath
|
||||
@@ -46,7 +46,9 @@ jobs:
|
||||
run: composer install --prefer-dist --no-interaction --no-progress --no-scripts
|
||||
|
||||
- name: "Create database file"
|
||||
run: touch storage/database/database.sqlite
|
||||
run: |
|
||||
touch storage/database/database.sqlite
|
||||
wget -q https://github.com/firefly-iii/test-fixtures/raw/refs/heads/main/test-database.sqlite -O storage/database/database.sqlite
|
||||
|
||||
- name: "Upgrades the database to the latest version"
|
||||
run: php artisan firefly-iii:upgrade-database
|
||||
|
10
.gitignore
vendored
10
.gitignore
vendored
@@ -7,6 +7,7 @@ yarn-error.log
|
||||
.env
|
||||
/.ci/php-cs-fixer/vendor
|
||||
coverage.xml
|
||||
output.txt
|
||||
|
||||
# ignore generated files.
|
||||
public/build
|
||||
@@ -14,7 +15,16 @@ public/build
|
||||
# ignore v1 build files
|
||||
resources/assets/v1/node_modules
|
||||
resources/assets/v1/build
|
||||
public/v1/js/app.js*
|
||||
public/v1/js/app_vue.js*
|
||||
public/v1/js/create*
|
||||
public/v1/js/edit*
|
||||
public/v1/js/profile*
|
||||
public/v1/js/administrations
|
||||
public/v1/js/exchange-rates
|
||||
public/v1/js/webhooks
|
||||
|
||||
# ignore v2 build files
|
||||
resources/assets/v2/node_modules
|
||||
resources/assets/v2/build
|
||||
public/v2/i18n
|
||||
|
@@ -3,7 +3,16 @@
|
||||
Over time, many people have contributed to Firefly III. Their efforts are not always visible, but always remembered and appreciated.
|
||||
Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution.
|
||||
|
||||
## 2025
|
||||
- Denis Iskandarov
|
||||
- =
|
||||
- Lompi
|
||||
- Jose Diaz-Gonzalez
|
||||
- SoftBrix
|
||||
|
||||
## 2024
|
||||
- Sobuno
|
||||
- TasneemTantawy
|
||||
- Antônio Franco
|
||||
- yparitcher
|
||||
- Jhon Pedroza
|
||||
|
@@ -26,13 +26,16 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Debug\Timer;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class AccountController
|
||||
@@ -41,6 +44,9 @@ class AccountController extends Controller
|
||||
{
|
||||
use AccountFilter;
|
||||
|
||||
// this array only exists to test if the constructor will use it properly.
|
||||
protected array $accepts = ['application/json', 'application/vnd.api+json'];
|
||||
|
||||
/** @var array<int, string> */
|
||||
private array $balanceTypes;
|
||||
private AccountRepositoryInterface $repository;
|
||||
@@ -61,7 +67,7 @@ class AccountController extends Controller
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
$this->balanceTypes = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
|
||||
$this->balanceTypes = [AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,40 +79,51 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function accounts(AutocompleteRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getData();
|
||||
$types = $data['types'];
|
||||
$query = $data['query'];
|
||||
$date = $data['date'] ?? today(config('app.timezone'));
|
||||
$return = [];
|
||||
$result = $this->repository->searchAccount((string)$query, $types, $this->parameters->get('limit'));
|
||||
$data = $request->getData();
|
||||
$types = $data['types'];
|
||||
$query = $data['query'];
|
||||
$date = $data['date'] ?? today(config('app.timezone'));
|
||||
$return = [];
|
||||
Timer::start(sprintf('AC accounts "%s"', $query));
|
||||
$result = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit'));
|
||||
|
||||
// TODO this code is duplicated in the V2 Autocomplete controller, which means this code is due to be deprecated.
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
// set date to subday + end-of-day for account balance. so it is at $date 23:59:59
|
||||
$date->endOfDay();
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($result as $account) {
|
||||
$nameWithBalance = $account->name;
|
||||
$currency = $this->repository->getAccountCurrency($account) ?? $defaultCurrency;
|
||||
|
||||
$currency = $this->repository->getAccountCurrency($account) ?? $this->nativeCurrency;
|
||||
$useCurrency = $currency;
|
||||
if (in_array($account->accountType->type, $this->balanceTypes, true)) {
|
||||
$balance = app('steam')->balance($account, $date);
|
||||
// this one is correct.
|
||||
Log::debug(sprintf('accounts: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||
$balance = Steam::finalAccountBalance($account, $date);
|
||||
$key = $this->convertToNative && $currency->id !== $this->nativeCurrency->id ? 'native_balance' : 'balance';
|
||||
$useCurrency = $this->convertToNative && $currency->id !== $this->nativeCurrency->id ? $this->nativeCurrency : $currency;
|
||||
$amount = $balance[$key] ?? '0';
|
||||
$nameWithBalance = sprintf(
|
||||
'%s (%s)',
|
||||
$account->name,
|
||||
app('amount')->formatAnything($currency, $balance, false)
|
||||
app('amount')->formatAnything($useCurrency, $amount, false)
|
||||
);
|
||||
}
|
||||
|
||||
$return[] = [
|
||||
'id' => (string)$account->id,
|
||||
'name' => $account->name,
|
||||
'name_with_balance' => $nameWithBalance,
|
||||
'type' => $account->accountType->type,
|
||||
'currency_id' => (string)$currency->id,
|
||||
'currency_name' => $currency->name,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'id' => (string) $account->id,
|
||||
'name' => $account->name,
|
||||
'name_with_balance' => $nameWithBalance,
|
||||
'type' => $account->accountType->type,
|
||||
'currency_id' => (string) $useCurrency->id,
|
||||
'currency_name' => $useCurrency->name,
|
||||
'currency_code' => $useCurrency->code,
|
||||
'currency_symbol' => $useCurrency->symbol,
|
||||
'currency_decimal_places' => $useCurrency->decimal_places,
|
||||
'account_currency_id' => (string) $currency->id,
|
||||
'account_currency_name' => $currency->name,
|
||||
'account_currency_code' => $currency->code,
|
||||
'account_currency_symbol' => $currency->symbol,
|
||||
'account_currency_decimal_places' => $currency->decimal_places,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -114,14 +131,15 @@ class AccountController extends Controller
|
||||
usort(
|
||||
$return,
|
||||
static function (array $left, array $right) {
|
||||
$order = [AccountType::ASSET, AccountType::REVENUE, AccountType::EXPENSE];
|
||||
$posA = (int)array_search($left['type'], $order, true);
|
||||
$posB = (int)array_search($right['type'], $order, true);
|
||||
$order = [AccountTypeEnum::ASSET->value, AccountTypeEnum::REVENUE->value, AccountTypeEnum::EXPENSE->value];
|
||||
$posA = (int) array_search($left['type'], $order, true);
|
||||
$posB = (int) array_search($right['type'], $order, true);
|
||||
|
||||
return $posA - $posB;
|
||||
}
|
||||
);
|
||||
Timer::stop(sprintf('AC accounts "%s"', $query));
|
||||
|
||||
return response()->json($return);
|
||||
return response()->api($return);
|
||||
}
|
||||
}
|
||||
|
@@ -65,15 +65,13 @@ class BillController extends Controller
|
||||
$data = $request->getData();
|
||||
$result = $this->repository->searchBill($data['query'], $this->parameters->get('limit'));
|
||||
$filtered = $result->map(
|
||||
static function (Bill $item) {
|
||||
return [
|
||||
'id' => (string)$item->id,
|
||||
'name' => $item->name,
|
||||
'active' => $item->active,
|
||||
];
|
||||
}
|
||||
static fn (Bill $item) => [
|
||||
'id' => (string) $item->id,
|
||||
'name' => $item->name,
|
||||
'active' => $item->active,
|
||||
]
|
||||
);
|
||||
|
||||
return response()->json($filtered->toArray());
|
||||
return response()->api($filtered->toArray());
|
||||
}
|
||||
}
|
||||
|
@@ -65,14 +65,12 @@ class BudgetController extends Controller
|
||||
$data = $request->getData();
|
||||
$result = $this->repository->searchBudget($data['query'], $this->parameters->get('limit'));
|
||||
$filtered = $result->map(
|
||||
static function (Budget $item) {
|
||||
return [
|
||||
'id' => (string)$item->id,
|
||||
'name' => $item->name,
|
||||
];
|
||||
}
|
||||
static fn (Budget $item) => [
|
||||
'id' => (string) $item->id,
|
||||
'name' => $item->name,
|
||||
]
|
||||
);
|
||||
|
||||
return response()->json($filtered);
|
||||
return response()->api($filtered->toArray());
|
||||
}
|
||||
}
|
||||
|
@@ -65,14 +65,12 @@ class CategoryController extends Controller
|
||||
$data = $request->getData();
|
||||
$result = $this->repository->searchCategory($data['query'], $this->parameters->get('limit'));
|
||||
$filtered = $result->map(
|
||||
static function (Category $item) {
|
||||
return [
|
||||
'id' => (string)$item->id,
|
||||
'name' => $item->name,
|
||||
];
|
||||
}
|
||||
static fn (Category $item) => [
|
||||
'id' => (string) $item->id,
|
||||
'name' => $item->name,
|
||||
]
|
||||
);
|
||||
|
||||
return response()->json($filtered);
|
||||
return response()->api($filtered->toArray());
|
||||
}
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
@@ -69,7 +69,7 @@ class CurrencyController extends Controller
|
||||
/** @var TransactionCurrency $currency */
|
||||
foreach ($collection as $currency) {
|
||||
$result[] = [
|
||||
'id' => (string)$currency->id,
|
||||
'id' => (string) $currency->id,
|
||||
'name' => $currency->name,
|
||||
'code' => $currency->code,
|
||||
'symbol' => $currency->symbol,
|
||||
@@ -77,7 +77,7 @@ class CurrencyController extends Controller
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($result);
|
||||
return response()->api($result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,7 +95,7 @@ class CurrencyController extends Controller
|
||||
/** @var TransactionCurrency $currency */
|
||||
foreach ($collection as $currency) {
|
||||
$result[] = [
|
||||
'id' => (string)$currency->id,
|
||||
'id' => (string) $currency->id,
|
||||
'name' => sprintf('%s (%s)', $currency->name, $currency->code),
|
||||
'code' => $currency->code,
|
||||
'symbol' => $currency->symbol,
|
||||
@@ -103,6 +103,6 @@ class CurrencyController extends Controller
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($result);
|
||||
return response()->api($result);
|
||||
}
|
||||
}
|
||||
|
@@ -69,12 +69,12 @@ class ObjectGroupController extends Controller
|
||||
/** @var ObjectGroup $objectGroup */
|
||||
foreach ($result as $objectGroup) {
|
||||
$return[] = [
|
||||
'id' => (string)$objectGroup->id,
|
||||
'id' => (string) $objectGroup->id,
|
||||
'name' => $objectGroup->title,
|
||||
'title' => $objectGroup->title,
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($return);
|
||||
return response()->api($return);
|
||||
}
|
||||
}
|
||||
|
@@ -66,29 +66,28 @@ class PiggyBankController extends Controller
|
||||
*/
|
||||
public function piggyBanks(AutocompleteRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getData();
|
||||
$piggies = $this->piggyRepository->searchPiggyBank($data['query'], $this->parameters->get('limit'));
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
$response = [];
|
||||
$data = $request->getData();
|
||||
$piggies = $this->piggyRepository->searchPiggyBank($data['query'], $this->parameters->get('limit'));
|
||||
$response = [];
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($piggies as $piggy) {
|
||||
$currency = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency;
|
||||
$currency = $piggy->transactionCurrency;
|
||||
$objectGroup = $piggy->objectGroups()->first();
|
||||
$response[] = [
|
||||
'id' => (string)$piggy->id,
|
||||
'id' => (string) $piggy->id,
|
||||
'name' => $piggy->name,
|
||||
'currency_id' => (string)$currency->id,
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_name' => $currency->name,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'object_group_id' => null === $objectGroup ? null : (string)$objectGroup->id,
|
||||
'object_group_id' => null === $objectGroup ? null : (string) $objectGroup->id,
|
||||
'object_group_title' => $objectGroup?->title,
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($response);
|
||||
return response()->api($response);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,35 +96,34 @@ class PiggyBankController extends Controller
|
||||
*/
|
||||
public function piggyBanksWithBalance(AutocompleteRequest $request): JsonResponse
|
||||
{
|
||||
$data = $request->getData();
|
||||
$piggies = $this->piggyRepository->searchPiggyBank($data['query'], $this->parameters->get('limit'));
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
$response = [];
|
||||
$data = $request->getData();
|
||||
$piggies = $this->piggyRepository->searchPiggyBank($data['query'], $this->parameters->get('limit'));
|
||||
$response = [];
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($piggies as $piggy) {
|
||||
$currency = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency;
|
||||
$currentAmount = $this->piggyRepository->getRepetition($piggy)->currentamount ?? '0';
|
||||
$currency = $piggy->transactionCurrency;
|
||||
$currentAmount = $this->piggyRepository->getCurrentAmount($piggy);
|
||||
$objectGroup = $piggy->objectGroups()->first();
|
||||
$response[] = [
|
||||
'id' => (string)$piggy->id,
|
||||
'id' => (string) $piggy->id,
|
||||
'name' => $piggy->name,
|
||||
'name_with_balance' => sprintf(
|
||||
'%s (%s / %s)',
|
||||
$piggy->name,
|
||||
app('amount')->formatAnything($currency, $currentAmount, false),
|
||||
app('amount')->formatAnything($currency, $piggy->targetamount, false),
|
||||
app('amount')->formatAnything($currency, $piggy->target_amount, false),
|
||||
),
|
||||
'currency_id' => (string)$currency->id,
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_name' => $currency->name,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'object_group_id' => null === $objectGroup ? null : (string)$objectGroup->id,
|
||||
'object_group_id' => null === $objectGroup ? null : (string) $objectGroup->id,
|
||||
'object_group_title' => $objectGroup?->title,
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($response);
|
||||
return response()->api($response);
|
||||
}
|
||||
}
|
||||
|
@@ -67,12 +67,12 @@ class RecurrenceController extends Controller
|
||||
/** @var Recurrence $recurrence */
|
||||
foreach ($recurrences as $recurrence) {
|
||||
$response[] = [
|
||||
'id' => (string)$recurrence->id,
|
||||
'id' => (string) $recurrence->id,
|
||||
'name' => $recurrence->title,
|
||||
'description' => $recurrence->description,
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($response);
|
||||
return response()->api($response);
|
||||
}
|
||||
}
|
||||
|
@@ -66,12 +66,12 @@ class RuleController extends Controller
|
||||
/** @var Rule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
$response[] = [
|
||||
'id' => (string)$rule->id,
|
||||
'id' => (string) $rule->id,
|
||||
'name' => $rule->title,
|
||||
'description' => $rule->description,
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($response);
|
||||
return response()->api($response);
|
||||
}
|
||||
}
|
||||
|
@@ -66,12 +66,12 @@ class RuleGroupController extends Controller
|
||||
/** @var RuleGroup $group */
|
||||
foreach ($groups as $group) {
|
||||
$response[] = [
|
||||
'id' => (string)$group->id,
|
||||
'id' => (string) $group->id,
|
||||
'name' => $group->title,
|
||||
'description' => $group->description,
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($response);
|
||||
return response()->api($response);
|
||||
}
|
||||
}
|
||||
|
@@ -69,12 +69,12 @@ class TagController extends Controller
|
||||
/** @var Tag $tag */
|
||||
foreach ($result as $tag) {
|
||||
$array[] = [
|
||||
'id' => (string)$tag->id,
|
||||
'id' => (string) $tag->id,
|
||||
'name' => $tag->tag,
|
||||
'tag' => $tag->tag,
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($array);
|
||||
return response()->api($array);
|
||||
}
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||
@@ -38,6 +39,7 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
class TransactionController extends Controller
|
||||
{
|
||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||
private TransactionGroupRepositoryInterface $groupRepository;
|
||||
private JournalRepositoryInterface $repository;
|
||||
|
||||
@@ -51,10 +53,12 @@ class TransactionController extends Controller
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$userGroup = $this->validateUserGroup($request);
|
||||
$this->repository = app(JournalRepositoryInterface::class);
|
||||
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
$this->groupRepository->setUser($user);
|
||||
$this->groupRepository->setUserGroup($userGroup);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -77,14 +81,14 @@ class TransactionController extends Controller
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($filtered as $journal) {
|
||||
$array[] = [
|
||||
'id' => (string)$journal->id,
|
||||
'transaction_group_id' => (string)$journal->transaction_group_id,
|
||||
'id' => (string) $journal->id,
|
||||
'transaction_group_id' => (string) $journal->transaction_group_id,
|
||||
'name' => $journal->description,
|
||||
'description' => $journal->description,
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($array);
|
||||
return response()->api($array);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +101,7 @@ class TransactionController extends Controller
|
||||
$result = new Collection();
|
||||
if (is_numeric($data['query'])) {
|
||||
// search for group, not journal.
|
||||
$firstResult = $this->groupRepository->find((int)$data['query']);
|
||||
$firstResult = $this->groupRepository->find((int) $data['query']);
|
||||
if (null !== $firstResult) {
|
||||
// group may contain multiple journals, each a result:
|
||||
foreach ($firstResult->transactionJournals as $journal) {
|
||||
@@ -115,13 +119,13 @@ class TransactionController extends Controller
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($result as $journal) {
|
||||
$array[] = [
|
||||
'id' => (string)$journal->id,
|
||||
'transaction_group_id' => (string)$journal->transaction_group_id,
|
||||
'id' => (string) $journal->id,
|
||||
'transaction_group_id' => (string) $journal->transaction_group_id,
|
||||
'name' => sprintf('#%d: %s', $journal->transaction_group_id, $journal->description),
|
||||
'description' => sprintf('#%d: %s', $journal->transaction_group_id, $journal->description),
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($array);
|
||||
return response()->api($array);
|
||||
}
|
||||
}
|
||||
|
@@ -66,12 +66,12 @@ class TransactionTypeController extends Controller
|
||||
foreach ($types as $type) {
|
||||
// different key for consistency.
|
||||
$array[] = [
|
||||
'id' => (string)$type->id,
|
||||
'id' => (string) $type->id,
|
||||
'name' => $type->type,
|
||||
'type' => $type->type,
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($array);
|
||||
return response()->api($array);
|
||||
}
|
||||
}
|
||||
|
@@ -26,13 +26,17 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Chart\ChartRequest;
|
||||
use FireflyIII\Api\V1\Requests\Data\DateRequest;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Chart\ChartData;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Http\Api\ApiSupport;
|
||||
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
@@ -42,7 +46,9 @@ use Illuminate\Http\JsonResponse;
|
||||
class AccountController extends Controller
|
||||
{
|
||||
use ApiSupport;
|
||||
use CollectsAccountsFromFilter;
|
||||
|
||||
private ChartData $chartData;
|
||||
private AccountRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
@@ -55,6 +61,7 @@ class AccountController extends Controller
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$this->chartData = new ChartData();
|
||||
$this->repository = app(AccountRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
|
||||
@@ -63,6 +70,70 @@ class AccountController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO fix documentation
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function dashboard(ChartRequest $request): JsonResponse
|
||||
{
|
||||
$queryParameters = $request->getParameters();
|
||||
$accounts = $this->getAccountList($queryParameters);
|
||||
|
||||
// move date to end of day
|
||||
$queryParameters['start']->startOfDay();
|
||||
$queryParameters['end']->endOfDay();
|
||||
|
||||
// loop each account, and collect info:
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$this->renderAccountData($queryParameters, $account);
|
||||
}
|
||||
|
||||
return response()->json($this->chartData->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function renderAccountData(array $params, Account $account): void
|
||||
{
|
||||
$currency = $this->repository->getAccountCurrency($account);
|
||||
if (null === $currency) {
|
||||
$currency = $this->default;
|
||||
}
|
||||
$currentSet = [
|
||||
'label' => $account->name,
|
||||
|
||||
// the currency that belongs to the account.
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
|
||||
// the default currency of the user (could be the same!)
|
||||
'date' => $params['start']->toAtomString(),
|
||||
'start' => $params['start']->toAtomString(),
|
||||
'end' => $params['end']->toAtomString(),
|
||||
'period' => '1D',
|
||||
'entries' => [],
|
||||
];
|
||||
$currentStart = clone $params['start'];
|
||||
$range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative);
|
||||
|
||||
$previous = array_values($range)[0]['balance'];
|
||||
while ($currentStart <= $params['end']) {
|
||||
$format = $currentStart->format('Y-m-d');
|
||||
$label = $currentStart->toAtomString();
|
||||
$balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous;
|
||||
$previous = $balance;
|
||||
|
||||
$currentStart->addDay();
|
||||
$currentSet['entries'][$label] = $balance;
|
||||
}
|
||||
$this->chartData->add($currentSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/charts/getChartAccountOverview
|
||||
@@ -80,12 +151,15 @@ class AccountController extends Controller
|
||||
/** @var Carbon $end */
|
||||
$end = $dates['end'];
|
||||
|
||||
// set dates to end of day + start of day:
|
||||
$start->startOfDay();
|
||||
$end->endOfDay();
|
||||
|
||||
// user's preferences
|
||||
$defaultSet = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray();
|
||||
$defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
|
||||
|
||||
/** @var Preference $frontpage */
|
||||
$frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
|
||||
$default = app('amount')->getDefaultCurrency();
|
||||
|
||||
if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {
|
||||
$frontpage->data = $defaultSet;
|
||||
@@ -98,13 +172,11 @@ class AccountController extends Controller
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$currency = $this->repository->getAccountCurrency($account);
|
||||
if (null === $currency) {
|
||||
$currency = $default;
|
||||
}
|
||||
$currency = $this->repository->getAccountCurrency($account) ?? $this->nativeCurrency;
|
||||
$field = $this->convertToNative && $currency->id !== $this->nativeCurrency->id ? 'native_balance' : 'balance';
|
||||
$currentSet = [
|
||||
'label' => $account->name,
|
||||
'currency_id' => (string)$currency->id,
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
@@ -116,13 +188,12 @@ class AccountController extends Controller
|
||||
];
|
||||
// TODO this code is also present in the V2 chart account controller so this method is due to be deprecated.
|
||||
$currentStart = clone $start;
|
||||
$range = app('steam')->balanceInRange($account, $start, clone $end);
|
||||
// 2022-10-11 this method no longer converts to float.
|
||||
$previous = array_values($range)[0];
|
||||
$range = Steam::finalAccountBalanceInRange($account, $start, clone $end, $this->convertToNative);
|
||||
$previous = array_values($range)[0][$field];
|
||||
while ($currentStart <= $end) {
|
||||
$format = $currentStart->format('Y-m-d');
|
||||
$label = $currentStart->toAtomString();
|
||||
$balance = array_key_exists($format, $range) ? $range[$format] : $previous;
|
||||
$balance = array_key_exists($format, $range) ? $range[$format][$field] : $previous;
|
||||
$previous = $balance;
|
||||
$currentStart->addDay();
|
||||
$currentSet['entries'][$label] = $balance;
|
||||
|
260
app/Api/V1/Controllers/Chart/BudgetController.php
Normal file
260
app/Api/V1/Controllers/Chart/BudgetController.php
Normal file
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* BudgetController.php
|
||||
* Copyright (c) 2023 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Chart;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Generic\DateRequest;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\CleansChartData;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class BudgetController
|
||||
*/
|
||||
class BudgetController extends Controller
|
||||
{
|
||||
use CleansChartData;
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||
|
||||
protected OperationsRepositoryInterface $opsRepository;
|
||||
private BudgetLimitRepositoryInterface $blRepository;
|
||||
private array $currencies = [];
|
||||
private TransactionCurrency $currency;
|
||||
private BudgetRepositoryInterface $repository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||
$this->opsRepository = app(OperationsRepositoryInterface::class);
|
||||
$userGroup = $this->validateUserGroup($request);
|
||||
$this->repository->setUserGroup($userGroup);
|
||||
$this->opsRepository->setUserGroup($userGroup);
|
||||
$this->blRepository->setUserGroup($userGroup);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO see autocomplete/accountcontroller
|
||||
*/
|
||||
public function dashboard(DateRequest $request): JsonResponse
|
||||
{
|
||||
$params = $request->getAll();
|
||||
|
||||
/** @var Carbon $start */
|
||||
$start = $params['start'];
|
||||
|
||||
/** @var Carbon $end */
|
||||
$end = $params['end'];
|
||||
|
||||
// code from FrontpageChartGenerator, but not in separate class
|
||||
$budgets = $this->repository->getActiveBudgets();
|
||||
$data = [];
|
||||
|
||||
/** @var Budget $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
// could return multiple arrays, so merge.
|
||||
$data = array_merge($data, $this->processBudget($budget, $start, $end));
|
||||
}
|
||||
|
||||
return response()->json($this->clean($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function processBudget(Budget $budget, Carbon $start, Carbon $end): array
|
||||
{
|
||||
// get all limits:
|
||||
$limits = $this->blRepository->getBudgetLimits($budget, $start, $end);
|
||||
$rows = [];
|
||||
|
||||
// if no limits
|
||||
if (0 === $limits->count()) {
|
||||
// return as a single item in an array
|
||||
$rows = $this->noBudgetLimits($budget, $start, $end);
|
||||
}
|
||||
if ($limits->count() > 0) {
|
||||
$rows = $this->budgetLimits($budget, $limits);
|
||||
}
|
||||
// is always an array
|
||||
$return = [];
|
||||
foreach ($rows as $row) {
|
||||
$current = [
|
||||
'label' => $budget->name,
|
||||
'currency_id' => (string) $row['currency_id'],
|
||||
'currency_code' => $row['currency_code'],
|
||||
'currency_name' => $row['currency_name'],
|
||||
'currency_decimal_places' => $row['currency_decimal_places'],
|
||||
'period' => null,
|
||||
'start' => $row['start'],
|
||||
'end' => $row['end'],
|
||||
'entries' => [
|
||||
'spent' => $row['spent'],
|
||||
'left' => $row['left'],
|
||||
'overspent' => $row['overspent'],
|
||||
],
|
||||
];
|
||||
$return[] = $current;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* When no budget limits are present, the expenses of the whole period are collected and grouped.
|
||||
* This is grouped per currency. Because there is no limit set, "left to spend" and "overspent" are empty.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function noBudgetLimits(Budget $budget, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$spent = $this->opsRepository->listExpenses($start, $end, null, new Collection([$budget]));
|
||||
|
||||
return $this->processExpenses($budget->id, $spent, $start, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared between the "noBudgetLimits" function and "processLimit". Will take a single set of expenses and return
|
||||
* its info.
|
||||
*
|
||||
* @param array<int, array<int, string>> $array
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function processExpenses(int $budgetId, array $array, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$return = [];
|
||||
|
||||
/**
|
||||
* This array contains the expenses in this budget. Grouped per currency.
|
||||
* The grouping is on the main currency only.
|
||||
*
|
||||
* @var int $currencyId
|
||||
* @var array $block
|
||||
*/
|
||||
foreach ($array as $currencyId => $block) {
|
||||
$this->currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
|
||||
$return[$currencyId] ??= [
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $block['currency_code'],
|
||||
'currency_name' => $block['currency_name'],
|
||||
'currency_symbol' => $block['currency_symbol'],
|
||||
'currency_decimal_places' => (int) $block['currency_decimal_places'],
|
||||
'start' => $start->toAtomString(),
|
||||
'end' => $end->toAtomString(),
|
||||
'spent' => '0',
|
||||
'left' => '0',
|
||||
'overspent' => '0',
|
||||
];
|
||||
$currentBudgetArray = $block['budgets'][$budgetId];
|
||||
|
||||
// var_dump($return);
|
||||
/** @var array $journal */
|
||||
foreach ($currentBudgetArray['transaction_journals'] as $journal) {
|
||||
$return[$currencyId]['spent'] = bcadd($return[$currencyId]['spent'], (string) $journal['amount']);
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that processes each budget limit (per budget).
|
||||
*
|
||||
* If you have a budget limit in EUR, only transactions in EUR will be considered.
|
||||
* If you have a budget limit in GBP, only transactions in GBP will be considered.
|
||||
*
|
||||
* If you have a budget limit in EUR, and a transaction in GBP, it will not be considered for the EUR budget limit.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function budgetLimits(Budget $budget, Collection $limits): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in budgetLimits(#%d)', $budget->id));
|
||||
$data = [];
|
||||
|
||||
/** @var BudgetLimit $limit */
|
||||
foreach ($limits as $limit) {
|
||||
$data = array_merge($data, $this->processLimit($budget, $limit));
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function processLimit(Budget $budget, BudgetLimit $limit): array
|
||||
{
|
||||
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
|
||||
$end = clone $limit->end_date;
|
||||
$end->endOfDay();
|
||||
$spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection([$budget]));
|
||||
$limitCurrencyId = $limit->transaction_currency_id;
|
||||
$filtered = [];
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($spent as $currencyId => $entry) {
|
||||
// only spent the entry where the entry's currency matches the budget limit's currency
|
||||
// so $filtered will only have 1 or 0 entries
|
||||
if ($entry['currency_id'] === $limitCurrencyId) {
|
||||
$filtered[$currencyId] = $entry;
|
||||
}
|
||||
}
|
||||
$result = $this->processExpenses($budget->id, $filtered, $limit->start_date, $end);
|
||||
if (1 === count($result)) {
|
||||
$compare = bccomp($limit->amount, (string) app('steam')->positive($result[$limitCurrencyId]['spent']));
|
||||
if (1 === $compare) {
|
||||
// convert this amount into the native currency:
|
||||
$result[$limitCurrencyId]['left'] = bcadd($limit->amount, (string) $result[$limitCurrencyId]['spent']);
|
||||
}
|
||||
if ($compare <= 0) {
|
||||
$result[$limitCurrencyId]['overspent'] = app('steam')->positive(bcadd($limit->amount, (string) $result[$limitCurrencyId]['spent']));
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
126
app/Api/V1/Controllers/Chart/CategoryController.php
Normal file
126
app/Api/V1/Controllers/Chart/CategoryController.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* CategoryController.php
|
||||
* Copyright (c) 2023 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Chart;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V2\Controllers\Controller;
|
||||
use FireflyIII\Api\V2\Request\Generic\DateRequest;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\CleansChartData;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
* Class BudgetController
|
||||
*/
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
use CleansChartData;
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
private AccountRepositoryInterface $accountRepos;
|
||||
private CurrencyRepositoryInterface $currencyRepos;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->accountRepos = app(AccountRepositoryInterface::class);
|
||||
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||
$userGroup = $this->validateUserGroup($request);
|
||||
$this->accountRepos->setUserGroup($userGroup);
|
||||
$this->currencyRepos->setUserGroup($userGroup);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO may be worth to move to a handler but the data is simple enough.
|
||||
* TODO see autoComplete/account controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function dashboard(DateRequest $request): JsonResponse
|
||||
{
|
||||
/** @var Carbon $start */
|
||||
$start = $this->parameters->get('start');
|
||||
|
||||
/** @var Carbon $end */
|
||||
$end = $this->parameters->get('end');
|
||||
$accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]);
|
||||
$currencies = [];
|
||||
$return = [];
|
||||
|
||||
// get journals for entire period:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setRange($start, $end)->withAccountInformation();
|
||||
$collector->setXorAccounts($accounts)->withCategoryInformation();
|
||||
$collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::RECONCILIATION->value]);
|
||||
$journals = $collector->getExtractedJournals();
|
||||
|
||||
/** @var array $journal */
|
||||
foreach ($journals as $journal) {
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId);
|
||||
$currencies[$currencyId] = $currency;
|
||||
$categoryName = $journal['category_name'] ?? (string) trans('firefly.no_category');
|
||||
$amount = app('steam')->positive($journal['amount']);
|
||||
$key = sprintf('%s-%s', $categoryName, $currency->code);
|
||||
// create arrays
|
||||
$return[$key] ??= [
|
||||
'label' => $categoryName,
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_name' => $currency->name,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'period' => null,
|
||||
'start' => $start->toAtomString(),
|
||||
'end' => $end->toAtomString(),
|
||||
'amount' => '0',
|
||||
];
|
||||
|
||||
// add monies
|
||||
$return[$key]['amount'] = bcadd($return[$key]['amount'], (string) $amount);
|
||||
}
|
||||
$return = array_values($return);
|
||||
|
||||
// order by amount
|
||||
usort($return, static fn (array $a, array $b) => (float) $a['amount'] < (float) $b['amount'] ? 1 : -1);
|
||||
|
||||
return response()->json($this->clean($return));
|
||||
}
|
||||
}
|
@@ -25,15 +25,25 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Carbon\Exceptions\InvalidDateException;
|
||||
use Carbon\Exceptions\InvalidFormatException;
|
||||
use FireflyIII\Exceptions\BadHttpHeaderException;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use FireflyIII\Transformers\AbstractTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
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 Symfony\Component\HttpFoundation\Exception\BadRequestException;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
@@ -41,20 +51,25 @@ use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
/**
|
||||
* Class Controller.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
* @SuppressWarnings(PHPMD.NumberOfChildren)
|
||||
* @SuppressWarnings("PHPMD.CouplingBetweenObjects")
|
||||
* @SuppressWarnings("PHPMD.NumberOfChildren")
|
||||
*/
|
||||
abstract class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
use DispatchesJobs;
|
||||
use ValidatesRequests;
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
protected const string CONTENT_TYPE = 'application/vnd.api+json';
|
||||
protected const string CONTENT_TYPE = 'application/vnd.api+json';
|
||||
protected const string JSON_CONTENT_TYPE = 'application/json';
|
||||
protected array $accepts = ['application/json', 'application/vnd.api+json'];
|
||||
|
||||
/** @var array<int, string> */
|
||||
protected array $allowedSort;
|
||||
protected ParameterBag $parameters;
|
||||
protected array $allowedSort;
|
||||
protected bool $convertToNative = false;
|
||||
protected TransactionCurrency $nativeCurrency;
|
||||
protected ParameterBag $parameters;
|
||||
|
||||
/**
|
||||
* Controller constructor.
|
||||
@@ -67,10 +82,19 @@ abstract class Controller extends BaseController
|
||||
function ($request, $next) {
|
||||
$this->parameters = $this->getParameters();
|
||||
if (auth()->check()) {
|
||||
$language = app('steam')->getLanguage();
|
||||
$language = Steam::getLanguage();
|
||||
$this->convertToNative = Amount::convertToNative();
|
||||
$this->nativeCurrency = Amount::getNativeCurrency();
|
||||
app()->setLocale($language);
|
||||
}
|
||||
|
||||
|
||||
// filter down what this endpoint accepts.
|
||||
if (!$request->accepts($this->accepts)) {
|
||||
throw new BadHttpHeaderException(sprintf('Sorry, Accept header "%s" is not something this endpoint can provide.', $request->header('Accept')));
|
||||
}
|
||||
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
@@ -82,7 +106,7 @@ abstract class Controller extends BaseController
|
||||
private function getParameters(): ParameterBag
|
||||
{
|
||||
$bag = new ParameterBag();
|
||||
$page = (int)request()->get('page');
|
||||
$page = (int) request()->get('page');
|
||||
if ($page < 1) {
|
||||
$page = 1;
|
||||
}
|
||||
@@ -107,13 +131,13 @@ abstract class Controller extends BaseController
|
||||
$obj = null;
|
||||
if (null !== $date) {
|
||||
try {
|
||||
$obj = Carbon::parse((string)$date);
|
||||
} catch (InvalidDateException|InvalidFormatException $e) {
|
||||
$obj = Carbon::parse((string) $date);
|
||||
} catch (InvalidFormatException $e) {
|
||||
// don't care
|
||||
app('log')->warning(
|
||||
sprintf(
|
||||
'Ignored invalid date "%s" in API controller parameter check: %s',
|
||||
substr((string)$date, 0, 20),
|
||||
substr((string) $date, 0, 20),
|
||||
$e->getMessage()
|
||||
)
|
||||
);
|
||||
@@ -134,7 +158,15 @@ abstract class Controller extends BaseController
|
||||
$value = null;
|
||||
}
|
||||
if (null !== $value) {
|
||||
$bag->set($integer, (int)$value);
|
||||
$value = (int) $value;
|
||||
if ($value < 1) {
|
||||
$value = 1;
|
||||
}
|
||||
if ($value > 2 ** 16) {
|
||||
$value = 2 ** 16;
|
||||
}
|
||||
|
||||
$bag->set($integer, $value);
|
||||
}
|
||||
if (null === $value
|
||||
&& 'limit' === $integer // @phpstan-ignore-line
|
||||
@@ -144,7 +176,7 @@ abstract class Controller extends BaseController
|
||||
$user = auth()->user();
|
||||
|
||||
/** @var Preference $pageSize */
|
||||
$pageSize = (int)app('preferences')->getForUser($user, 'listPageSize', 50)->data;
|
||||
$pageSize = (int) app('preferences')->getForUser($user, 'listPageSize', 50)->data;
|
||||
$bag->set($integer, $pageSize);
|
||||
}
|
||||
}
|
||||
@@ -158,7 +190,7 @@ abstract class Controller extends BaseController
|
||||
$sortParameters = [];
|
||||
|
||||
try {
|
||||
$param = (string)request()->query->get('sort');
|
||||
$param = (string) request()->query->get('sort');
|
||||
} catch (BadRequestException $e) {
|
||||
app('log')->error('Request field "sort" contains a non-scalar value. Value set to NULL.');
|
||||
app('log')->error($e->getMessage());
|
||||
@@ -216,4 +248,45 @@ abstract class Controller extends BaseController
|
||||
|
||||
return $manager;
|
||||
}
|
||||
|
||||
final protected function jsonApiList(string $key, LengthAwarePaginator $paginator, AbstractTransformer $transformer): array
|
||||
{
|
||||
$manager = new Manager();
|
||||
$baseUrl = sprintf('%s/api/v1/', request()->getSchemeAndHttpHost());
|
||||
|
||||
// TODO add stuff to path?
|
||||
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
$objects = $paginator->getCollection();
|
||||
|
||||
// the transformer, at this point, needs to collect information that ALL items in the collection
|
||||
// require, like meta-data and stuff like that, and save it for later.
|
||||
// $objects = $transformer->collectMetaData($objects);
|
||||
$paginator->setCollection($objects);
|
||||
|
||||
$resource = new FractalCollection($objects, $transformer, $key);
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return $manager->createData($resource)->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JSON API object and returns it.
|
||||
*
|
||||
* @param array<int, mixed>|Model $object
|
||||
*/
|
||||
final protected function jsonApiObject(string $key, array|Model $object, AbstractTransformer $transformer): array
|
||||
{
|
||||
// create some objects:
|
||||
$manager = new Manager();
|
||||
$baseUrl = sprintf('%s/api/v1', request()->getSchemeAndHttpHost());
|
||||
$manager->setSerializer(new JsonApiSerializer($baseUrl));
|
||||
|
||||
// $transformer->collectMetaData(new Collection([$object]));
|
||||
|
||||
$resource = new Item($object, $transformer, $key);
|
||||
|
||||
return $manager->createData($resource)->toArray();
|
||||
}
|
||||
}
|
||||
|
@@ -70,8 +70,8 @@ class TransactionController extends Controller
|
||||
// to respond to what is in the $query.
|
||||
// this is OK because only one thing can be in the query at the moment.
|
||||
if ($this->isUpdateTransactionAccount($params)) {
|
||||
$original = $this->repository->find((int)$params['where']['account_id']);
|
||||
$destination = $this->repository->find((int)$params['update']['account_id']);
|
||||
$original = $this->repository->find((int) $params['where']['account_id']);
|
||||
$destination = $this->repository->find((int) $params['update']['account_id']);
|
||||
|
||||
/** @var AccountDestroyService $service */
|
||||
$service = app(AccountDestroyService::class);
|
||||
|
@@ -26,10 +26,10 @@ namespace FireflyIII\Api\V1\Controllers\Data;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Data\DestroyRequest;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
@@ -66,9 +66,9 @@ class DestroyController extends Controller
|
||||
$objects = $request->getObjects();
|
||||
$this->unused = $request->boolean('unused', false);
|
||||
|
||||
$allExceptAssets = [AccountType::BENEFICIARY, AccountType::CASH, AccountType::CREDITCARD, AccountType::DEFAULT, AccountType::EXPENSE, AccountType::IMPORT, AccountType::INITIAL_BALANCE, AccountType::LIABILITY_CREDIT, AccountType::RECONCILIATION, AccountType::REVENUE];
|
||||
$all = [AccountType::ASSET, AccountType::BENEFICIARY, AccountType::CASH, AccountType::CREDITCARD, AccountType::DEBT, AccountType::DEFAULT, AccountType::EXPENSE, AccountType::IMPORT, AccountType::INITIAL_BALANCE, AccountType::LIABILITY_CREDIT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::RECONCILIATION];
|
||||
$liabilities = [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD];
|
||||
$allExceptAssets = [AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::RECONCILIATION->value, AccountTypeEnum::REVENUE->value];
|
||||
$all = [AccountTypeEnum::ASSET->value, AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::RECONCILIATION->value];
|
||||
$liabilities = [AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::CREDITCARD->value];
|
||||
$transactions = [TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::DEPOSIT->value, TransactionTypeEnum::TRANSFER->value, TransactionTypeEnum::RECONCILIATION->value];
|
||||
|
||||
match ($objects) {
|
||||
@@ -82,9 +82,9 @@ class DestroyController extends Controller
|
||||
'object_groups' => $this->destroyObjectGroups(),
|
||||
'not_assets_liabilities' => $this->destroyAccounts($allExceptAssets),
|
||||
'accounts' => $this->destroyAccounts($all),
|
||||
'asset_accounts' => $this->destroyAccounts([AccountType::ASSET, AccountType::DEFAULT]),
|
||||
'expense_accounts' => $this->destroyAccounts([AccountType::BENEFICIARY, AccountType::EXPENSE]),
|
||||
'revenue_accounts' => $this->destroyAccounts([AccountType::REVENUE]),
|
||||
'asset_accounts' => $this->destroyAccounts([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]),
|
||||
'expense_accounts' => $this->destroyAccounts([AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::EXPENSE->value]),
|
||||
'revenue_accounts' => $this->destroyAccounts([AccountTypeEnum::REVENUE->value]),
|
||||
'liabilities' => $this->destroyAccounts($liabilities),
|
||||
'transactions' => $this->destroyTransactions($transactions),
|
||||
'withdrawals' => $this->destroyTransactions([TransactionTypeEnum::WITHDRAWAL->value]),
|
||||
|
@@ -30,6 +30,8 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Support\Export\ExportDataGenerator;
|
||||
use Illuminate\Http\Response as LaravelResponse;
|
||||
|
||||
use function Safe\date;
|
||||
|
||||
/**
|
||||
* Class ExportController
|
||||
*/
|
||||
@@ -59,7 +61,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function accounts(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -88,7 +90,7 @@ class ExportController extends Controller
|
||||
->header('Expires', '0')
|
||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||
->header('Pragma', 'public')
|
||||
->header('Content-Length', (string)strlen($data[$key]))
|
||||
->header('Content-Length', (string) strlen((string) $data[$key]))
|
||||
;
|
||||
|
||||
return $response;
|
||||
@@ -100,7 +102,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function bills(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -115,7 +117,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function budgets(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -130,7 +132,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function categories(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -145,7 +147,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function piggyBanks(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -160,7 +162,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function recurring(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -175,7 +177,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function rules(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -190,7 +192,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function tags(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
|
@@ -29,13 +29,13 @@ use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
@@ -52,7 +52,7 @@ class PurgeController extends Controller
|
||||
public function purge(): JsonResponse
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$user = auth()->user();
|
||||
|
||||
// some manual code, too lazy to call all repositories.
|
||||
|
||||
@@ -63,14 +63,17 @@ class PurgeController extends Controller
|
||||
Bill::whereUserId($user->id)->onlyTrashed()->forceDelete();
|
||||
|
||||
// piggies
|
||||
$set = PiggyBank::leftJoin('accounts', 'accounts.id', 'piggy_banks.account_id')
|
||||
->where('accounts.user_id', $user->id)->onlyTrashed()->get(['piggy_banks.*'])
|
||||
;
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($set as $piggy) {
|
||||
$piggy->forceDelete();
|
||||
}
|
||||
$repository = app(PiggyBankRepositoryInterface::class);
|
||||
$repository->setUser($user);
|
||||
$repository->purgeAll();
|
||||
// $set = PiggyBank::leftJoin('accounts', 'accounts.id', 'piggy_banks.account_id')
|
||||
// ->where('accounts.user_id', $user->id)->onlyTrashed()->get(['piggy_banks.*'])
|
||||
// ;
|
||||
//
|
||||
// /** @var PiggyBank $piggy */
|
||||
// foreach ($set as $piggy) {
|
||||
// $piggy->forceDelete();
|
||||
// }
|
||||
|
||||
// rule group
|
||||
RuleGroup::whereUserId($user->id)->onlyTrashed()->forceDelete();
|
||||
|
@@ -79,11 +79,11 @@ class AccountController extends Controller
|
||||
/** @var array $expense */
|
||||
foreach ($expenses as $expense) {
|
||||
$result[] = [
|
||||
'id' => (string)$expense['id'],
|
||||
'id' => (string) $expense['id'],
|
||||
'name' => $expense['name'],
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float)$expense['sum'], // intentional float
|
||||
'currency_id' => (string)$expense['currency_id'],
|
||||
'difference_float' => (float) $expense['sum'], // intentional float
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
}
|
||||
@@ -107,11 +107,11 @@ class AccountController extends Controller
|
||||
/** @var array $expense */
|
||||
foreach ($expenses as $expense) {
|
||||
$result[] = [
|
||||
'id' => (string)$expense['id'],
|
||||
'id' => (string) $expense['id'],
|
||||
'name' => $expense['name'],
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float)$expense['sum'], // intentional float
|
||||
'currency_id' => (string)$expense['currency_id'],
|
||||
'difference_float' => (float) $expense['sum'], // intentional float
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
}
|
||||
|
@@ -29,7 +29,9 @@ use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class BillController
|
||||
@@ -63,11 +65,13 @@ class BillController extends Controller
|
||||
*/
|
||||
public function bill(GenericRequest $request): JsonResponse
|
||||
{
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$bills = $request->getBills();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$bills = $request->getBills();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$convertToNative = Amount::convertToNative();
|
||||
$default = Amount::getNativeCurrency();
|
||||
$response = [];
|
||||
|
||||
// get all bills:
|
||||
if (0 === $bills->count()) {
|
||||
@@ -75,39 +79,42 @@ class BillController extends Controller
|
||||
}
|
||||
|
||||
// collect all expenses in this period (regardless of type) by the given bills and accounts.
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setRange($start, $end)->setSourceAccounts($accounts);
|
||||
$collector->setBills($bills);
|
||||
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
foreach ($genericSet as $journal) {
|
||||
$billId = (int)$journal['bill_id'];
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
$key = sprintf('%d-%d', $billId, $currencyId);
|
||||
$foreignKey = sprintf('%d-%d', $billId, $foreignCurrencyId);
|
||||
$billId = (int) $journal['bill_id'];
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currencyCode = $journal['currency_code'];
|
||||
$field = 'amount';
|
||||
|
||||
// use the native amount if the user wants to convert to native currency
|
||||
if ($convertToNative && $currencyId !== $default->id) {
|
||||
$currencyId = $default->id;
|
||||
$currencyCode = $default->code;
|
||||
$field = 'native_amount';
|
||||
}
|
||||
// use foreign amount when the foreign currency IS the default currency.
|
||||
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
|
||||
$field = 'foreign_amount';
|
||||
}
|
||||
Log::debug(sprintf('Journal #%d in bill #%d will use %s (%s %s)', $journal['transaction_group_id'], $billId, $field, $currencyCode, $journal[$field] ?? '0'));
|
||||
|
||||
$key = sprintf('%d-%d', $billId, $currencyId);
|
||||
|
||||
if (0 !== $currencyId) {
|
||||
$response[$key] ??= [
|
||||
'id' => (string)$billId,
|
||||
'id' => (string) $billId,
|
||||
'name' => $journal['bill_name'],
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$currencyId,
|
||||
'currency_code' => $journal['currency_code'],
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $currencyCode,
|
||||
];
|
||||
$response[$key]['difference'] = bcadd($response[$key]['difference'], $journal['amount']);
|
||||
$response[$key]['difference_float'] = (float)$response[$key]['difference']; // intentional float
|
||||
}
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$response[$foreignKey] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignKey]['difference'] = bcadd($response[$foreignKey]['difference'], $journal['foreign_amount']);
|
||||
$response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference']; // intentional float
|
||||
$response[$key]['difference'] = bcadd($response[$key]['difference'], (string) ($journal[$field] ?? '0'));
|
||||
$response[$key]['difference_float'] = (float) $response[$key]['difference']; // intentional float
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,41 +129,46 @@ class BillController extends Controller
|
||||
*/
|
||||
public function noBill(GenericRequest $request): JsonResponse
|
||||
{
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$convertToNative = Amount::convertToNative();
|
||||
$default = Amount::getNativeCurrency();
|
||||
$response = [];
|
||||
|
||||
// collect all expenses in this period (regardless of type) by the given bills and accounts.
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setRange($start, $end)->setSourceAccounts($accounts);
|
||||
$collector->withoutBill();
|
||||
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currencyCode = $journal['currency_code'];
|
||||
$field = 'amount';
|
||||
|
||||
// use the native amount if the user wants to convert to native currency
|
||||
if ($convertToNative && $currencyId !== $default->id) {
|
||||
$currencyId = $default->id;
|
||||
$currencyCode = $default->code;
|
||||
$field = 'native_amount';
|
||||
}
|
||||
// use foreign amount when the foreign currency IS the default currency.
|
||||
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
|
||||
$field = 'foreign_amount';
|
||||
}
|
||||
Log::debug(sprintf('Journal #%d will use %s (%s %s)', $journal['transaction_group_id'], $field, $currencyCode, $journal[$field] ?? '0'));
|
||||
|
||||
if (0 !== $currencyId) {
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$currencyId,
|
||||
'currency_code' => $journal['currency_code'],
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $currencyCode,
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $journal['amount']);
|
||||
$response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; // intentional float
|
||||
}
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$response[$foreignCurrencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignCurrencyId]['difference'] = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']);
|
||||
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // intentional float
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], (string) ($journal[$field] ?? '0'));
|
||||
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -85,11 +85,11 @@ class BudgetController extends Controller
|
||||
/** @var array $expense */
|
||||
foreach ($expenses as $expense) {
|
||||
$result[] = [
|
||||
'id' => (string)$budget->id,
|
||||
'id' => (string) $budget->id,
|
||||
'name' => $budget->name,
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float)$expense['sum'], // intentional float
|
||||
'currency_id' => (string)$expense['currency_id'],
|
||||
'difference_float' => (float) $expense['sum'], // intentional float
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
}
|
||||
@@ -114,8 +114,8 @@ class BudgetController extends Controller
|
||||
foreach ($expenses as $expense) {
|
||||
$result[] = [
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float)$expense['sum'], // intentional float
|
||||
'currency_id' => (string)$expense['currency_id'],
|
||||
'difference_float' => (float) $expense['sum'], // intentional float
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
}
|
||||
|
@@ -85,11 +85,11 @@ class CategoryController extends Controller
|
||||
/** @var array $expense */
|
||||
foreach ($expenses as $expense) {
|
||||
$result[] = [
|
||||
'id' => (string)$category->id,
|
||||
'id' => (string) $category->id,
|
||||
'name' => $category->name,
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float)$expense['sum'], // intentional float
|
||||
'currency_id' => (string)$expense['currency_id'],
|
||||
'difference_float' => (float) $expense['sum'], // intentional float
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
}
|
||||
@@ -114,8 +114,8 @@ class CategoryController extends Controller
|
||||
foreach ($expenses as $expense) {
|
||||
$result[] = [
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float)$expense['sum'], // intentional float
|
||||
'currency_id' => (string)$expense['currency_id'],
|
||||
'difference_float' => (float) $expense['sum'], // intentional float
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
}
|
||||
|
@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class PeriodController
|
||||
@@ -41,39 +43,49 @@ class PeriodController extends Controller
|
||||
*/
|
||||
public function total(GenericRequest $request): JsonResponse
|
||||
{
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$convertToNative = Amount::convertToNative();
|
||||
$default = Amount::getNativeCurrency();
|
||||
|
||||
// collect all expenses in this period (regardless of type)
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setRange($start, $end)->setSourceAccounts($accounts);
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
// same code as many other sumExpense methods. I think this needs some kind of generic method.
|
||||
$amount = '0';
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currencyCode = $journal['currency_code'];
|
||||
if ($convertToNative) {
|
||||
$amount = Amount::getAmountFromJournal($journal);
|
||||
if ($default->id !== (int) $journal['currency_id'] && $default->id !== (int) $journal['foreign_currency_id']) {
|
||||
$currencyId = $default->id;
|
||||
$currencyCode = $default->code;
|
||||
}
|
||||
if ($default->id !== (int) $journal['currency_id'] && $default->id === (int) $journal['foreign_currency_id']) {
|
||||
$currencyId = $journal['foreign_currency_id'];
|
||||
$currencyCode = $journal['foreign_currency_code'];
|
||||
}
|
||||
Log::debug(sprintf('[a] Add amount %s %s', $currencyCode, $amount));
|
||||
}
|
||||
if (!$convertToNative) {
|
||||
// ignore the amount in foreign currency.
|
||||
Log::debug(sprintf('[b] Add amount %s %s', $currencyCode, $journal['amount']));
|
||||
$amount = $journal['amount'];
|
||||
}
|
||||
|
||||
if (0 !== $currencyId) {
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$currencyId,
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $journal['amount']);
|
||||
$response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; // intentional float
|
||||
}
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$response[$foreignCurrencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignCurrencyId]['difference'] = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']);
|
||||
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // intentional float
|
||||
}
|
||||
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $currencyCode,
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $amount);
|
||||
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float
|
||||
}
|
||||
|
||||
return response()->json(array_values($response));
|
||||
|
@@ -29,7 +29,9 @@ use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class TagController
|
||||
@@ -62,42 +64,51 @@ class TagController extends Controller
|
||||
*/
|
||||
public function noTag(GenericRequest $request): JsonResponse
|
||||
{
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$convertToNative = Amount::convertToNative();
|
||||
$default = Amount::getNativeCurrency();
|
||||
|
||||
// collect all expenses in this period (regardless of type) by the given bills and accounts.
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setRange($start, $end)->setSourceAccounts($accounts);
|
||||
$collector->withoutTags();
|
||||
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
// same code as many other sumExpense methods. I think this needs some kind of generic method.
|
||||
$amount = '0';
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$currencyCode = $journal['currency_code'];
|
||||
if ($convertToNative) {
|
||||
$amount = Amount::getAmountFromJournal($journal);
|
||||
if ($default->id !== (int) $journal['currency_id'] && $default->id !== (int) $journal['foreign_currency_id']) {
|
||||
$currencyId = $default->id;
|
||||
$currencyCode = $default->code;
|
||||
}
|
||||
if ($default->id !== (int) $journal['currency_id'] && $default->id === (int) $journal['foreign_currency_id']) {
|
||||
$currencyId = $journal['foreign_currency_id'];
|
||||
$currencyCode = $journal['foreign_currency_code'];
|
||||
}
|
||||
Log::debug(sprintf('[a] Add amount %s %s', $currencyCode, $amount));
|
||||
}
|
||||
if (!$convertToNative) {
|
||||
// ignore the amount in foreign currency.
|
||||
Log::debug(sprintf('[b] Add amount %s %s', $currencyCode, $journal['amount']));
|
||||
$amount = $journal['amount'];
|
||||
}
|
||||
|
||||
if (0 !== $currencyId) {
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$currencyId,
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $journal['amount']);
|
||||
$response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; // float but on purpose.
|
||||
}
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$response[$foreignCurrencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignCurrencyId]['difference'] = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']);
|
||||
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // float but on purpose.
|
||||
}
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $currencyCode,
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $amount);
|
||||
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // float but on purpose.
|
||||
}
|
||||
|
||||
return response()->json(array_values($response));
|
||||
@@ -130,8 +141,8 @@ class TagController extends Controller
|
||||
|
||||
/** @var array $journal */
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$foreignCurrencyId = (int) $journal['foreign_currency_id'];
|
||||
|
||||
/** @var array $tag */
|
||||
foreach ($journal['tags'] as $tag) {
|
||||
@@ -142,15 +153,15 @@ class TagController extends Controller
|
||||
// on currency ID
|
||||
if (0 !== $currencyId) {
|
||||
$response[$key] ??= [
|
||||
'id' => (string)$tagId,
|
||||
'id' => (string) $tagId,
|
||||
'name' => $tag['name'],
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$currencyId,
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$key]['difference'] = bcadd($response[$key]['difference'], $journal['amount']);
|
||||
$response[$key]['difference_float'] = (float)$response[$key]['difference']; // float but on purpose.
|
||||
$response[$key]['difference'] = bcadd((string) $response[$key]['difference'], (string) $journal['amount']);
|
||||
$response[$key]['difference_float'] = (float) $response[$key]['difference']; // float but on purpose.
|
||||
}
|
||||
|
||||
// on foreign ID
|
||||
@@ -158,11 +169,11 @@ class TagController extends Controller
|
||||
$response[$foreignKey] = $journal[$foreignKey] ?? [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$foreignCurrencyId,
|
||||
'currency_id' => (string) $foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignKey]['difference'] = bcadd($response[$foreignKey]['difference'], $journal['foreign_amount']);
|
||||
$response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference']; // float but on purpose.
|
||||
$response[$foreignKey]['difference'] = bcadd((string) $response[$foreignKey]['difference'], (string) $journal['foreign_amount']);
|
||||
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // float but on purpose.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -73,17 +73,18 @@ class AccountController extends Controller
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$assetAccounts = $request->getAssetAccounts();
|
||||
|
||||
$income = $this->opsRepository->sumIncomeByDestination($start, $end, $assetAccounts);
|
||||
$result = [];
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($income as $entry) {
|
||||
$result[] = [
|
||||
'id' => (string)$entry['id'],
|
||||
'id' => (string) $entry['id'],
|
||||
'name' => $entry['name'],
|
||||
'difference' => $entry['sum'],
|
||||
'difference_float' => (float)$entry['sum'], // float but on purpose.
|
||||
'currency_id' => (string)$entry['currency_id'],
|
||||
'difference_float' => (float) $entry['sum'], // float but on purpose.
|
||||
'currency_id' => (string) $entry['currency_id'],
|
||||
'currency_code' => $entry['currency_code'],
|
||||
];
|
||||
}
|
||||
@@ -107,11 +108,11 @@ class AccountController extends Controller
|
||||
/** @var array $entry */
|
||||
foreach ($income as $entry) {
|
||||
$result[] = [
|
||||
'id' => (string)$entry['id'],
|
||||
'id' => (string) $entry['id'],
|
||||
'name' => $entry['name'],
|
||||
'difference' => $entry['sum'],
|
||||
'difference_float' => (float)$entry['sum'], // float but on purpose.
|
||||
'currency_id' => (string)$entry['currency_id'],
|
||||
'difference_float' => (float) $entry['sum'], // float but on purpose.
|
||||
'currency_id' => (string) $entry['currency_id'],
|
||||
'currency_code' => $entry['currency_code'],
|
||||
];
|
||||
}
|
||||
|
@@ -85,11 +85,11 @@ class CategoryController extends Controller
|
||||
/** @var array $expense */
|
||||
foreach ($expenses as $expense) {
|
||||
$result[] = [
|
||||
'id' => (string)$category->id,
|
||||
'id' => (string) $category->id,
|
||||
'name' => $category->name,
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float)$expense['sum'], // float but on purpose.
|
||||
'currency_id' => (string)$expense['currency_id'],
|
||||
'difference_float' => (float) $expense['sum'], // float but on purpose.
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
}
|
||||
@@ -114,8 +114,8 @@ class CategoryController extends Controller
|
||||
foreach ($expenses as $expense) {
|
||||
$result[] = [
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float)$expense['sum'], // float but on purpose.
|
||||
'currency_id' => (string)$expense['currency_id'],
|
||||
'difference_float' => (float) $expense['sum'], // float but on purpose.
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
}
|
||||
|
@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
@@ -41,42 +42,41 @@ class PeriodController extends Controller
|
||||
*/
|
||||
public function total(GenericRequest $request): JsonResponse
|
||||
{
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$convertToNative = Amount::convertToNative();
|
||||
$default = Amount::getNativeCurrency();
|
||||
|
||||
// collect all expenses in this period (regardless of type)
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes([TransactionTypeEnum::DEPOSIT->value])->setRange($start, $end)->setDestinationAccounts($accounts);
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
// currency
|
||||
$currencyId = $journal['currency_id'];
|
||||
$currencyCode = $journal['currency_code'];
|
||||
$field = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount';
|
||||
|
||||
if (0 !== $currencyId) {
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$currencyId,
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount']));
|
||||
$response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; // float but on purpose.
|
||||
// perhaps use default currency instead?
|
||||
if ($convertToNative && $journal['currency_id'] !== $default->id) {
|
||||
$currencyId = $default->id;
|
||||
$currencyCode = $default->code;
|
||||
}
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$response[$foreignCurrencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignCurrencyId]['difference'] = bcadd(
|
||||
$response[$foreignCurrencyId]['difference'],
|
||||
app('steam')->positive($journal['foreign_amount'])
|
||||
);
|
||||
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // float but on purpose.
|
||||
// use foreign amount when the foreign currency IS the default currency.
|
||||
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
|
||||
$field = 'foreign_amount';
|
||||
}
|
||||
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $currencyCode,
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], (string) app('steam')->positive($journal[$field]));
|
||||
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // float but on purpose.
|
||||
}
|
||||
|
||||
return response()->json(array_values($response));
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
@@ -63,45 +64,45 @@ class TagController extends Controller
|
||||
*/
|
||||
public function noTag(GenericRequest $request): JsonResponse
|
||||
{
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$convertToNative = Amount::convertToNative();
|
||||
$default = Amount::getNativeCurrency();
|
||||
|
||||
// collect all expenses in this period (regardless of type) by the given bills and accounts.
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes([TransactionTypeEnum::DEPOSIT->value])->setRange($start, $end)->setDestinationAccounts($accounts);
|
||||
$collector->withoutTags();
|
||||
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
// currency
|
||||
$currencyId = $journal['currency_id'];
|
||||
$currencyCode = $journal['currency_code'];
|
||||
$field = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount';
|
||||
|
||||
if (0 !== $currencyId) {
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$currencyId,
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount']));
|
||||
$response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference'];
|
||||
// perhaps use default currency instead?
|
||||
if ($convertToNative && $journal['currency_id'] !== $default->id) {
|
||||
$currencyId = $default->id;
|
||||
$currencyCode = $default->code;
|
||||
}
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$response[$foreignCurrencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignCurrencyId]['difference'] = bcadd(
|
||||
$response[$foreignCurrencyId]['difference'],
|
||||
app('steam')->positive($journal['foreign_amount'])
|
||||
);
|
||||
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference'];
|
||||
// use foreign amount when the foreign currency IS the default currency.
|
||||
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
|
||||
$field = 'foreign_amount';
|
||||
}
|
||||
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $currencyCode,
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], (string) app('steam')->positive($journal[$field]));
|
||||
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
|
||||
|
||||
}
|
||||
|
||||
return response()->json(array_values($response));
|
||||
@@ -134,8 +135,8 @@ class TagController extends Controller
|
||||
|
||||
/** @var array $journal */
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$foreignCurrencyId = (int) $journal['foreign_currency_id'];
|
||||
|
||||
/** @var array $tag */
|
||||
foreach ($journal['tags'] as $tag) {
|
||||
@@ -146,15 +147,15 @@ class TagController extends Controller
|
||||
// on currency ID
|
||||
if (0 !== $currencyId) {
|
||||
$response[$key] ??= [
|
||||
'id' => (string)$tagId,
|
||||
'id' => (string) $tagId,
|
||||
'name' => $tag['name'],
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$currencyId,
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$key]['difference'] = bcadd($response[$key]['difference'], app('steam')->positive($journal['amount']));
|
||||
$response[$key]['difference_float'] = (float)$response[$key]['difference'];
|
||||
$response[$key]['difference'] = bcadd((string) $response[$key]['difference'], (string) app('steam')->positive($journal['amount']));
|
||||
$response[$key]['difference_float'] = (float) $response[$key]['difference'];
|
||||
}
|
||||
|
||||
// on foreign ID
|
||||
@@ -162,14 +163,14 @@ class TagController extends Controller
|
||||
$response[$foreignKey] = $journal[$foreignKey] ?? [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$foreignCurrencyId,
|
||||
'currency_id' => (string) $foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignKey]['difference'] = bcadd(
|
||||
$response[$foreignKey]['difference'],
|
||||
app('steam')->positive($journal['foreign_amount'])
|
||||
(string) $response[$foreignKey]['difference'],
|
||||
(string) app('steam')->positive($journal['foreign_amount'])
|
||||
);
|
||||
$response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference'];
|
||||
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -85,11 +85,11 @@ class CategoryController extends Controller
|
||||
/** @var array $expense */
|
||||
foreach ($expenses as $expense) {
|
||||
$result[] = [
|
||||
'id' => (string)$category->id,
|
||||
'id' => (string) $category->id,
|
||||
'name' => $category->name,
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float)$expense['sum'],
|
||||
'currency_id' => (string)$expense['currency_id'],
|
||||
'difference_float' => (float) $expense['sum'],
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
}
|
||||
@@ -114,8 +114,8 @@ class CategoryController extends Controller
|
||||
foreach ($expenses as $expense) {
|
||||
$result[] = [
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float)$expense['sum'],
|
||||
'currency_id' => (string)$expense['currency_id'],
|
||||
'difference_float' => (float) $expense['sum'],
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
}
|
||||
|
@@ -26,8 +26,9 @@ namespace FireflyIII\Api\V1\Controllers\Insight\Transfer;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
@@ -41,42 +42,42 @@ class PeriodController extends Controller
|
||||
*/
|
||||
public function total(GenericRequest $request): JsonResponse
|
||||
{
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$convertToNative = Amount::convertToNative();
|
||||
$default = Amount::getNativeCurrency();
|
||||
|
||||
// collect all expenses in this period (regardless of type)
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes([TransactionType::TRANSFER])->setRange($start, $end)->setDestinationAccounts($accounts);
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes([TransactionTypeEnum::TRANSFER->value])->setRange($start, $end)->setDestinationAccounts($accounts);
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
// currency
|
||||
$currencyId = $journal['currency_id'];
|
||||
$currencyCode = $journal['currency_code'];
|
||||
$field = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount';
|
||||
|
||||
if (0 !== $currencyId) {
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$currencyId,
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount']));
|
||||
$response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference'];
|
||||
// perhaps use default currency instead?
|
||||
if ($convertToNative && $journal['currency_id'] !== $default->id) {
|
||||
$currencyId = $default->id;
|
||||
$currencyCode = $default->code;
|
||||
}
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$response[$foreignCurrencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignCurrencyId]['difference'] = bcadd(
|
||||
$response[$foreignCurrencyId]['difference'],
|
||||
app('steam')->positive($journal['foreign_amount'])
|
||||
);
|
||||
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference'];
|
||||
// use foreign amount when the foreign currency IS the default currency.
|
||||
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
|
||||
$field = 'foreign_amount';
|
||||
}
|
||||
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $currencyCode,
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], (string) app('steam')->positive($journal[$field]));
|
||||
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
|
||||
|
||||
}
|
||||
|
||||
return response()->json(array_values($response));
|
||||
|
@@ -26,9 +26,10 @@ namespace FireflyIII\Api\V1\Controllers\Insight\Transfer;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
@@ -61,45 +62,46 @@ class TagController extends Controller
|
||||
*/
|
||||
public function noTag(GenericRequest $request): JsonResponse
|
||||
{
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$accounts = $request->getAssetAccounts();
|
||||
$start = $request->getStart();
|
||||
$end = $request->getEnd();
|
||||
$response = [];
|
||||
$convertToNative = Amount::convertToNative();
|
||||
$default = Amount::getNativeCurrency();
|
||||
|
||||
|
||||
// collect all expenses in this period (regardless of type) by the given bills and accounts.
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes([TransactionType::TRANSFER])->setRange($start, $end)->setDestinationAccounts($accounts);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes([TransactionTypeEnum::TRANSFER->value])->setRange($start, $end)->setDestinationAccounts($accounts);
|
||||
$collector->withoutTags();
|
||||
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
// currency
|
||||
$currencyId = $journal['currency_id'];
|
||||
$currencyCode = $journal['currency_code'];
|
||||
$field = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount';
|
||||
|
||||
if (0 !== $currencyId) {
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$currencyId,
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount']));
|
||||
$response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference'];
|
||||
// perhaps use default currency instead?
|
||||
if ($convertToNative && $journal['currency_id'] !== $default->id) {
|
||||
$currencyId = $default->id;
|
||||
$currencyCode = $default->code;
|
||||
}
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$response[$foreignCurrencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignCurrencyId]['difference'] = bcadd(
|
||||
$response[$foreignCurrencyId]['difference'],
|
||||
app('steam')->positive($journal['foreign_amount'])
|
||||
);
|
||||
$response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference'];
|
||||
// use foreign amount when the foreign currency IS the default currency.
|
||||
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
|
||||
$field = 'foreign_amount';
|
||||
}
|
||||
|
||||
$response[$currencyId] ??= [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $currencyCode,
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], (string) app('steam')->positive($journal[$field]));
|
||||
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
|
||||
|
||||
}
|
||||
|
||||
return response()->json(array_values($response));
|
||||
@@ -126,14 +128,14 @@ class TagController extends Controller
|
||||
|
||||
// collect all expenses in this period (regardless of type) by the given bills and accounts.
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes([TransactionType::TRANSFER])->setRange($start, $end)->setDestinationAccounts($accounts);
|
||||
$collector->setTypes([TransactionTypeEnum::TRANSFER->value])->setRange($start, $end)->setDestinationAccounts($accounts);
|
||||
$collector->setTags($tags);
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
|
||||
/** @var array $journal */
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
$currencyId = (int) $journal['currency_id'];
|
||||
$foreignCurrencyId = (int) $journal['foreign_currency_id'];
|
||||
|
||||
/** @var array $tag */
|
||||
foreach ($journal['tags'] as $tag) {
|
||||
@@ -144,15 +146,15 @@ class TagController extends Controller
|
||||
// on currency ID
|
||||
if (0 !== $currencyId) {
|
||||
$response[$key] ??= [
|
||||
'id' => (string)$tagId,
|
||||
'id' => (string) $tagId,
|
||||
'name' => $tag['name'],
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$currencyId,
|
||||
'currency_id' => (string) $currencyId,
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$key]['difference'] = bcadd($response[$key]['difference'], app('steam')->positive($journal['amount']));
|
||||
$response[$key]['difference_float'] = (float)$response[$key]['difference'];
|
||||
$response[$key]['difference'] = bcadd((string) $response[$key]['difference'], (string) app('steam')->positive($journal['amount']));
|
||||
$response[$key]['difference_float'] = (float) $response[$key]['difference'];
|
||||
}
|
||||
|
||||
// on foreign ID
|
||||
@@ -160,14 +162,14 @@ class TagController extends Controller
|
||||
$response[$foreignKey] = $journal[$foreignKey] ?? [
|
||||
'difference' => '0',
|
||||
'difference_float' => 0,
|
||||
'currency_id' => (string)$foreignCurrencyId,
|
||||
'currency_id' => (string) $foreignCurrencyId,
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignKey]['difference'] = bcadd(
|
||||
$response[$foreignKey]['difference'],
|
||||
app('steam')->positive($journal['foreign_amount'])
|
||||
(string) $response[$foreignKey]['difference'],
|
||||
(string) app('steam')->positive($journal['foreign_amount'])
|
||||
);
|
||||
$response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference']; // intentional float
|
||||
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
@@ -111,7 +112,7 @@ class ListController extends Controller
|
||||
// types to get, page size:
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
|
||||
// get list of budgets. Count it and split it.
|
||||
// get list of piggy banks. Count it and split it.
|
||||
$collection = $this->repository->getPiggyBanks($account);
|
||||
$count = $collection->count();
|
||||
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
@@ -140,18 +141,18 @@ class ListController extends Controller
|
||||
*/
|
||||
public function transactions(Request $request, Account $account): JsonResponse
|
||||
{
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
$type = $request->get('type') ?? 'default';
|
||||
$this->parameters->set('type', $type);
|
||||
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||
$manager = $this->getManager();
|
||||
$types = $this->mapTransactionTypes($this->parameters->get('type'));
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setUser($admin)->setAccounts(new Collection([$account]))
|
||||
->withAPIInformation()->setLimit($pageSize)->setPage($this->parameters->get('page'))->setTypes($types)
|
||||
;
|
||||
@@ -163,15 +164,19 @@ class ListController extends Controller
|
||||
$collector->setEnd($this->parameters->get('end'));
|
||||
}
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.accounts.transactions', [$account->id]).$this->buildParams());
|
||||
$groups = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($groups, $transformer, 'transactions');
|
||||
$resource = new FractalCollection($transactions, $transformer, 'transactions');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
|
@@ -29,7 +29,9 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
@@ -88,9 +90,16 @@ class ShowController extends Controller
|
||||
$count = $collection->count();
|
||||
|
||||
// continue sort:
|
||||
|
||||
$accounts = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$accounts = $enrichment->enrich($accounts);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.accounts.index').$this->buildParams());
|
||||
@@ -118,6 +127,15 @@ class ShowController extends Controller
|
||||
$account->refresh();
|
||||
$manager = $this->getManager();
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$account = $enrichment->enrichSingle($account);
|
||||
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -27,7 +27,9 @@ namespace FireflyIII\Api\V1\Controllers\Models\Account;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\Account\StoreRequest;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
@@ -69,6 +71,14 @@ class StoreController extends Controller
|
||||
$account = $this->repository->store($data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$account = $enrichment->enrichSingle($account);
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\Account\UpdateRequest;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
@@ -73,6 +75,14 @@ class UpdateController extends Controller
|
||||
$account->refresh();
|
||||
app('preferences')->mark();
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$account = $enrichment->enrichSingle($account);
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -105,7 +105,7 @@ class ShowController extends Controller
|
||||
->header('Expires', '0')
|
||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||
->header('Pragma', 'public')
|
||||
->header('Content-Length', (string)strlen($content))
|
||||
->header('Content-Length', (string) strlen($content))
|
||||
;
|
||||
|
||||
return $response;
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\RuleTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
@@ -176,7 +177,11 @@ class ListController extends Controller
|
||||
// get paginator.
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.bills.transactions', [$bill->id]).$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -25,12 +25,14 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Controllers\Models\Budget;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
@@ -171,7 +173,11 @@ class ListController extends Controller
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.budgets.transactions', [$budget->id]).$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
@@ -208,6 +214,8 @@ class ListController extends Controller
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
// withdrawals only
|
||||
->setTypes([TransactionTypeEnum::WITHDRAWAL->value])
|
||||
// filter on budget.
|
||||
->withoutBudget()
|
||||
// all info needed for the API:
|
||||
@@ -229,7 +237,11 @@ class ListController extends Controller
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.budgets.without-budget').$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -84,7 +85,11 @@ class ListController extends Controller
|
||||
$collector->setTypes($types);
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.budgets.limits.transactions', [$budget->id, $budgetLimit->id]).$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -100,7 +100,7 @@ class ShowController extends Controller
|
||||
*
|
||||
* Display a listing of the budget limits for this budget.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function indexAll(SameDateRequest $request): JsonResponse
|
||||
{
|
||||
|
@@ -69,6 +69,7 @@ class StoreController extends Controller
|
||||
$data = $request->getAll();
|
||||
$data['start_date'] = $data['start'];
|
||||
$data['end_date'] = $data['end'];
|
||||
$data['notes'] = $data['notes'];
|
||||
$data['budget_id'] = $budget->id;
|
||||
|
||||
$budgetLimit = $this->blRepository->store($data);
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
@@ -139,7 +140,11 @@ class ListController extends Controller
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.categories.transactions', [$category->id]).$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* DestroyController.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\DestroyRequest;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Exceptions\ValidationException;
|
||||
use FireflyIII\Models\CurrencyExchangeRate;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class DestroyController extends Controller
|
||||
{
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
public const string RESOURCE_KEY = 'exchange-rates';
|
||||
protected array $acceptedRoles = [UserRoleEnum::OWNER];
|
||||
private ExchangeRateRepositoryInterface $repository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(ExchangeRateRepositoryInterface::class);
|
||||
$this->repository->setUserGroup($this->validateUserGroup($request));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function destroy(DestroyRequest $request, TransactionCurrency $from, TransactionCurrency $to): JsonResponse
|
||||
{
|
||||
$date = $request->getDate();
|
||||
if (null === $date) {
|
||||
throw new ValidationException('Date is required');
|
||||
}
|
||||
$rate = $this->repository->getSpecificRateOnDate($from, $to, $date);
|
||||
if (null === $rate) {
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
$this->repository->deleteRate($rate);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
public function destroySingle(CurrencyExchangeRate $exchangeRate): JsonResponse
|
||||
{
|
||||
$this->repository->deleteRate($exchangeRate);
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* IndexController.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate;
|
||||
|
||||
use FireflyIII\Api\V2\Controllers\Controller;
|
||||
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use FireflyIII\Transformers\ExchangeRateTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
|
||||
/**
|
||||
* Class ShowController
|
||||
*/
|
||||
class IndexController extends Controller
|
||||
{
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
public const string RESOURCE_KEY = 'currency_exchange_rates';
|
||||
|
||||
private ExchangeRateRepositoryInterface $repository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(ExchangeRateRepositoryInterface::class);
|
||||
$this->repository->setUserGroup($this->validateUserGroup($request));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
$entries = $this->repository->getAll();
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
$count = $entries->count();
|
||||
$entries = $entries->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
$paginator = new LengthAwarePaginator($entries, $count, $pageSize, $this->parameters->get('page'));
|
||||
$transformer = new ExchangeRateTransformer();
|
||||
$transformer->setParameters($this->parameters); // give params to transformer
|
||||
|
||||
return response()
|
||||
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
|
||||
->header('Content-Type', self::CONTENT_TYPE)
|
||||
;
|
||||
}
|
||||
}
|
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* ShowController.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate;
|
||||
|
||||
use FireflyIII\Api\V2\Controllers\Controller;
|
||||
use FireflyIII\Models\CurrencyExchangeRate;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use FireflyIII\Transformers\ExchangeRateTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
|
||||
/**
|
||||
* Class ShowController
|
||||
*/
|
||||
class ShowController extends Controller
|
||||
{
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
public const string RESOURCE_KEY = 'exchange-rates';
|
||||
|
||||
private ExchangeRateRepositoryInterface $repository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(ExchangeRateRepositoryInterface::class);
|
||||
$this->repository->setUserGroup($this->validateUserGroup($request));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function show(TransactionCurrency $from, TransactionCurrency $to): JsonResponse
|
||||
{
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
$page = $this->parameters->get('page');
|
||||
$rates = $this->repository->getRates($from, $to);
|
||||
$count = $rates->count();
|
||||
$rates = $rates->slice(($page - 1) * $pageSize, $pageSize);
|
||||
$paginator = new LengthAwarePaginator($rates, $count, $pageSize, $page);
|
||||
|
||||
$transformer = new ExchangeRateTransformer();
|
||||
$transformer->setParameters($this->parameters); // give params to transformer
|
||||
|
||||
return response()
|
||||
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
|
||||
->header('Content-Type', self::CONTENT_TYPE)
|
||||
;
|
||||
}
|
||||
|
||||
public function showSingle(CurrencyExchangeRate $exchangeRate): JsonResponse
|
||||
{
|
||||
$transformer = new ExchangeRateTransformer();
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
return response()
|
||||
->api($this->jsonApiObject(self::RESOURCE_KEY, $exchangeRate, $transformer))
|
||||
->header('Content-Type', self::CONTENT_TYPE)
|
||||
;
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* StoreController.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\StoreRequest;
|
||||
use FireflyIII\Api\V2\Controllers\Controller;
|
||||
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use FireflyIII\Transformers\ExchangeRateTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class StoreController extends Controller
|
||||
{
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
public const string RESOURCE_KEY = 'exchange-rates';
|
||||
|
||||
private ExchangeRateRepositoryInterface $repository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(ExchangeRateRepositoryInterface::class);
|
||||
$this->repository->setUserGroup($this->validateUserGroup($request));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function store(StoreRequest $request): JsonResponse
|
||||
{
|
||||
$date = $request->getDate();
|
||||
$rate = $request->getRate();
|
||||
$from = $request->getFromCurrency();
|
||||
$to = $request->getToCurrency();
|
||||
|
||||
// already has rate?
|
||||
$object = $this->repository->getSpecificRateOnDate($from, $to, $date);
|
||||
if (null !== $object) {
|
||||
// just update it, no matter.
|
||||
$rate = $this->repository->updateExchangeRate($object, $rate, $date);
|
||||
}
|
||||
if (null === $object) {
|
||||
// store new
|
||||
$rate = $this->repository->storeExchangeRate($from, $to, $rate, $date);
|
||||
}
|
||||
|
||||
$transformer = new ExchangeRateTransformer();
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
return response()
|
||||
->api($this->jsonApiObject(self::RESOURCE_KEY, $rate, $transformer))
|
||||
->header('Content-Type', self::CONTENT_TYPE)
|
||||
;
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* UpdateController.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate;
|
||||
|
||||
use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\UpdateRequest;
|
||||
use FireflyIII\Api\V2\Controllers\Controller;
|
||||
use FireflyIII\Models\CurrencyExchangeRate;
|
||||
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use FireflyIII\Transformers\ExchangeRateTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class UpdateController extends Controller
|
||||
{
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
public const string RESOURCE_KEY = 'exchange-rates';
|
||||
|
||||
private ExchangeRateRepositoryInterface $repository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(ExchangeRateRepositoryInterface::class);
|
||||
$this->repository->setUserGroup($this->validateUserGroup($request));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function update(UpdateRequest $request, CurrencyExchangeRate $exchangeRate): JsonResponse
|
||||
{
|
||||
$date = $request->getDate();
|
||||
$rate = $request->getRate();
|
||||
$exchangeRate = $this->repository->updateExchangeRate($exchangeRate, $rate, $date);
|
||||
$transformer = new ExchangeRateTransformer();
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
return response()
|
||||
->api($this->jsonApiObject(self::RESOURCE_KEY, $exchangeRate, $transformer))
|
||||
->header('Content-Type', self::CONTENT_TYPE)
|
||||
;
|
||||
}
|
||||
}
|
@@ -28,8 +28,11 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankEventTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
@@ -58,6 +61,46 @@ class ListController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/piggy_banks/listAccountByPiggyBank
|
||||
*
|
||||
* List single resource.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function accounts(PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
// types to get, page size:
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
$manager = $this->getManager();
|
||||
|
||||
$collection = $piggyBank->accounts;
|
||||
$count = $collection->count();
|
||||
$accounts = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$accounts = $enrichment->enrich($accounts);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.piggy-banks.accounts', [$piggyBank->id]).$this->buildParams());
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($accounts, $transformer, 'accounts');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/piggy_banks/listAttachmentByPiggyBank
|
||||
|
@@ -72,7 +72,7 @@ class ShowController extends Controller
|
||||
// types to get, page size:
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
|
||||
// get list of budgets. Count it and split it.
|
||||
// get list of piggy banks. Count it and split it.
|
||||
$collection = $this->repository->getPiggyBanks();
|
||||
$count = $collection->count();
|
||||
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Recurrence;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -110,7 +111,11 @@ class ListController extends Controller
|
||||
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.transactions.index').$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -37,7 +37,7 @@ class ExpressionController extends Controller
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/rules/validateExpression
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function validateExpression(ValidateExpressionRequest $request): JsonResponse
|
||||
{
|
||||
|
@@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Models\Rule\TestRequest;
|
||||
use FireflyIII\Api\V1\Requests\Models\Rule\TriggerRequest;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
@@ -94,6 +95,11 @@ class TriggerController extends Controller
|
||||
$transactions = $ruleEngine->find();
|
||||
$count = $transactions->count();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($rule->user);
|
||||
$transactions = $enrichment->enrich($transactions);
|
||||
|
||||
$paginator = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.rules.test', [$rule->id]).$this->buildParams());
|
||||
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Api\V1\Requests\Models\RuleGroup\TriggerRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
@@ -100,6 +101,11 @@ class TriggerController extends Controller
|
||||
$transactions = $ruleEngine->find();
|
||||
$count = $transactions->count();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($group->user);
|
||||
$transactions = $enrichment->enrich($transactions);
|
||||
|
||||
$paginator = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.rule-groups.test', [$group->id]).$this->buildParams());
|
||||
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
@@ -141,7 +142,12 @@ class ListController extends Controller
|
||||
}
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.tags.transactions', [$tag->id]).$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -85,7 +86,11 @@ class ShowController extends Controller
|
||||
}
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.transactions.index').$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
@@ -137,6 +142,11 @@ class ShowController extends Controller
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$selectedGroup = $enrichment->enrichSingle($selectedGroup);
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\Transaction;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\Transaction\StoreRequest;
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Events\StoredTransactionGroup;
|
||||
use FireflyIII\Exceptions\DuplicateTransactionException;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
@@ -33,10 +34,12 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||
use FireflyIII\Rules\IsDuplicateTransaction;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
@@ -47,6 +50,7 @@ class StoreController extends Controller
|
||||
{
|
||||
use TransactionFilter;
|
||||
|
||||
protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS];
|
||||
private TransactionGroupRepositoryInterface $groupRepository;
|
||||
|
||||
/**
|
||||
@@ -59,9 +63,11 @@ class StoreController extends Controller
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$userGroup = $this->validateUserGroup($request);
|
||||
|
||||
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
|
||||
$this->groupRepository->setUser($admin);
|
||||
$this->groupRepository->setUserGroup($userGroup);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -79,61 +85,64 @@ class StoreController extends Controller
|
||||
public function store(StoreRequest $request): JsonResponse
|
||||
{
|
||||
app('log')->debug('Now in API StoreController::store()');
|
||||
$data = $request->getAll();
|
||||
$data['user'] = auth()->user()->id;
|
||||
$data = $request->getAll();
|
||||
$data['user'] = auth()->user();
|
||||
$data['user_group'] = $this->userGroup;
|
||||
|
||||
Log::channel('audit')
|
||||
->info('Store new transaction over API.', $data)
|
||||
;
|
||||
|
||||
Log::channel('audit')->info('Store new transaction over API.', $data);
|
||||
|
||||
try {
|
||||
$transactionGroup = $this->groupRepository->store($data);
|
||||
} catch (DuplicateTransactionException $e) { // @phpstan-ignore-line
|
||||
} catch (DuplicateTransactionException $e) {
|
||||
app('log')->warning('Caught a duplicate transaction. Return error message.');
|
||||
$validator = \Validator::make(
|
||||
['transactions' => [['description' => $e->getMessage()]]],
|
||||
['transactions.0.description' => new IsDuplicateTransaction()]
|
||||
);
|
||||
$validator = Validator::make(['transactions' => [['description' => $e->getMessage()]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
|
||||
|
||||
throw new ValidationException($validator); // @phpstan-ignore-line
|
||||
} catch (FireflyException $e) { // @phpstan-ignore-line
|
||||
throw new ValidationException($validator);
|
||||
} catch (FireflyException $e) {
|
||||
app('log')->warning('Caught an exception. Return error message.');
|
||||
app('log')->error($e->getMessage());
|
||||
$message = sprintf('Internal exception: %s', $e->getMessage());
|
||||
$validator = \Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
|
||||
$validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
|
||||
|
||||
throw new ValidationException($validator); // @phpstan-ignore-line
|
||||
throw new ValidationException($validator);
|
||||
}
|
||||
app('preferences')->mark();
|
||||
$applyRules = $data['apply_rules'] ?? true;
|
||||
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
||||
$applyRules = $data['apply_rules'] ?? true;
|
||||
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
||||
event(new StoredTransactionGroup($transactionGroup, $applyRules, $fireWebhooks));
|
||||
|
||||
$manager = $this->getManager();
|
||||
$manager = $this->getManager();
|
||||
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$admin = auth()->user();
|
||||
|
||||
// use new group collector:
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector
|
||||
->setUser($admin)
|
||||
->setUserGroup($this->userGroup)
|
||||
// filter on transaction group.
|
||||
->setTransactionGroup($transactionGroup)
|
||||
// all info needed for the API:
|
||||
->withAPIInformation()
|
||||
;
|
||||
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
if (null === $selectedGroup) {
|
||||
throw new FireflyException('200032: Cannot find transaction. Possibly, a rule deleted this transaction after its creation.');
|
||||
}
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$selectedGroup = $enrichment->enrichSingle($selectedGroup);
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||
$resource = new Item($selectedGroup, $transformer, 'transactions');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Events\UpdatedTransactionGroup;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -72,13 +73,6 @@ class UpdateController extends Controller
|
||||
{
|
||||
app('log')->debug('Now in update routine for transaction group');
|
||||
$data = $request->getAll();
|
||||
|
||||
// Fixes 8750.
|
||||
$transactions = $data['transactions'] ?? [];
|
||||
foreach ($transactions as $index => $info) {
|
||||
unset($data['transactions'][$index]['type']);
|
||||
}
|
||||
|
||||
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
||||
$manager = $this->getManager();
|
||||
|
||||
@@ -106,6 +100,11 @@ class UpdateController extends Controller
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$selectedGroup = $enrichment->enrichSingle($selectedGroup);
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -27,8 +27,8 @@ namespace FireflyIII\Api\V1\Controllers\Models\TransactionCurrency;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
|
@@ -42,6 +42,8 @@ use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\AvailableBudgetTransformer;
|
||||
use FireflyIII\Transformers\BillTransformer;
|
||||
@@ -91,7 +93,7 @@ class ListController extends Controller
|
||||
// filter list on currency preference:
|
||||
$collection = $unfiltered->filter(
|
||||
static function (Account $account) use ($currency, $accountRepository) {
|
||||
$currencyId = (int)$accountRepository->getMetaValue($account, 'currency_id');
|
||||
$currencyId = (int) $accountRepository->getMetaValue($account, 'currency_id');
|
||||
|
||||
return $currencyId === $currency->id;
|
||||
}
|
||||
@@ -100,6 +102,14 @@ class ListController extends Controller
|
||||
$count = $collection->count();
|
||||
$accounts = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$accounts = $enrichment->enrich($accounts);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.currencies.accounts', [$currency->code]).$this->buildParams());
|
||||
@@ -167,9 +177,7 @@ class ListController extends Controller
|
||||
|
||||
// filter and paginate list:
|
||||
$collection = $unfiltered->filter(
|
||||
static function (Bill $bill) use ($currency) {
|
||||
return $bill->transaction_currency_id === $currency->id;
|
||||
}
|
||||
static fn (Bill $bill) => $bill->transaction_currency_id === $currency->id
|
||||
);
|
||||
$count = $collection->count();
|
||||
$bills = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
@@ -236,10 +244,10 @@ class ListController extends Controller
|
||||
// get list of budgets. Count it and split it.
|
||||
/** @var RecurringRepositoryInterface $recurringRepos */
|
||||
$recurringRepos = app(RecurringRepositoryInterface::class);
|
||||
$unfiltered = $recurringRepos->getAll();
|
||||
$unfiltered = $recurringRepos->get();
|
||||
|
||||
// filter selection
|
||||
$collection = $unfiltered->filter( // @phpstan-ignore-line
|
||||
$collection = $unfiltered->filter(
|
||||
static function (Recurrence $recurrence) use ($currency) { // @phpstan-ignore-line
|
||||
/** @var RecurrenceTransaction $transaction */
|
||||
foreach ($recurrence->recurrenceTransactions as $transaction) {
|
||||
@@ -286,7 +294,7 @@ class ListController extends Controller
|
||||
$ruleRepos = app(RuleRepositoryInterface::class);
|
||||
$unfiltered = $ruleRepos->getAll();
|
||||
|
||||
$collection = $unfiltered->filter( // @phpstan-ignore-line
|
||||
$collection = $unfiltered->filter(
|
||||
static function (Rule $rule) use ($currency) { // @phpstan-ignore-line
|
||||
/** @var RuleTrigger $trigger */
|
||||
foreach ($rule->ruleTriggers as $trigger) {
|
||||
@@ -360,7 +368,11 @@ class ListController extends Controller
|
||||
}
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.currencies.transactions', [$currency->code]).$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -27,7 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\TransactionCurrency;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\CurrencyTransformer;
|
||||
@@ -105,26 +105,25 @@ class ShowController extends Controller
|
||||
public function show(TransactionCurrency $currency): JsonResponse
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$manager = $this->getManager();
|
||||
$defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($user->userGroup);
|
||||
$this->parameters->set('defaultCurrency', $defaultCurrency);
|
||||
$user = auth()->user();
|
||||
$manager = $this->getManager();
|
||||
$this->parameters->set('nativeCurrency', $this->nativeCurrency);
|
||||
|
||||
// update fields with user info.
|
||||
$currency->refreshForUser($user);
|
||||
|
||||
/** @var CurrencyTransformer $transformer */
|
||||
$transformer = app(CurrencyTransformer::class);
|
||||
$transformer = app(CurrencyTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new Item($currency, $transformer, 'currencies');
|
||||
$resource = new Item($currency, $transformer, 'currencies');
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/getDefaultCurrency
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/getNativeCurrency
|
||||
*
|
||||
* Show a currency.
|
||||
*
|
||||
@@ -135,7 +134,7 @@ class ShowController extends Controller
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$manager = $this->getManager();
|
||||
$currency = app('amount')->getDefaultCurrencyByUserGroup($user->userGroup);
|
||||
$currency = $this->nativeCurrency;
|
||||
|
||||
// update fields with user info.
|
||||
$currency->refreshForUser($user);
|
||||
|
@@ -27,7 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\TransactionCurrency;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\TransactionCurrency\StoreRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\CurrencyTransformer;
|
||||
|
@@ -28,7 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\TransactionCurrency\UpdateRequest;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Transformers\CurrencyTransformer;
|
||||
@@ -100,7 +100,7 @@ class UpdateController extends Controller
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/defaultCurrency
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/nativeCurrency
|
||||
*
|
||||
* Make the currency a default currency.
|
||||
*
|
||||
|
@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Models\LinkType;
|
||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -109,7 +110,11 @@ class ListController extends Controller
|
||||
}
|
||||
$paginator = $collector->getPaginatedGroups();
|
||||
$paginator->setPath(route('api.v1.transactions.index').$this->buildParams());
|
||||
$transactions = $paginator->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$transactions = $enrichment->enrich($paginator->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
71
app/Api/V1/Controllers/Models/UserGroup/IndexController.php
Normal file
71
app/Api/V1/Controllers/Models/UserGroup/IndexController.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* IndexController.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Models\UserGroup;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Data\DateRequest;
|
||||
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
|
||||
use FireflyIII\Transformers\UserGroupTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
|
||||
class IndexController extends Controller
|
||||
{
|
||||
public const string RESOURCE_KEY = 'user_groups';
|
||||
|
||||
private UserGroupRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(UserGroupRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function index(DateRequest $request): JsonResponse
|
||||
{
|
||||
$administrations = $this->repository->get();
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
$count = $administrations->count();
|
||||
$administrations = $administrations->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
$paginator = new LengthAwarePaginator($administrations, $count, $pageSize, $this->parameters->get('page'));
|
||||
$transformer = new UserGroupTransformer();
|
||||
|
||||
$transformer->setParameters($this->parameters); // give params to transformer
|
||||
|
||||
return response()
|
||||
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
|
||||
->header('Content-Type', self::CONTENT_TYPE)
|
||||
;
|
||||
}
|
||||
}
|
64
app/Api/V1/Controllers/Models/UserGroup/ShowController.php
Normal file
64
app/Api/V1/Controllers/Models/UserGroup/ShowController.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* ShowController.php
|
||||
* Copyright (c) 2021 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Models\UserGroup;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
|
||||
use FireflyIII\Transformers\UserGroupTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
* Class ShowController
|
||||
*/
|
||||
class ShowController extends Controller
|
||||
{
|
||||
public const string RESOURCE_KEY = 'user_groups';
|
||||
private WebhookRepositoryInterface $repository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(WebhookRepositoryInterface::class);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function show(UserGroup $userGroup): JsonResponse
|
||||
{
|
||||
$transformer = new UserGroupTransformer();
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
return response()
|
||||
->api($this->jsonApiObject(self::RESOURCE_KEY, $userGroup, $transformer))
|
||||
->header('Content-Type', self::CONTENT_TYPE)
|
||||
;
|
||||
}
|
||||
}
|
71
app/Api/V1/Controllers/Models/UserGroup/UpdateController.php
Normal file
71
app/Api/V1/Controllers/Models/UserGroup/UpdateController.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* UpdateController.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Controllers\Models\UserGroup;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Models\UserGroup\UpdateRequest;
|
||||
use FireflyIII\Models\UserGroup;
|
||||
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
|
||||
use FireflyIII\Transformers\UserGroupTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class UpdateController extends Controller
|
||||
{
|
||||
public const string RESOURCE_KEY = 'user_groups';
|
||||
|
||||
private UserGroupRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* AccountController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(UserGroupRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function update(UpdateRequest $request, UserGroup $userGroup): JsonResponse
|
||||
{
|
||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
||||
$data = $request->getData();
|
||||
$userGroup = $this->repository->update($userGroup, $data);
|
||||
$userGroup->refresh();
|
||||
app('preferences')->mark();
|
||||
|
||||
$transformer = new UserGroupTransformer();
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
return response()
|
||||
->api($this->jsonApiObject(self::RESOURCE_KEY, $userGroup, $transformer))
|
||||
->header('Content-Type', self::CONTENT_TYPE)
|
||||
;
|
||||
}
|
||||
}
|
@@ -26,8 +26,10 @@ namespace FireflyIII\Api\V1\Controllers\Search;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||
use FireflyIII\Support\Search\AccountSearch;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
@@ -62,14 +64,14 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function search(Request $request): JsonResponse|Response
|
||||
{
|
||||
app('log')->debug('Now in account search()');
|
||||
$manager = $this->getManager();
|
||||
$query = trim((string)$request->get('query'));
|
||||
$field = trim((string)$request->get('field'));
|
||||
$query = trim((string) $request->get('query'));
|
||||
$field = trim((string) $request->get('field'));
|
||||
$type = $request->get('type') ?? 'all';
|
||||
if ('' === $query || !in_array($field, $this->validFields, true)) {
|
||||
return response(null, 422);
|
||||
}
|
||||
app('log')->debug(sprintf('Now in account search("%s", "%s")', $field, $query));
|
||||
$types = $this->mapAccountTypes($type);
|
||||
|
||||
/** @var AccountSearch $search */
|
||||
@@ -81,6 +83,14 @@ class AccountController extends Controller
|
||||
|
||||
$accounts = $search->search();
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setUser($admin);
|
||||
$enrichment->setNative($this->nativeCurrency);
|
||||
$accounts = $enrichment->enrich($accounts);
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Search;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
||||
use FireflyIII\Support\Search\SearchInterface;
|
||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -47,8 +48,8 @@ class TransactionController extends Controller
|
||||
public function search(Request $request, SearchInterface $searcher): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
$fullQuery = (string)$request->get('query');
|
||||
$page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page');
|
||||
$fullQuery = (string) $request->get('query');
|
||||
$page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page');
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
$searcher->parseQuery($fullQuery);
|
||||
$searcher->setPage($page);
|
||||
@@ -57,7 +58,11 @@ class TransactionController extends Controller
|
||||
$parameters = ['search' => $fullQuery];
|
||||
$url = route('api.v1.search.transactions').'?'.http_build_query($parameters);
|
||||
$groups->setPath($url);
|
||||
$transactions = $groups->getCollection();
|
||||
|
||||
// enrich
|
||||
$enrichment = new TransactionGroupEnrichment();
|
||||
$enrichment->setUser(auth()->user());
|
||||
$transactions = $enrichment->enrich($groups->getCollection());
|
||||
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -27,19 +27,24 @@ namespace FireflyIII\Api\V1\Controllers\Summary;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Data\DateRequest;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Enums\TransactionTypeEnum;
|
||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
use FireflyIII\Helpers\Report\NetWorthInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
|
||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||
use FireflyIII\Support\Report\Summarizer\TransactionSummarizer;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class BasicController
|
||||
@@ -95,16 +100,15 @@ class BasicController extends Controller
|
||||
$start = $dates['start'];
|
||||
$end = $dates['end'];
|
||||
$code = $request->get('currency_code');
|
||||
|
||||
// balance information:
|
||||
$balanceData = $this->getBalanceInformation($start, $end);
|
||||
$billData = $this->getBillInformation($start, $end);
|
||||
$billData = $this->getSubscriptionInformation($start, $end);
|
||||
$spentData = $this->getLeftToSpendInfo($start, $end);
|
||||
$netWorthData = $this->getNetWorthInfo($start, $end);
|
||||
// $balanceData = [];
|
||||
// $billData = [];
|
||||
// $spentData = [];
|
||||
// $netWorthData = [];
|
||||
$netWorthData = $this->getNetWorthInfo($end);
|
||||
// $balanceData = [];
|
||||
// $billData = [];
|
||||
// $spentData = [];
|
||||
// $netWorthData = [];
|
||||
$total = array_merge($balanceData, $billData, $spentData, $netWorthData);
|
||||
|
||||
// give new keys
|
||||
@@ -120,50 +124,119 @@ class BasicController extends Controller
|
||||
|
||||
private function getBalanceInformation(Carbon $start, Carbon $end): array
|
||||
{
|
||||
Log::debug('getBalanceInformation');
|
||||
// some config settings
|
||||
$convertToNative = Amount::convertToNative();
|
||||
$default = Amount::getNativeCurrency();
|
||||
// prep some arrays:
|
||||
$incomes = [];
|
||||
$expenses = [];
|
||||
$sums = [];
|
||||
$return = [];
|
||||
$incomes = [];
|
||||
$expenses = [];
|
||||
$sums = [];
|
||||
$return = [];
|
||||
$currencies = [
|
||||
$default->id => $default,
|
||||
];
|
||||
|
||||
// collect income of user using the new group collector.
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::DEPOSIT->value]);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$summarizer = new TransactionSummarizer();
|
||||
$set = $collector->setRange($start, $end)->setTypes([TransactionTypeEnum::DEPOSIT->value])->getExtractedJournals();
|
||||
$incomes = $summarizer->groupByCurrencyId($set, 'positive', false);
|
||||
|
||||
$set = $collector->getExtractedJournals();
|
||||
|
||||
/** @var array $transactionJournal */
|
||||
foreach ($set as $transactionJournal) {
|
||||
$currencyId = (int)$transactionJournal['currency_id'];
|
||||
$incomes[$currencyId] ??= '0';
|
||||
$incomes[$currencyId] = bcadd(
|
||||
$incomes[$currencyId],
|
||||
bcmul($transactionJournal['amount'], '-1')
|
||||
);
|
||||
$sums[$currencyId] ??= '0';
|
||||
$sums[$currencyId] = bcadd($sums[$currencyId], bcmul($transactionJournal['amount'], '-1'));
|
||||
}
|
||||
|
||||
// collect expenses of user.
|
||||
// collect expenses of user using the new group collector.
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
|
||||
$set = $collector->getExtractedJournals();
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$set = $collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->getExtractedJournals();
|
||||
$expenses = $summarizer->groupByCurrencyId($set, 'negative', false);
|
||||
|
||||
/** @var array $transactionJournal */
|
||||
foreach ($set as $transactionJournal) {
|
||||
$currencyId = (int)$transactionJournal['currency_id'];
|
||||
$expenses[$currencyId] ??= '0';
|
||||
$expenses[$currencyId] = bcadd($expenses[$currencyId], $transactionJournal['amount']);
|
||||
$sums[$currencyId] ??= '0';
|
||||
$sums[$currencyId] = bcadd($sums[$currencyId], $transactionJournal['amount']);
|
||||
// if convert to native, do so right now.
|
||||
if ($convertToNative) {
|
||||
$newExpenses = [
|
||||
$default->id => [
|
||||
'currency_id' => $default->id,
|
||||
'currency_code' => $default->code,
|
||||
'currency_symbol' => $default->symbol,
|
||||
'currency_decimal_places' => $default->decimal_places,
|
||||
'sum' => '0',
|
||||
],
|
||||
];
|
||||
$newIncomes = [
|
||||
$default->id => [
|
||||
'currency_id' => $default->id,
|
||||
'currency_code' => $default->code,
|
||||
'currency_symbol' => $default->symbol,
|
||||
'currency_decimal_places' => $default->decimal_places,
|
||||
'sum' => '0',
|
||||
],
|
||||
];
|
||||
$sums = [
|
||||
$default->id => [
|
||||
'currency_id' => $default->id,
|
||||
'currency_code' => $default->code,
|
||||
'currency_symbol' => $default->symbol,
|
||||
'currency_decimal_places' => $default->decimal_places,
|
||||
'sum' => '0',
|
||||
],
|
||||
];
|
||||
|
||||
$converter = new ExchangeRateConverter();
|
||||
// loop over income and expenses
|
||||
foreach ([$expenses, $incomes] as $index => $array) {
|
||||
|
||||
// loop over either one.
|
||||
foreach ($array as $entry) {
|
||||
|
||||
// if it is the native currency already.
|
||||
if ($entry['currency_id'] === $default->id) {
|
||||
$sums[$default->id]['sum'] = bcadd((string) $entry['sum'], $sums[$default->id]['sum']);
|
||||
|
||||
// don't forget to add it to newExpenses and newIncome
|
||||
if (0 === $index) {
|
||||
$newExpenses[$default->id]['sum'] = bcadd($newExpenses[$default->id]['sum'], (string) $entry['sum']);
|
||||
}
|
||||
if (1 === $index) {
|
||||
$newIncomes[$default->id]['sum'] = bcadd($newIncomes[$default->id]['sum'], (string) $entry['sum']);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$currencies[$entry['currency_id']] ??= $this->currencyRepos->find($entry['currency_id']);
|
||||
$convertedSum = $converter->convert($currencies[$entry['currency_id']], $default, $start, $entry['sum']);
|
||||
$sums[$default->id]['sum'] = bcadd($sums[$default->id]['sum'], $convertedSum);
|
||||
if (0 === $index) {
|
||||
$newExpenses[$default->id]['sum'] = bcadd($newExpenses[$default->id]['sum'], $convertedSum);
|
||||
}
|
||||
if (1 === $index) {
|
||||
$newIncomes[$default->id]['sum'] = bcadd($newIncomes[$default->id]['sum'], $convertedSum);
|
||||
}
|
||||
}
|
||||
}
|
||||
$incomes = $newIncomes;
|
||||
$expenses = $newExpenses;
|
||||
}
|
||||
if (!$convertToNative) {
|
||||
foreach ([$expenses, $incomes] as $array) {
|
||||
foreach ($array as $entry) {
|
||||
$currencyId = $entry['currency_id'];
|
||||
$sums[$currencyId] ??= [
|
||||
'currency_id' => $entry['currency_id'],
|
||||
'currency_code' => $entry['currency_code'],
|
||||
'currency_symbol' => $entry['currency_symbol'],
|
||||
'currency_decimal_places' => $entry['currency_decimal_places'],
|
||||
'sum' => '0',
|
||||
];
|
||||
$sums[$currencyId]['sum'] = bcadd($sums[$currencyId]['sum'], (string) $entry['sum']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// format amounts:
|
||||
$keys = array_keys($sums);
|
||||
$keys = array_keys($sums);
|
||||
foreach ($keys as $currencyId) {
|
||||
$currency = $this->currencyRepos->find($currencyId);
|
||||
$currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId);
|
||||
if (null === $currency) {
|
||||
continue;
|
||||
}
|
||||
@@ -171,37 +244,78 @@ class BasicController extends Controller
|
||||
$return[] = [
|
||||
'key' => sprintf('balance-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => $sums[$currencyId] ?? '0',
|
||||
'currency_id' => (string)$currency->id,
|
||||
'monetary_value' => $sums[$currencyId]['sum'] ?? '0',
|
||||
'currency_id' => (string) $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),
|
||||
'value_parsed' => app('amount')->formatAnything($currency, $sums[$currencyId]['sum'] ?? '0', false),
|
||||
'local_icon' => 'balance-scale',
|
||||
'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false).
|
||||
' + '.app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false),
|
||||
'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId]['sum'] ?? '0', false)
|
||||
.' + '.app('amount')->formatAnything($currency, $incomes[$currencyId]['sum'] ?? '0', false),
|
||||
];
|
||||
$return[] = [
|
||||
'key' => sprintf('spent-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => $expenses[$currencyId] ?? '0',
|
||||
'currency_id' => (string)$currency->id,
|
||||
'monetary_value' => $expenses[$currencyId]['sum'] ?? '0',
|
||||
'currency_id' => (string) $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),
|
||||
'value_parsed' => app('amount')->formatAnything($currency, $expenses[$currencyId]['sum'] ?? '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' => $incomes[$currencyId] ?? '0',
|
||||
'currency_id' => (string)$currency->id,
|
||||
'monetary_value' => $incomes[$currencyId]['sum'] ?? '0',
|
||||
'currency_id' => (string) $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),
|
||||
'value_parsed' => app('amount')->formatAnything($currency, $incomes[$currencyId]['sum'] ?? '0', false),
|
||||
'local_icon' => 'balance-scale',
|
||||
'sub_title' => '',
|
||||
];
|
||||
}
|
||||
if (0 === count($return)) {
|
||||
$currency = $this->nativeCurrency;
|
||||
// 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' => '0',
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatAnything($currency, '0', false),
|
||||
'local_icon' => 'balance-scale',
|
||||
'sub_title' => app('amount')->formatAnything($currency, '0', false)
|
||||
.' + '.app('amount')->formatAnything($currency, '0', false),
|
||||
];
|
||||
$return[] = [
|
||||
'key' => sprintf('spent-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => '0',
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatAnything($currency, '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' => '0',
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatAnything($currency, '0', false),
|
||||
'local_icon' => 'balance-scale',
|
||||
'sub_title' => '',
|
||||
];
|
||||
@@ -210,15 +324,72 @@ class BasicController extends Controller
|
||||
return $return;
|
||||
}
|
||||
|
||||
private function getBillInformation(Carbon $start, Carbon $end): array
|
||||
private function getSubscriptionInformation(Carbon $start, Carbon $end): array
|
||||
{
|
||||
app('log')->debug(sprintf('Now in getBillInformation("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d-')));
|
||||
Log::debug(sprintf('Now in getBillInformation("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d-')));
|
||||
/*
|
||||
* 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->sumPaidInRange($start, $end);
|
||||
$unpaidAmount = $this->billRepository->sumUnpaidInRange($start, $end);
|
||||
$currencies = [
|
||||
$this->nativeCurrency->id => $this->nativeCurrency,
|
||||
];
|
||||
|
||||
if ($this->convertToNative) {
|
||||
$converter = new ExchangeRateConverter();
|
||||
$newPaidAmount = [[
|
||||
'id' => $this->nativeCurrency->id,
|
||||
'name' => $this->nativeCurrency->name,
|
||||
'symbol' => $this->nativeCurrency->symbol,
|
||||
'code' => $this->nativeCurrency->code,
|
||||
'decimal_places' => $this->nativeCurrency->decimal_places,
|
||||
'sum' => '0',
|
||||
]];
|
||||
|
||||
$newUnpaidAmount = [[
|
||||
'id' => $this->nativeCurrency->id,
|
||||
'name' => $this->nativeCurrency->name,
|
||||
'symbol' => $this->nativeCurrency->symbol,
|
||||
'code' => $this->nativeCurrency->code,
|
||||
'decimal_places' => $this->nativeCurrency->decimal_places,
|
||||
'sum' => '0',
|
||||
]];
|
||||
foreach ([$paidAmount, $unpaidAmount] as $index => $array) {
|
||||
foreach ($array as $item) {
|
||||
$currencyId = (int) $item['id'];
|
||||
if (0 === $index) {
|
||||
// paid amount
|
||||
if ($currencyId === $this->nativeCurrency->id) {
|
||||
$newPaidAmount[0]['sum'] = bcadd($newPaidAmount[0]['sum'], (string) $item['sum']);
|
||||
|
||||
continue;
|
||||
}
|
||||
$currencies[$currencyId] ??= $this->currencyRepos->find($currencyId);
|
||||
$convertedAmount = $converter->convert($currencies[$currencyId], $this->nativeCurrency, $start, $item['sum']);
|
||||
$newPaidAmount[0]['sum'] = bcadd($newPaidAmount[0]['sum'], $convertedAmount);
|
||||
|
||||
continue;
|
||||
}
|
||||
// unpaid amount
|
||||
if ($currencyId === $this->nativeCurrency->id) {
|
||||
$newUnpaidAmount[0]['sum'] = bcadd($newUnpaidAmount[0]['sum'], (string) $item['sum']);
|
||||
|
||||
continue;
|
||||
}
|
||||
$currencies[$currencyId] ??= $this->currencyRepos->find($currencyId);
|
||||
$convertedAmount = $converter->convert($currencies[$currencyId], $this->nativeCurrency, $start, $item['sum']);
|
||||
$newUnpaidAmount[0]['sum'] = bcadd($newUnpaidAmount[0]['sum'], $convertedAmount);
|
||||
}
|
||||
}
|
||||
$paidAmount = $newPaidAmount;
|
||||
$unpaidAmount = $newUnpaidAmount;
|
||||
}
|
||||
|
||||
// var_dump($paidAmount);
|
||||
// var_dump($unpaidAmount);
|
||||
// exit;
|
||||
|
||||
$return = [];
|
||||
|
||||
@@ -226,12 +397,12 @@ class BasicController extends Controller
|
||||
* @var array $info
|
||||
*/
|
||||
foreach ($paidAmount as $info) {
|
||||
$amount = bcmul($info['sum'], '-1');
|
||||
$amount = bcmul((string) $info['sum'], '-1');
|
||||
$return[] = [
|
||||
'key' => sprintf('bills-paid-in-%s', $info['code']),
|
||||
'title' => trans('firefly.box_bill_paid_in_currency', ['currency' => $info['symbol']]),
|
||||
'monetary_value' => $amount,
|
||||
'currency_id' => (string)$info['id'],
|
||||
'currency_id' => (string) $info['id'],
|
||||
'currency_code' => $info['code'],
|
||||
'currency_symbol' => $info['symbol'],
|
||||
'currency_decimal_places' => $info['decimal_places'],
|
||||
@@ -245,12 +416,12 @@ class BasicController extends Controller
|
||||
* @var array $info
|
||||
*/
|
||||
foreach ($unpaidAmount as $info) {
|
||||
$amount = bcmul($info['sum'], '-1');
|
||||
$amount = bcmul((string) $info['sum'], '-1');
|
||||
$return[] = [
|
||||
'key' => sprintf('bills-unpaid-in-%s', $info['code']),
|
||||
'title' => trans('firefly.box_bill_unpaid_in_currency', ['currency' => $info['symbol']]),
|
||||
'monetary_value' => $amount,
|
||||
'currency_id' => (string)$info['id'],
|
||||
'currency_id' => (string) $info['id'],
|
||||
'currency_code' => $info['code'],
|
||||
'currency_symbol' => $info['symbol'],
|
||||
'currency_decimal_places' => $info['decimal_places'],
|
||||
@@ -259,7 +430,38 @@ class BasicController extends Controller
|
||||
'sub_title' => '',
|
||||
];
|
||||
}
|
||||
app('log')->debug(sprintf('Done with getBillInformation("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d-')));
|
||||
Log::debug(sprintf('Done with getBillInformation("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d-')));
|
||||
|
||||
if (0 === count($return)) {
|
||||
$currency = $this->nativeCurrency;
|
||||
unset($info, $amount);
|
||||
|
||||
$return[] = [
|
||||
'key' => sprintf('bills-paid-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_bill_paid_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => '0',
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatFlat($currency->symbol, $currency->decimal_places, '0', false),
|
||||
'local_icon' => 'check',
|
||||
'sub_title' => '',
|
||||
];
|
||||
$return[] = [
|
||||
'key' => sprintf('bills-unpaid-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_bill_unpaid_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => '0',
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatFlat($currency->symbol, $currency->decimal_places, '0', false),
|
||||
'local_icon' => 'calendar-o',
|
||||
'sub_title' => '',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
return $return;
|
||||
}
|
||||
@@ -269,29 +471,62 @@ class BasicController extends Controller
|
||||
*/
|
||||
private function getLeftToSpendInfo(Carbon $start, Carbon $end): array
|
||||
{
|
||||
$return = [];
|
||||
$today = today(config('app.timezone'));
|
||||
$available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end);
|
||||
$budgets = $this->budgetRepository->getActiveBudgets();
|
||||
$spent = $this->opsRepository->sumExpenses($start, $end, null, $budgets);
|
||||
|
||||
Log::debug(sprintf('Now in getLeftToSpendInfo("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||
$return = [];
|
||||
$today = today(config('app.timezone'));
|
||||
$available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end);
|
||||
$budgets = $this->budgetRepository->getActiveBudgets();
|
||||
$spent = $this->opsRepository->sumExpenses($start, $end, null, $budgets);
|
||||
$days = (int) $today->diffInDays($end, true) + 1;
|
||||
$currencies = [];
|
||||
|
||||
// first, create an entry for each entry in the "available" array.
|
||||
/** @var array $availableBudget */
|
||||
foreach ($available as $currencyId => $availableBudget) {
|
||||
$currencies[$currencyId] ??= $this->currencyRepos->find($currencyId);
|
||||
$return[$currencyId] = [
|
||||
'key' => sprintf('left-to-spend-in-%s', $currencies[$currencyId]->code),
|
||||
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $currencies[$currencyId]->symbol]),
|
||||
'no_available_budgets' => false,
|
||||
'monetary_value' => $availableBudget,
|
||||
'currency_id' => (string) $currencies[$currencyId]->id,
|
||||
'currency_code' => $currencies[$currencyId]->code,
|
||||
'currency_symbol' => $currencies[$currencyId]->symbol,
|
||||
'currency_decimal_places' => $currencies[$currencyId]->decimal_places,
|
||||
'value_parsed' => app('amount')->formatFlat($currencies[$currencyId]->symbol, $currencies[$currencyId]->decimal_places, $availableBudget, false),
|
||||
'local_icon' => 'money',
|
||||
'sub_title' => app('amount')->formatFlat(
|
||||
$currencies[$currencyId]->symbol,
|
||||
$currencies[$currencyId]->decimal_places,
|
||||
$availableBudget,
|
||||
false
|
||||
),
|
||||
];
|
||||
}
|
||||
foreach ($spent as $row) {
|
||||
// either an amount was budgeted or 0 is available.
|
||||
$amount = (string)($available[$row['currency_id']] ?? '0');
|
||||
$spentInCurrency = $row['sum'];
|
||||
$leftToSpend = bcadd($amount, $spentInCurrency);
|
||||
|
||||
$days = (int)$today->diffInDays($end, true) + 1;
|
||||
$perDay = '0';
|
||||
$currencyId = (int) $row['currency_id'];
|
||||
$amount = (string) ($available[$currencyId] ?? '0');
|
||||
if (0 === bccomp($amount, '0')) {
|
||||
// #9858 skip over currencies with no available budget.
|
||||
continue;
|
||||
}
|
||||
$spentInCurrency = $row['sum'];
|
||||
$leftToSpend = bcadd($amount, (string) $spentInCurrency);
|
||||
$perDay = '0';
|
||||
if (0 !== $days && bccomp($leftToSpend, '0') > -1) {
|
||||
$perDay = bcdiv($leftToSpend, (string)$days);
|
||||
$perDay = bcdiv($leftToSpend, (string) $days);
|
||||
}
|
||||
|
||||
$return[] = [
|
||||
Log::debug(sprintf('Spent %s %s', $row['currency_code'], $row['sum']));
|
||||
|
||||
$return[$currencyId] = [
|
||||
'key' => sprintf('left-to-spend-in-%s', $row['currency_code']),
|
||||
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $row['currency_symbol']]),
|
||||
'no_available_budgets' => false,
|
||||
'monetary_value' => $leftToSpend,
|
||||
'currency_id' => (string)$row['currency_id'],
|
||||
'currency_id' => (string) $row['currency_id'],
|
||||
'currency_code' => $row['currency_code'],
|
||||
'currency_symbol' => $row['currency_symbol'],
|
||||
'currency_decimal_places' => $row['currency_decimal_places'],
|
||||
@@ -305,27 +540,80 @@ class BasicController extends Controller
|
||||
),
|
||||
];
|
||||
}
|
||||
unset($leftToSpend);
|
||||
if (0 === count($return)) {
|
||||
// a small trick to get every expense in this period, regardless of budget.
|
||||
$spent = $this->opsRepository->sumExpenses($start, $end, null, new Collection());
|
||||
foreach ($spent as $row) {
|
||||
// either an amount was budgeted or 0 is available.
|
||||
$currencyId = (int) $row['currency_id'];
|
||||
$spentInCurrency = $row['sum'];
|
||||
$perDay = '0';
|
||||
if (0 !== $days && -1 === bccomp((string) $spentInCurrency, '0')) {
|
||||
$perDay = bcdiv((string) $spentInCurrency, (string) $days);
|
||||
}
|
||||
|
||||
return $return;
|
||||
Log::debug(sprintf('Spent %s %s', $row['currency_code'], $row['sum']));
|
||||
|
||||
$return[$currencyId] = [
|
||||
'key' => sprintf('left-to-spend-in-%s', $row['currency_code']),
|
||||
'title' => trans('firefly.spent'),
|
||||
'no_available_budgets' => true,
|
||||
'monetary_value' => $spentInCurrency,
|
||||
'currency_id' => (string) $row['currency_id'],
|
||||
'currency_code' => $row['currency_code'],
|
||||
'currency_symbol' => $row['currency_symbol'],
|
||||
'currency_decimal_places' => $row['currency_decimal_places'],
|
||||
'value_parsed' => app('amount')->formatFlat($row['currency_symbol'], $row['currency_decimal_places'], $spentInCurrency, false),
|
||||
'local_icon' => 'money',
|
||||
'sub_title' => app('amount')->formatFlat(
|
||||
$row['currency_symbol'],
|
||||
$row['currency_decimal_places'],
|
||||
$perDay,
|
||||
false
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
// $amount = '0';
|
||||
// // $days
|
||||
// // fill in by money spent, just count it.
|
||||
// $currency = $this->nativeCurrency;
|
||||
// $return[$currency->id] = [
|
||||
// 'key' => sprintf('left-to-spend-in-%s', $currency->code),
|
||||
// 'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $currency->symbol]),
|
||||
// 'monetary_value' => '0',
|
||||
// 'no_available_budgets' => true,
|
||||
// 'currency_id' => (string) $currency->id,
|
||||
// 'currency_code' => $currency->code,
|
||||
// 'currency_symbol' => $currency->symbol,
|
||||
// 'currency_decimal_places' => $currency->decimal_places,
|
||||
// 'value_parsed' => app('amount')->formatFlat($currency->symbol, $currency->decimal_places, '0', false),
|
||||
// 'local_icon' => 'money',
|
||||
// 'sub_title' => app('amount')->formatFlat(
|
||||
// $currency->symbol,
|
||||
// $currency->decimal_places,
|
||||
// '0',
|
||||
// false
|
||||
// ),
|
||||
// ];
|
||||
}
|
||||
|
||||
return array_values($return);
|
||||
}
|
||||
|
||||
private function getNetWorthInfo(Carbon $start, Carbon $end): array
|
||||
private function getNetWorthInfo(Carbon $end): array
|
||||
{
|
||||
$end->endOfDay();
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$date = today(config('app.timezone'))->startOfDay();
|
||||
// start and end in the future? use $end
|
||||
if ($this->notInDateRange($date, $start, $end)) {
|
||||
/** @var Carbon $date */
|
||||
$date = session('end', today(config('app.timezone'))->endOfMonth());
|
||||
}
|
||||
Log::debug(sprintf('getNetWorthInfo up until "%s".', $end->format('Y-m-d H:i:s')));
|
||||
|
||||
/** @var NetWorthInterface $netWorthHelper */
|
||||
$netWorthHelper = app(NetWorthInterface::class);
|
||||
$netWorthHelper->setUser($user);
|
||||
$allAccounts = $this->accountRepository->getActiveAccountsByType(
|
||||
[AccountType::ASSET, AccountType::DEFAULT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::DEBT]
|
||||
);
|
||||
$allAccounts = $this->accountRepository->getActiveAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value]);
|
||||
|
||||
// filter list on preference of being included.
|
||||
$filtered = $allAccounts->filter(
|
||||
@@ -336,14 +624,14 @@ class BasicController extends Controller
|
||||
}
|
||||
);
|
||||
|
||||
$netWorthSet = $netWorthHelper->byAccounts($filtered, $date);
|
||||
$netWorthSet = $netWorthHelper->byAccounts($filtered, $end);
|
||||
$return = [];
|
||||
foreach ($netWorthSet as $key => $data) {
|
||||
if ('native' === $key) {
|
||||
continue;
|
||||
}
|
||||
$amount = $data['balance'];
|
||||
if (0 === bccomp($amount, '0')) {
|
||||
if (0 === bccomp((string) $amount, '0')) {
|
||||
continue;
|
||||
}
|
||||
// return stuff
|
||||
@@ -351,7 +639,7 @@ class BasicController extends Controller
|
||||
'key' => sprintf('net-worth-in-%s', $data['currency_code']),
|
||||
'title' => trans('firefly.box_net_worth_in_currency', ['currency' => $data['currency_symbol']]),
|
||||
'monetary_value' => $amount,
|
||||
'currency_id' => (string)$data['currency_id'],
|
||||
'currency_id' => (string) $data['currency_id'],
|
||||
'currency_code' => $data['currency_code'],
|
||||
'currency_symbol' => $data['currency_symbol'],
|
||||
'currency_decimal_places' => $data['currency_decimal_places'],
|
||||
@@ -360,6 +648,23 @@ class BasicController extends Controller
|
||||
'sub_title' => '',
|
||||
];
|
||||
}
|
||||
if (0 === count($return)) {
|
||||
$return[] = [
|
||||
'key' => sprintf('net-worth-in-%s', $this->nativeCurrency->code),
|
||||
'title' => trans('firefly.box_net_worth_in_currency', ['currency' => $this->nativeCurrency->symbol]),
|
||||
'monetary_value' => '0',
|
||||
'currency_id' => (string) $this->nativeCurrency->id,
|
||||
'currency_code' => $this->nativeCurrency->code,
|
||||
'currency_symbol' => $this->nativeCurrency->symbol,
|
||||
'currency_decimal_places' => $this->nativeCurrency->decimal_places,
|
||||
'value_parsed' => app('amount')->formatFlat($this->nativeCurrency->symbol, $this->nativeCurrency->decimal_places, '0', false),
|
||||
'local_icon' => 'line-chart',
|
||||
'sub_title' => '',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
Log::debug('End of getNetWorthInfo');
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\System;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Transformers\UserTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use League\Fractal\Resource\Item;
|
||||
|
||||
/**
|
||||
@@ -48,7 +49,7 @@ class AboutController extends Controller
|
||||
$replace = ['\~', '# '];
|
||||
$phpVersion = str_replace($search, $replace, PHP_VERSION);
|
||||
$phpOs = str_replace($search, $replace, PHP_OS);
|
||||
$currentDriver = \DB::getDriverName();
|
||||
$currentDriver = DB::getDriverName();
|
||||
$data
|
||||
= [
|
||||
'version' => config('firefly.version'),
|
||||
@@ -58,7 +59,7 @@ class AboutController extends Controller
|
||||
'driver' => $currentDriver,
|
||||
];
|
||||
|
||||
return response()->api(['data' => $data])->header('Content-Type', self::CONTENT_TYPE);
|
||||
return response()->api(['data' => $data])->header('Content-Type', self::JSON_CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -86,7 +86,7 @@ class ConfigurationController extends Controller
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($return);
|
||||
return response()->api($return);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,8 +101,8 @@ class ConfigurationController extends Controller
|
||||
|
||||
return [
|
||||
'is_demo_site' => $isDemoSite?->data,
|
||||
'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data,
|
||||
'last_update_check' => null === $lastCheck ? null : (int)$lastCheck->data,
|
||||
'permission_update_check' => null === $updateCheck ? null : (int) $updateCheck->data,
|
||||
'last_update_check' => null === $lastCheck ? null : (int) $lastCheck->data,
|
||||
'single_user_mode' => $singleUser?->data,
|
||||
];
|
||||
}
|
||||
@@ -142,7 +142,7 @@ class ConfigurationController extends Controller
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json(['data' => $data])->header('Content-Type', self::CONTENT_TYPE);
|
||||
return response()->api(['data' => $data])->header('Content-Type', self::JSON_CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,6 +173,6 @@ class ConfigurationController extends Controller
|
||||
'editable' => true,
|
||||
];
|
||||
|
||||
return response()->json(['data' => $data])->header('Content-Type', self::CONTENT_TYPE);
|
||||
return response()->api(['data' => $data])->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
}
|
||||
|
@@ -52,8 +52,8 @@ class CronController extends Controller
|
||||
if (true === config('cer.download_enabled')) {
|
||||
$return['exchange_rates'] = $this->exchangeRatesCronJob($config['force'], $config['date']);
|
||||
}
|
||||
$return['bill_warnings'] = $this->billWarningCronJob($config['force'], $config['date']);
|
||||
$return['bill_notifications'] = $this->billWarningCronJob($config['force'], $config['date']);
|
||||
|
||||
return response()->json($return);
|
||||
return response()->api($return);
|
||||
}
|
||||
}
|
||||
|
@@ -32,7 +32,6 @@ use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Transformers\PreferenceTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
@@ -86,7 +85,7 @@ class PreferencesController extends Controller
|
||||
$manager = $this->getManager();
|
||||
|
||||
if ('currencyPreference' === $preference->name) {
|
||||
throw new FireflyException('Please use api/v1/currencies/default instead.');
|
||||
throw new FireflyException('Please use api/v1/currencies/native instead.');
|
||||
}
|
||||
|
||||
/** @var PreferenceTransformer $transformer */
|
||||
@@ -98,34 +97,6 @@ class PreferencesController extends Controller
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO This endpoint is not documented.
|
||||
*
|
||||
* Return a single preference by name.
|
||||
*
|
||||
* @param Collection<int, Preference> $collection
|
||||
*/
|
||||
public function showList(Collection $collection): JsonResponse
|
||||
{
|
||||
$manager = $this->getManager();
|
||||
$count = $collection->count();
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
$preferences = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($preferences, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.preferences.show-list').$this->buildParams());
|
||||
|
||||
/** @var PreferenceTransformer $transformer */
|
||||
$transformer = app(PreferenceTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($preferences, $transformer, self::RESOURCE_KEY);
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/preferences/storePreference
|
||||
@@ -161,7 +132,7 @@ class PreferencesController extends Controller
|
||||
public function update(PreferenceUpdateRequest $request, Preference $preference): JsonResponse
|
||||
{
|
||||
if ('currencyPreference' === $preference->name) {
|
||||
throw new FireflyException('Please use api/v1/currencies/default instead.');
|
||||
throw new FireflyException('Please use api/v1/currencies/native instead.');
|
||||
}
|
||||
|
||||
$manager = $this->getManager();
|
||||
|
@@ -24,7 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Autocomplete;
|
||||
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
@@ -46,7 +46,7 @@ class AutocompleteRequest extends FormRequest
|
||||
}
|
||||
|
||||
// remove 'initial balance' from allowed types. its internal
|
||||
$array = array_diff($array, [AccountType::INITIAL_BALANCE, AccountType::RECONCILIATION]);
|
||||
$array = array_diff($array, [AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::RECONCILIATION->value]);
|
||||
|
||||
return [
|
||||
'types' => $array,
|
||||
@@ -58,6 +58,7 @@ class AutocompleteRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'date' => 'date|after:1900-01-01|before:2099-12-31',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
91
app/Api/V1/Requests/Chart/ChartRequest.php
Normal file
91
app/Api/V1/Requests/Chart/ChartRequest.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* DashboardChartRequest.php
|
||||
* Copyright (c) 2023 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Chart;
|
||||
|
||||
use FireflyIII\Enums\UserRoleEnum;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
* Class ChartRequest
|
||||
*/
|
||||
class ChartRequest extends FormRequest
|
||||
{
|
||||
use ChecksLogin;
|
||||
use ConvertsDataTypes;
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||
|
||||
public function getParameters(): array
|
||||
{
|
||||
return [
|
||||
'start' => $this->convertDateTime('start')?->startOfDay(),
|
||||
'end' => $this->convertDateTime('end')?->endOfDay(),
|
||||
'preselected' => $this->convertString('preselected', 'empty'),
|
||||
'period' => $this->convertString('period', '1M'),
|
||||
'accounts' => $this->arrayFromValue($this->get('accounts')),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'start' => 'required|date|after:1900-01-01|before:2099-12-31|before_or_equal:end',
|
||||
'end' => 'required|date|after:1900-01-01|before:2099-12-31|after_or_equal:start',
|
||||
'preselected' => sprintf('nullable|in:%s', implode(',', config('firefly.preselected_accounts'))),
|
||||
'period' => sprintf('nullable|in:%s', implode(',', config('firefly.valid_view_ranges'))),
|
||||
'accounts.*' => 'exists:accounts,id',
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
static function (Validator $validator): void {
|
||||
// validate transaction query data.
|
||||
$data = $validator->getData();
|
||||
if (!array_key_exists('accounts', $data)) {
|
||||
// $validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts']));
|
||||
return;
|
||||
}
|
||||
if (!is_array($data['accounts'])) {
|
||||
$validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts']));
|
||||
}
|
||||
}
|
||||
);
|
||||
if ($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
@@ -74,7 +74,7 @@ class MoveTransactionsRequest extends FormRequest
|
||||
}
|
||||
);
|
||||
if ($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,12 +83,12 @@ class MoveTransactionsRequest extends FormRequest
|
||||
$data = $validator->getData();
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$original = $repository->find((int)$data['original_account']);
|
||||
$destination = $repository->find((int)$data['destination_account']);
|
||||
$original = $repository->find((int) $data['original_account']);
|
||||
$destination = $repository->find((int) $data['destination_account']);
|
||||
|
||||
// not the same type:
|
||||
if ($original->accountType->type !== $destination->accountType->type) {
|
||||
$validator->errors()->add('title', (string)trans('validation.same_account_type'));
|
||||
$validator->errors()->add('title', (string) trans('validation.same_account_type'));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -98,7 +98,7 @@ class MoveTransactionsRequest extends FormRequest
|
||||
|
||||
// check different scenario's.
|
||||
if (null === $originalCurrency xor null === $destinationCurrency) {
|
||||
$validator->errors()->add('title', (string)trans('validation.same_account_currency'));
|
||||
$validator->errors()->add('title', (string) trans('validation.same_account_currency'));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -107,7 +107,7 @@ class MoveTransactionsRequest extends FormRequest
|
||||
return;
|
||||
}
|
||||
if ($originalCurrency->code !== $destinationCurrency->code) {
|
||||
$validator->errors()->add('title', (string)trans('validation.same_account_currency'));
|
||||
$validator->errors()->add('title', (string) trans('validation.same_account_currency'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -33,6 +33,8 @@ use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
use function Safe\json_decode;
|
||||
|
||||
/**
|
||||
* Class TransactionRequest
|
||||
*/
|
||||
@@ -74,7 +76,7 @@ class TransactionRequest extends FormRequest
|
||||
}
|
||||
);
|
||||
if ($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Data;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Exceptions\ValidationException;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
@@ -49,12 +49,13 @@ class DateRequest extends FormRequest
|
||||
$start->startOfDay();
|
||||
$end->endOfDay();
|
||||
if ($start->diffInYears($end, true) > 5) {
|
||||
throw new FireflyException('Date range out of range.');
|
||||
throw new ValidationException('Date range out of range.');
|
||||
}
|
||||
|
||||
return [
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'date' => $this->getCarbonDate('date'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -64,8 +65,9 @@ class DateRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'start' => 'required|date',
|
||||
'end' => 'required|date|after:start',
|
||||
'date' => 'date|after:1900-01-01|before:2099-12-31',
|
||||
'start' => 'date|after:1900-01-01|before:2099-12-31|before:end|required_with:end',
|
||||
'end' => 'date|after:1900-01-01|before:2099-12-31|after:start|required_with:start',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -49,9 +49,9 @@ class DestroyRequest extends FormRequest
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$valid = 'budgets,bills,piggy_banks,rules,recurring,categories,tags,object_groups'.
|
||||
',accounts,asset_accounts,expense_accounts,revenue_accounts,liabilities,transactions,withdrawals,deposits,transfers'.
|
||||
',not_assets_liabilities';
|
||||
$valid = 'budgets,bills,piggy_banks,rules,recurring,categories,tags,object_groups'
|
||||
.',accounts,asset_accounts,expense_accounts,revenue_accounts,liabilities,transactions,withdrawals,deposits,transfers'
|
||||
.',not_assets_liabilities';
|
||||
|
||||
return [
|
||||
'objects' => sprintf('required|max:255|min:1|string|in:%s', $valid),
|
||||
|
@@ -24,7 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Data\Export;
|
||||
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
@@ -52,10 +52,10 @@ class ExportRequest extends FormRequest
|
||||
|
||||
$accounts = new Collection();
|
||||
foreach ($parts as $part) {
|
||||
$accountId = (int)$part;
|
||||
$accountId = (int) $part;
|
||||
if (0 !== $accountId) {
|
||||
$account = $repository->find($accountId);
|
||||
if (null !== $account && AccountType::ASSET === $account->accountType->type) {
|
||||
if (null !== $account && AccountTypeEnum::ASSET->value === $account->accountType->type) {
|
||||
$accounts->push($account);
|
||||
}
|
||||
}
|
||||
|
62
app/Api/V1/Requests/Generic/DateRequest.php
Normal file
62
app/Api/V1/Requests/Generic/DateRequest.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* DateRequest.php
|
||||
* Copyright (c) 2021 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Generic;
|
||||
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
/**
|
||||
* Request class for end points that require date parameters.
|
||||
*
|
||||
* Class DateRequest
|
||||
*/
|
||||
class DateRequest extends FormRequest
|
||||
{
|
||||
use ChecksLogin;
|
||||
use ConvertsDataTypes;
|
||||
|
||||
/**
|
||||
* Get all data from the request.
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
return [
|
||||
'start' => $this->getCarbonDate('start')->startOfDay(),
|
||||
'end' => $this->getCarbonDate('end')->endOfDay(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'start' => 'required|date|after:1900-01-01|before:2099-12-31',
|
||||
'end' => 'required|date|after_or_equal:start|before:2099-12-31|after:1900-01-01',
|
||||
];
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user