mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-08-16 10:54:39 +00:00
Compare commits
422 Commits
develop-20
...
develop-20
Author | SHA1 | Date | |
---|---|---|---|
|
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 | ||
|
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 | ||
|
76cc27a267 | ||
|
e8a6f30e4e | ||
|
2d10f255c2 | ||
|
ee76cc6761 | ||
|
d4e4907363 | ||
|
c205e93876 | ||
|
3b24bb99bb | ||
|
2814cd1b2a | ||
|
5285e1ac14 | ||
|
48a999cf91 | ||
|
6bb297e76f | ||
|
bc698f67ea | ||
|
2d0aa207d4 | ||
|
4a75e9c262 | ||
|
ee7c4b8863 | ||
|
53cce6510c | ||
|
8f3cf38f77 | ||
|
f33766a062 | ||
|
ac5e62c65d | ||
|
e2289ce1e6 | ||
|
28d7e24d30 | ||
|
6a62f781e9 | ||
|
fb6c67fa04 | ||
|
03e9e3dbdb | ||
|
5520992861 | ||
|
5f1502eea7 | ||
|
b3560ff525 | ||
|
8030167ffc | ||
|
fd2c1615cf | ||
|
b976239580 | ||
|
7d8d773f8f | ||
|
b930ad4da7 | ||
|
abad7cdf16 | ||
|
0e5eb036b0 | ||
|
d995bfc081 | ||
|
c920070ce2 | ||
|
c35ff3174a | ||
|
94085ee940 | ||
|
c841fa3620 | ||
|
2f7a1c941e | ||
|
c06fb8daf6 | ||
|
26948a058a | ||
|
1220564f30 | ||
|
ea4be9dd0c | ||
|
4819b5ac5d | ||
|
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'],
|
||||
|
116
.ci/php-cs-fixer/composer.lock
generated
116
.ci/php-cs-fixer/composer.lock
generated
@@ -406,16 +406,16 @@
|
||||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v3.65.0",
|
||||
"version": "v3.68.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||
"reference": "79d4f3e77b250a7d8043d76c6af8f0695e8a469f"
|
||||
"reference": "7bedb718b633355272428c60736dc97fb96daf27"
|
||||
},
|
||||
"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/7bedb718b633355272428c60736dc97fb96daf27",
|
||||
"reference": "7bedb718b633355272428c60736dc97fb96daf27",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -432,17 +432,17 @@
|
||||
"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",
|
||||
"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",
|
||||
@@ -454,9 +454,9 @@
|
||||
"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"
|
||||
"phpunit/phpunit": "^9.6.22 || ^10.5.40 || ^11.5.2",
|
||||
"symfony/var-dumper": "^5.4.48 || ^6.4.15 || ^7.2.0",
|
||||
"symfony/yaml": "^5.4.45 || ^6.4.13 || ^7.2.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "For handling output formats in XML",
|
||||
@@ -497,7 +497,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.68.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -505,7 +505,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-25T00:39:24+00:00"
|
||||
"time": "2025-01-30T17:00:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
@@ -734,33 +734,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 +797,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",
|
||||
@@ -1369,12 +1365,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": {
|
||||
@@ -1517,12 +1513,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": {
|
||||
@@ -1641,16 +1637,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v7.2.0",
|
||||
"version": "v7.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49"
|
||||
"reference": "87a71856f2f56e4100373e92529eed3171695cfb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/6de263e5868b9a137602dd1e33e4d48bfae99c49",
|
||||
"reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb",
|
||||
"reference": "87a71856f2f56e4100373e92529eed3171695cfb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1685,7 +1681,7 @@
|
||||
"description": "Finds files and directories via an intuitive fluent interface",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/finder/tree/v7.2.0"
|
||||
"source": "https://github.com/symfony/finder/tree/v7.2.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1701,7 +1697,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-10-23T06:56:12+00:00"
|
||||
"time": "2024-12-30T19:00:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
@@ -2329,12 +2325,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 +2386,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/stopwatch",
|
||||
"version": "v7.2.0",
|
||||
"version": "v7.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/stopwatch.git",
|
||||
"reference": "696f418b0d722a4225e1c3d95489d262971ca924"
|
||||
"reference": "e46690d5b9d7164a6d061cab1e8d46141b9f49df"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/696f418b0d722a4225e1c3d95489d262971ca924",
|
||||
"reference": "696f418b0d722a4225e1c3d95489d262971ca924",
|
||||
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/e46690d5b9d7164a6d061cab1e8d46141b9f49df",
|
||||
"reference": "e46690d5b9d7164a6d061cab1e8d46141b9f49df",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2432,7 +2428,7 @@
|
||||
"description": "Provides a way to profile code",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/stopwatch/tree/v7.2.0"
|
||||
"source": "https://github.com/symfony/stopwatch/tree/v7.2.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2448,7 +2444,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-25T14:21:43+00:00"
|
||||
"time": "2024-12-18T14:28:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
|
@@ -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.
|
||||
|
@@ -325,6 +325,12 @@ USE_RUNNING_BALANCE=false
|
||||
#
|
||||
FIREFLY_III_LAYOUT=v1
|
||||
|
||||
#
|
||||
# Which Query Parser implementation to use for the search rngine 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`
|
||||
|
||||
|
53
.github/mergify.yml
vendored
53
.github/mergify.yml
vendored
@@ -8,56 +8,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/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`
|
||||
|
86
.github/workflows/release.yml
vendored
86
.github/workflows/release.yml
vendored
@@ -10,7 +10,7 @@ on:
|
||||
phpversion:
|
||||
description: 'PHP version'
|
||||
required: true
|
||||
default: '8.3'
|
||||
default: '8.4'
|
||||
schedule:
|
||||
- cron: '0 3 * * MON'
|
||||
|
||||
@@ -58,15 +58,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
|
||||
@@ -168,7 +159,7 @@ jobs:
|
||||
|
||||
# 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
|
||||
@@ -177,7 +168,7 @@ jobs:
|
||||
|
||||
# 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;
|
||||
#[[ -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
|
||||
@@ -229,7 +220,7 @@ jobs:
|
||||
# describe the development release.
|
||||
if [[ "develop" == "$version" ]]; then
|
||||
echo 'Develop release.'
|
||||
rm output.txt
|
||||
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
|
||||
@@ -244,7 +235,7 @@ jobs:
|
||||
# describe a branch release
|
||||
if [[ "$version" == branch* ]]; then
|
||||
echo 'Branch release.'
|
||||
rm output.txt
|
||||
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
|
||||
@@ -257,9 +248,45 @@ jobs:
|
||||
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* ]]; then
|
||||
sudo chown -R runner:docker output.txt
|
||||
if [[ "develop" != "$version" ]] && [[ "$version" != branch* ]] && [[ "$version" != *alpha* ]] && [[ "$version" != *beta* ]]; then
|
||||
echo 'Main release.'
|
||||
sudo chown -R runner:docker 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 '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')** 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 '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')** 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
|
||||
@@ -278,6 +305,7 @@ jobs:
|
||||
git push origin $releaseName
|
||||
gh release create $releaseName -p --verify-tag \
|
||||
-t "Development release for $(date +'%Y-%m-%d')" \
|
||||
--latest=false \
|
||||
-F output.txt
|
||||
fi
|
||||
|
||||
@@ -291,6 +319,7 @@ jobs:
|
||||
git push origin $releaseName
|
||||
gh release create $releaseName -p --verify-tag \
|
||||
-t "Branch release for $(date +'%Y-%m-%d')" \
|
||||
--latest=false \
|
||||
-F output.txt
|
||||
fi
|
||||
|
||||
@@ -316,7 +345,18 @@ jobs:
|
||||
echo 'MAIN (real) release'
|
||||
git tag -a $releaseName -m "Here be changelog"
|
||||
git push origin $releaseName
|
||||
gh release create $releaseName -F output.txt -t "$releaseName" --verify-tag
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
||||
fi
|
||||
|
||||
# add archive files to release
|
||||
gh release upload $releaseName $zipName
|
||||
@@ -336,12 +376,12 @@ jobs:
|
||||
gh release upload $releaseName HEAD.txt
|
||||
|
||||
# remove all temporary files
|
||||
rm output.txt
|
||||
rm HEAD.txt
|
||||
rm $zipName
|
||||
rm $zipName.sha256
|
||||
rm $tarName
|
||||
rm $tarName.sha256
|
||||
rm -f output.txt
|
||||
rm -f HEAD.txt
|
||||
rm -f $zipName
|
||||
rm -f $zipName.sha256
|
||||
rm -f $tarName
|
||||
rm -f $tarName.sha256
|
||||
|
||||
# merge main back into develop
|
||||
git checkout develop
|
||||
|
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
|
||||
|
@@ -3,7 +3,12 @@
|
||||
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
|
||||
- SoftBrix
|
||||
|
||||
## 2024
|
||||
- Sobuno
|
||||
- TasneemTantawy
|
||||
- Antônio Franco
|
||||
- yparitcher
|
||||
- Jhon Pedroza
|
||||
|
@@ -26,10 +26,11 @@ 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\Facades\Steam;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -40,6 +41,8 @@ use Illuminate\Http\JsonResponse;
|
||||
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;
|
||||
@@ -61,7 +64,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 +76,43 @@ 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 = [];
|
||||
$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 end-of-day for account balance.
|
||||
$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);
|
||||
$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,
|
||||
'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,
|
||||
'currency_id' => (string) $useCurrency->id,
|
||||
'currency_name' => $useCurrency->name,
|
||||
'currency_code' => $useCurrency->code,
|
||||
'currency_symbol' => $useCurrency->symbol,
|
||||
'currency_decimal_places' => $useCurrency->decimal_places,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -114,14 +120,14 @@ 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;
|
||||
}
|
||||
);
|
||||
|
||||
return response()->json($return);
|
||||
return response()->api($return);
|
||||
}
|
||||
}
|
||||
|
@@ -67,13 +67,13 @@ class BillController extends Controller
|
||||
$filtered = $result->map(
|
||||
static function (Bill $item) {
|
||||
return [
|
||||
'id' => (string)$item->id,
|
||||
'id' => (string) $item->id,
|
||||
'name' => $item->name,
|
||||
'active' => $item->active,
|
||||
];
|
||||
}
|
||||
);
|
||||
|
||||
return response()->json($filtered->toArray());
|
||||
return response()->api($filtered->toArray());
|
||||
}
|
||||
}
|
||||
|
@@ -67,12 +67,12 @@ class BudgetController extends Controller
|
||||
$filtered = $result->map(
|
||||
static function (Budget $item) {
|
||||
return [
|
||||
'id' => (string)$item->id,
|
||||
'id' => (string) $item->id,
|
||||
'name' => $item->name,
|
||||
];
|
||||
}
|
||||
);
|
||||
|
||||
return response()->json($filtered);
|
||||
return response()->api($filtered->toArray());
|
||||
}
|
||||
}
|
||||
|
@@ -67,12 +67,12 @@ class CategoryController extends Controller
|
||||
$filtered = $result->map(
|
||||
static function (Category $item) {
|
||||
return [
|
||||
'id' => (string)$item->id,
|
||||
'id' => (string) $item->id,
|
||||
'name' => $item->name,
|
||||
];
|
||||
}
|
||||
);
|
||||
|
||||
return response()->json($filtered);
|
||||
return response()->api($filtered->toArray());
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -77,14 +77,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 +97,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 +115,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);
|
||||
}
|
||||
}
|
||||
|
@@ -27,11 +27,12 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
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\Facades\Steam;
|
||||
use FireflyIII\Support\Http\Api\ApiSupport;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -80,12 +81,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 +102,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 +118,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;
|
||||
|
@@ -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\Transformers\V2\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 Illuminate\Support\Collection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Serializer\JsonApiSerializer;
|
||||
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
@@ -41,8 +51,8 @@ use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
/**
|
||||
* Class Controller.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
* @SuppressWarnings(PHPMD.NumberOfChildren)
|
||||
* @SuppressWarnings("PHPMD.CouplingBetweenObjects")
|
||||
* @SuppressWarnings("PHPMD.NumberOfChildren")
|
||||
*/
|
||||
abstract class Controller extends BaseController
|
||||
{
|
||||
@@ -50,11 +60,15 @@ abstract class Controller extends BaseController
|
||||
use DispatchesJobs;
|
||||
use ValidatesRequests;
|
||||
|
||||
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';
|
||||
|
||||
/** @var array<int, string> */
|
||||
protected array $allowedSort;
|
||||
protected ParameterBag $parameters;
|
||||
protected bool $convertToNative = false;
|
||||
protected array $accepts = ['application/json', 'application/vnd.api+json'];
|
||||
protected TransactionCurrency $nativeCurrency;
|
||||
|
||||
/**
|
||||
* Controller constructor.
|
||||
@@ -67,10 +81,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 +105,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 +130,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 +157,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 +175,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 +189,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 +247,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]),
|
||||
|
@@ -59,7 +59,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function accounts(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -88,7 +88,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($data[$key]))
|
||||
;
|
||||
|
||||
return $response;
|
||||
@@ -100,7 +100,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function bills(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -115,7 +115,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function budgets(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -130,7 +130,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function categories(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -145,7 +145,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function piggyBanks(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -160,7 +160,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function recurring(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -175,7 +175,7 @@ class ExportController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||
*/
|
||||
public function rules(ExportRequest $request): LaravelResponse
|
||||
{
|
||||
@@ -190,7 +190,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_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_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'], 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'], 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_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'])
|
||||
);
|
||||
$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'], 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'], 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_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'])
|
||||
);
|
||||
$response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference']; // intentional float
|
||||
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -111,7 +111,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);
|
||||
|
@@ -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;
|
||||
|
@@ -25,6 +25,7 @@ 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;
|
||||
@@ -208,6 +209,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:
|
||||
|
@@ -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);
|
||||
|
@@ -0,0 +1,82 @@
|
||||
<?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\UserGroups\ExchangeRate\ExchangeRateRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class DestroyController extends Controller
|
||||
{
|
||||
use ValidatesUserGroupTrait;
|
||||
|
||||
protected array $acceptedRoles = [UserRoleEnum::OWNER];
|
||||
|
||||
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 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\UserGroups\ExchangeRate\ExchangeRateRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use FireflyIII\Transformers\V2\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\UserGroups\ExchangeRate\ExchangeRateRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use FireflyIII\Transformers\V2\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\UserGroups\ExchangeRate\ExchangeRateRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use FireflyIII\Transformers\V2\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\UserGroups\ExchangeRate\ExchangeRateRepositoryInterface;
|
||||
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
|
||||
use FireflyIII\Transformers\V2\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,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankEventTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -58,6 +59,38 @@ 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();
|
||||
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.piggy-banks.accounts', [$piggyBank->id]).$this->buildParams());
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($events, $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);
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -88,21 +88,21 @@ class StoreController extends Controller
|
||||
|
||||
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()]
|
||||
);
|
||||
|
||||
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()]);
|
||||
|
||||
throw new ValidationException($validator); // @phpstan-ignore-line
|
||||
throw new ValidationException($validator);
|
||||
}
|
||||
app('preferences')->mark();
|
||||
$applyRules = $data['apply_rules'] ?? true;
|
||||
|
@@ -72,13 +72,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();
|
||||
|
||||
|
@@ -91,7 +91,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;
|
||||
}
|
||||
@@ -236,10 +236,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 +286,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) {
|
||||
|
@@ -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);
|
||||
|
@@ -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.
|
||||
*
|
||||
|
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)
|
||||
;
|
||||
}
|
||||
}
|
@@ -62,14 +62,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 */
|
||||
|
@@ -47,8 +47,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);
|
||||
|
@@ -27,19 +27,21 @@ 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\Support\Facades\Amount;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class BasicController
|
||||
@@ -101,10 +103,10 @@ class BasicController extends Controller
|
||||
$billData = $this->getBillInformation($start, $end);
|
||||
$spentData = $this->getLeftToSpendInfo($start, $end);
|
||||
$netWorthData = $this->getNetWorthInfo($start, $end);
|
||||
// $balanceData = [];
|
||||
// $billData = [];
|
||||
// $spentData = [];
|
||||
// $netWorthData = [];
|
||||
// $balanceData = [];
|
||||
// $billData = [];
|
||||
// $spentData = [];
|
||||
// $netWorthData = [];
|
||||
$total = array_merge($balanceData, $billData, $spentData, $netWorthData);
|
||||
|
||||
// give new keys
|
||||
@@ -120,48 +122,53 @@ class BasicController extends Controller
|
||||
|
||||
private function getBalanceInformation(Carbon $start, Carbon $end): array
|
||||
{
|
||||
// some config settings
|
||||
$convertToNative = Amount::convertToNative();
|
||||
$default = Amount::getNativeCurrency();
|
||||
// prep some arrays:
|
||||
$incomes = [];
|
||||
$expenses = [];
|
||||
$sums = [];
|
||||
$return = [];
|
||||
$incomes = [];
|
||||
$expenses = [];
|
||||
$sums = [];
|
||||
$return = [];
|
||||
|
||||
// collect income of user using the new group collector.
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::DEPOSIT->value]);
|
||||
|
||||
$set = $collector->getExtractedJournals();
|
||||
$set = $collector->getExtractedJournals();
|
||||
|
||||
/** @var array $transactionJournal */
|
||||
foreach ($set as $transactionJournal) {
|
||||
$currencyId = (int)$transactionJournal['currency_id'];
|
||||
/** @var array $journal */
|
||||
foreach ($set as $journal) {
|
||||
$currencyId = $convertToNative ? $default->id : (int) $journal['currency_id'];
|
||||
$amount = Amount::getAmountFromJournal($journal);
|
||||
$incomes[$currencyId] ??= '0';
|
||||
$incomes[$currencyId] = bcadd(
|
||||
$incomes[$currencyId],
|
||||
bcmul($transactionJournal['amount'], '-1')
|
||||
bcmul($amount, '-1')
|
||||
);
|
||||
$sums[$currencyId] ??= '0';
|
||||
$sums[$currencyId] = bcadd($sums[$currencyId], bcmul($transactionJournal['amount'], '-1'));
|
||||
$sums[$currencyId] = bcadd($sums[$currencyId], bcmul($amount, '-1'));
|
||||
}
|
||||
|
||||
// collect expenses of user using the new group collector.
|
||||
/** @var GroupCollectorInterface $collector */
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
|
||||
$set = $collector->getExtractedJournals();
|
||||
$set = $collector->getExtractedJournals();
|
||||
|
||||
/** @var array $transactionJournal */
|
||||
foreach ($set as $transactionJournal) {
|
||||
$currencyId = (int)$transactionJournal['currency_id'];
|
||||
/** @var array $journal */
|
||||
foreach ($set as $journal) {
|
||||
$currencyId = $convertToNative ? $default->id : (int) $journal['currency_id'];
|
||||
$amount = Amount::getAmountFromJournal($journal);
|
||||
$expenses[$currencyId] ??= '0';
|
||||
$expenses[$currencyId] = bcadd($expenses[$currencyId], $transactionJournal['amount']);
|
||||
$expenses[$currencyId] = bcadd($expenses[$currencyId], $amount);
|
||||
$sums[$currencyId] ??= '0';
|
||||
$sums[$currencyId] = bcadd($sums[$currencyId], $transactionJournal['amount']);
|
||||
$sums[$currencyId] = bcadd($sums[$currencyId], $amount);
|
||||
}
|
||||
|
||||
// format amounts:
|
||||
$keys = array_keys($sums);
|
||||
$keys = array_keys($sums);
|
||||
foreach ($keys as $currencyId) {
|
||||
$currency = $this->currencyRepos->find($currencyId);
|
||||
if (null === $currency) {
|
||||
@@ -172,7 +179,7 @@ class BasicController extends Controller
|
||||
'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,
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
@@ -185,7 +192,7 @@ class BasicController extends Controller
|
||||
'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,
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
@@ -197,7 +204,7 @@ class BasicController extends Controller
|
||||
'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,
|
||||
'currency_id' => (string) $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
@@ -231,7 +238,7 @@ class BasicController extends Controller
|
||||
'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'],
|
||||
@@ -250,7 +257,7 @@ class BasicController extends Controller
|
||||
'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'],
|
||||
@@ -269,29 +276,32 @@ class BasicController extends Controller
|
||||
*/
|
||||
private function getLeftToSpendInfo(Carbon $start, Carbon $end): array
|
||||
{
|
||||
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;
|
||||
|
||||
foreach ($spent as $row) {
|
||||
// either an amount was budgeted or 0 is available.
|
||||
$amount = (string)($available[$row['currency_id']] ?? '0');
|
||||
$currencyId = $row['currency_id'];
|
||||
$amount = (string) ($available[$currencyId] ?? '0');
|
||||
$spentInCurrency = $row['sum'];
|
||||
$leftToSpend = bcadd($amount, $spentInCurrency);
|
||||
|
||||
$days = (int)$today->diffInDays($end, true) + 1;
|
||||
$perDay = '0';
|
||||
if (0 !== $days && bccomp($leftToSpend, '0') > -1) {
|
||||
$perDay = bcdiv($leftToSpend, (string)$days);
|
||||
$perDay = bcdiv($leftToSpend, (string) $days);
|
||||
}
|
||||
|
||||
Log::debug(sprintf('Spent %s %s', $row['currency_code'], $row['sum']));
|
||||
|
||||
$return[] = [
|
||||
'key' => sprintf('left-to-spend-in-%s', $row['currency_code']),
|
||||
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $row['currency_symbol']]),
|
||||
'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'],
|
||||
@@ -311,9 +321,11 @@ class BasicController extends Controller
|
||||
|
||||
private function getNetWorthInfo(Carbon $start, Carbon $end): array
|
||||
{
|
||||
Log::debug('getNetWorthInfo');
|
||||
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
$date = today(config('app.timezone'))->startOfDay();
|
||||
$date = now(config('app.timezone'));
|
||||
// start and end in the future? use $end
|
||||
if ($this->notInDateRange($date, $start, $end)) {
|
||||
/** @var Carbon $date */
|
||||
@@ -323,9 +335,7 @@ class BasicController extends Controller
|
||||
/** @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(
|
||||
@@ -351,7 +361,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 +370,7 @@ class BasicController extends Controller
|
||||
'sub_title' => '',
|
||||
];
|
||||
}
|
||||
Log::debug('End of getNetWorthInfo');
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
@@ -58,7 +58,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',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -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'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -25,8 +25,8 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests\Insight;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Enums\AccountTypeEnum;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
@@ -70,7 +70,7 @@ class GenericRequest extends FormRequest
|
||||
/** @var Account $account */
|
||||
foreach ($this->accounts as $account) {
|
||||
$type = $account->accountType->type;
|
||||
if (in_array($type, [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], true)) {
|
||||
if (in_array($type, [AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value], true)) {
|
||||
$return->push($account);
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ class GenericRequest extends FormRequest
|
||||
$array = $this->get('accounts');
|
||||
if (is_array($array)) {
|
||||
foreach ($array as $accountId) {
|
||||
$accountId = (int)$accountId;
|
||||
$accountId = (int) $accountId;
|
||||
$account = $repository->find($accountId);
|
||||
if (null !== $account) {
|
||||
$this->accounts->push($account);
|
||||
@@ -114,7 +114,7 @@ class GenericRequest extends FormRequest
|
||||
$array = $this->get('bills');
|
||||
if (is_array($array)) {
|
||||
foreach ($array as $billId) {
|
||||
$billId = (int)$billId;
|
||||
$billId = (int) $billId;
|
||||
$bill = $repository->find($billId);
|
||||
if (null !== $bill) {
|
||||
$this->bills->push($bill);
|
||||
@@ -140,7 +140,7 @@ class GenericRequest extends FormRequest
|
||||
$array = $this->get('budgets');
|
||||
if (is_array($array)) {
|
||||
foreach ($array as $budgetId) {
|
||||
$budgetId = (int)$budgetId;
|
||||
$budgetId = (int) $budgetId;
|
||||
$budget = $repository->find($budgetId);
|
||||
if (null !== $budget) {
|
||||
$this->budgets->push($budget);
|
||||
@@ -166,7 +166,7 @@ class GenericRequest extends FormRequest
|
||||
$array = $this->get('categories');
|
||||
if (is_array($array)) {
|
||||
foreach ($array as $categoryId) {
|
||||
$categoryId = (int)$categoryId;
|
||||
$categoryId = (int) $categoryId;
|
||||
$category = $repository->find($categoryId);
|
||||
if (null !== $category) {
|
||||
$this->categories->push($category);
|
||||
@@ -191,7 +191,7 @@ class GenericRequest extends FormRequest
|
||||
/** @var Account $account */
|
||||
foreach ($this->accounts as $account) {
|
||||
$type = $account->accountType->type;
|
||||
if (AccountType::EXPENSE === $type) {
|
||||
if (AccountTypeEnum::EXPENSE->value === $type) {
|
||||
$return->push($account);
|
||||
}
|
||||
}
|
||||
@@ -207,7 +207,7 @@ class GenericRequest extends FormRequest
|
||||
/** @var Account $account */
|
||||
foreach ($this->accounts as $account) {
|
||||
$type = $account->accountType->type;
|
||||
if (AccountType::REVENUE === $type) {
|
||||
if (AccountTypeEnum::REVENUE->value === $type) {
|
||||
$return->push($account);
|
||||
}
|
||||
}
|
||||
@@ -240,7 +240,7 @@ class GenericRequest extends FormRequest
|
||||
$array = $this->get('tags');
|
||||
if (is_array($array)) {
|
||||
foreach ($array as $tagId) {
|
||||
$tagId = (int)$tagId;
|
||||
$tagId = (int) $tagId;
|
||||
$tag = $repository->find($tagId);
|
||||
if (null !== $tag) {
|
||||
$this->tags->push($tag);
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests\Models\Account;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Location;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\UniqueAccountNumber;
|
||||
use FireflyIII\Rules\UniqueIban;
|
||||
@@ -33,6 +34,8 @@ use FireflyIII\Support\Request\AppendsLocationData;
|
||||
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 UpdateRequest
|
||||
@@ -112,4 +115,36 @@ class UpdateRequest extends FormRequest
|
||||
|
||||
return Location::requestRules($rules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance with special rules for after the basic validation rules.
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator): void {
|
||||
// validate start before end only if both are there.
|
||||
$data = $validator->getData();
|
||||
|
||||
/** @var Account $account */
|
||||
$account = $this->route()->parameter('account');
|
||||
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$currency = $repository->getAccountCurrency($account);
|
||||
|
||||
// how many piggies are attached?
|
||||
$piggyBanks = $account->piggyBanks()->count();
|
||||
if ($piggyBanks > 0 && array_key_exists('currency_code', $data) && $data['currency_code'] !== $currency->code) {
|
||||
$validator->errors()->add('currency_code', (string) trans('validation.piggy_no_change_currency'));
|
||||
}
|
||||
if ($piggyBanks > 0 && array_key_exists('currency_id', $data) && (int) $data['currency_id'] !== $currency->id) {
|
||||
$validator->errors()->add('currency_id', (string) trans('validation.piggy_no_change_currency'));
|
||||
}
|
||||
}
|
||||
);
|
||||
if ($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -66,8 +66,8 @@ class Request extends FormRequest
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
'amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'start' => 'date',
|
||||
'end' => 'date',
|
||||
'start' => 'date|after:1900-01-01|before:2099-12-31',
|
||||
'end' => 'date|after:1900-01-01|before:2099-12-31',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ class Request extends FormRequest
|
||||
$start = new Carbon($data['start']);
|
||||
$end = new Carbon($data['end']);
|
||||
if ($end->isBefore($start)) {
|
||||
$validator->errors()->add('end', (string)trans('validation.date_after'));
|
||||
$validator->errors()->add('end', (string) trans('validation.date_after'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -78,9 +78,9 @@ class StoreRequest extends FormRequest
|
||||
'amount_max' => ['required', new IsValidPositiveAmount()],
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
'date' => 'date|required',
|
||||
'end_date' => 'nullable|date|after:date',
|
||||
'extension_date' => 'nullable|date|after:date',
|
||||
'date' => 'date|required|after:1900-01-01|before:2099-12-31',
|
||||
'end_date' => 'nullable|date|after:date|after:1900-01-01|before:2099-12-31',
|
||||
'extension_date' => 'nullable|date|after:date|after:1900-01-01|before:2099-12-31',
|
||||
'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly|required',
|
||||
'skip' => 'min:0|max:31|numeric',
|
||||
'active' => [new IsBoolean()],
|
||||
@@ -95,16 +95,40 @@ class StoreRequest extends FormRequest
|
||||
{
|
||||
$validator->after(
|
||||
static function (Validator $validator): void {
|
||||
$data = $validator->getData();
|
||||
$min = (string)($data['amount_min'] ?? '0');
|
||||
$max = (string)($data['amount_max'] ?? '0');
|
||||
$data = $validator->getData();
|
||||
$min = $data['amount_min'] ?? '0';
|
||||
$max = $data['amount_max'] ?? '0';
|
||||
|
||||
if (1 === bccomp($min, $max)) {
|
||||
$validator->errors()->add('amount_min', (string)trans('validation.amount_min_over_max'));
|
||||
if (is_array($min) || is_array($max)) {
|
||||
$validator->errors()->add('amount_min', (string) trans('validation.generic_invalid'));
|
||||
$validator->errors()->add('amount_max', (string) trans('validation.generic_invalid'));
|
||||
$min = '0';
|
||||
$max = '0';
|
||||
}
|
||||
$result = false;
|
||||
|
||||
try {
|
||||
$result = bccomp($min, $max);
|
||||
} catch (\ValueError $e) {
|
||||
Log::error($e->getMessage());
|
||||
$validator->errors()->add('amount_min', (string) trans('validation.generic_invalid'));
|
||||
$validator->errors()->add('amount_max', (string) trans('validation.generic_invalid'));
|
||||
}
|
||||
|
||||
if (1 === $result) {
|
||||
$validator->errors()->add('amount_min', (string) trans('validation.amount_min_over_max'));
|
||||
}
|
||||
}
|
||||
);
|
||||
if ($validator->fails()) {
|
||||
$failed = false;
|
||||
|
||||
try {
|
||||
$failed = $validator->fails();
|
||||
} catch (\TypeError $e) {
|
||||
Log::error($e->getMessage());
|
||||
$failed = false;
|
||||
}
|
||||
if ($failed) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
@@ -81,9 +81,9 @@ class UpdateRequest extends FormRequest
|
||||
'amount_max' => ['nullable', new IsValidPositiveAmount()],
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
'date' => 'date',
|
||||
'end_date' => 'date|after:date',
|
||||
'extension_date' => 'date|after:date',
|
||||
'date' => 'date|after:1900-01-01|before:2099-12-31',
|
||||
'end_date' => 'date|after:date|after:1900-01-01|before:2099-12-31',
|
||||
'extension_date' => 'date|after:date|after:1900-01-01|before:2099-12-31',
|
||||
'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly',
|
||||
'skip' => 'min:0|max:31|numeric',
|
||||
'active' => [new IsBoolean()],
|
||||
@@ -104,7 +104,7 @@ class UpdateRequest extends FormRequest
|
||||
$max = $data['amount_max'] ?? '0';
|
||||
|
||||
if (1 === bccomp($min, $max)) {
|
||||
$validator->errors()->add('amount_min', (string)trans('validation.amount_min_over_max'));
|
||||
$validator->errors()->add('amount_min', (string) trans('validation.amount_min_over_max'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -48,6 +48,7 @@ class StoreRequest extends FormRequest
|
||||
'amount' => $this->convertString('amount'),
|
||||
'currency_id' => $this->convertInteger('currency_id'),
|
||||
'currency_code' => $this->convertString('currency_code'),
|
||||
'notes' => $this->stringWithNewlines('notes'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -62,6 +63,7 @@ class StoreRequest extends FormRequest
|
||||
'amount' => ['required', new IsValidPositiveAmount()],
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
'notes' => 'nullable|min:0|max:32768',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -51,7 +51,12 @@ class UpdateRequest extends FormRequest
|
||||
'amount' => ['amount', 'convertString'],
|
||||
'currency_id' => ['currency_id', 'convertInteger'],
|
||||
'currency_code' => ['currency_code', 'convertString'],
|
||||
'notes' => ['notes', 'stringWithNewlines'],
|
||||
];
|
||||
if (false === $this->has('notes')) {
|
||||
// ignore notes, not submitted.
|
||||
unset($fields['notes']);
|
||||
}
|
||||
|
||||
return $this->getAllData($fields);
|
||||
}
|
||||
@@ -62,11 +67,12 @@ class UpdateRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date',
|
||||
'start' => 'date|after:1900-01-01|before:2099-12-31',
|
||||
'end' => 'date|after:1900-01-01|before:2099-12-31',
|
||||
'amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'currency_id' => 'numeric|exists:transaction_currencies,id',
|
||||
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
|
||||
'notes' => 'nullable|min:0|max:32768',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -84,7 +90,7 @@ class UpdateRequest extends FormRequest
|
||||
$start = new Carbon($data['start']);
|
||||
$end = new Carbon($data['end']);
|
||||
if ($end->isBefore($start)) {
|
||||
$validator->errors()->add('end', (string)trans('validation.date_after'));
|
||||
$validator->errors()->add('end', (string) trans('validation.date_after'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* CollectsCustomParameters.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
* DestroyRequest.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -22,25 +22,30 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\JsonApi;
|
||||
namespace FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
trait CollectsCustomParameters
|
||||
class DestroyRequest extends FormRequest
|
||||
{
|
||||
protected function getOtherParams(array $params): array
|
||||
{
|
||||
$return = [];
|
||||
if (array_key_exists('startPeriod', $params)) {
|
||||
$return['start'] = Carbon::parse($params['startPeriod']);
|
||||
}
|
||||
if (array_key_exists('endPeriod', $params)) {
|
||||
$return['end'] = Carbon::parse($params['endPeriod']);
|
||||
}
|
||||
if (array_key_exists('currentMoment', $params)) {
|
||||
$return['today'] = Carbon::parse($params['currentMoment']);
|
||||
}
|
||||
use ChecksLogin;
|
||||
use ConvertsDataTypes;
|
||||
|
||||
return $return;
|
||||
public function getDate(): ?Carbon
|
||||
{
|
||||
return $this->getCarbonDate('date');
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'date' => 'required|date|after:1900-01-01|before:2099-12-31',
|
||||
];
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* StoreRequest.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\Requests\Models\CurrencyExchangeRate;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreRequest extends FormRequest
|
||||
{
|
||||
use ChecksLogin;
|
||||
use ConvertsDataTypes;
|
||||
|
||||
public function getDate(): ?Carbon
|
||||
{
|
||||
return $this->getCarbonDate('date');
|
||||
}
|
||||
|
||||
public function getRate(): string
|
||||
{
|
||||
return (string) $this->get('rate');
|
||||
}
|
||||
|
||||
public function getFromCurrency(): TransactionCurrency
|
||||
{
|
||||
return TransactionCurrency::where('code', $this->get('from'))->first();
|
||||
}
|
||||
|
||||
public function getToCurrency(): TransactionCurrency
|
||||
{
|
||||
return TransactionCurrency::where('code', $this->get('to'))->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'date' => 'required|date|after:1900-01-01|before:2099-12-31',
|
||||
'rate' => 'required|numeric|gt:0',
|
||||
'from' => 'required|exists:transaction_currencies,code',
|
||||
'to' => 'required|exists:transaction_currencies,code',
|
||||
];
|
||||
}
|
||||
}
|
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* AccountBalanceQuery.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
* UpdateRequest.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -22,38 +22,36 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\JsonApi\V2\AccountBalances\Capabilities;
|
||||
namespace FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate;
|
||||
|
||||
use FireflyIII\Entities\AccountBalance;
|
||||
use FireflyIII\Models\Account;
|
||||
use LaravelJsonApi\NonEloquent\Capabilities\QueryAll;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class AccountBalanceQuery extends QueryAll
|
||||
class UpdateRequest extends FormRequest
|
||||
{
|
||||
private Account $account;
|
||||
use ChecksLogin;
|
||||
use ConvertsDataTypes;
|
||||
|
||||
public function getDate(): ?Carbon
|
||||
{
|
||||
return $this->getCarbonDate('date');
|
||||
}
|
||||
|
||||
public function getRate(): string
|
||||
{
|
||||
return (string) $this->get('rate');
|
||||
}
|
||||
|
||||
/**
|
||||
* QuerySites constructor.
|
||||
* The rules that the incoming request must be matched against.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function get(): iterable
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
AccountBalance::fromArray(),
|
||||
AccountBalance::fromArray(),
|
||||
AccountBalance::fromArray(),
|
||||
AccountBalance::fromArray(),
|
||||
'date' => 'date|after:1900-01-01|before:2099-12-31',
|
||||
'rate' => 'required|numeric|gt:0',
|
||||
];
|
||||
}
|
||||
|
||||
public function withAccount(Account $account): self
|
||||
{
|
||||
$this->account = $account;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@@ -24,10 +24,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Models\PiggyBank;
|
||||
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Rules\IsValidZeroOrMoreAmount;
|
||||
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 StoreRequest
|
||||
@@ -42,38 +47,123 @@ class StoreRequest extends FormRequest
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$fields = [
|
||||
$fields = [
|
||||
'order' => ['order', 'convertInteger'],
|
||||
];
|
||||
$data = $this->getAllData($fields);
|
||||
$data['name'] = $this->convertString('name');
|
||||
$data['account_id'] = $this->convertInteger('account_id');
|
||||
$data['targetamount'] = $this->convertString('target_amount');
|
||||
$data['current_amount'] = $this->convertString('current_amount');
|
||||
$data['startdate'] = $this->getCarbonDate('start_date');
|
||||
$data['targetdate'] = $this->getCarbonDate('target_date');
|
||||
$data['notes'] = $this->stringWithNewlines('notes');
|
||||
$data['object_group_id'] = $this->convertInteger('object_group_id');
|
||||
$data['object_group_title'] = $this->convertString('object_group_title');
|
||||
$data = $this->getAllData($fields);
|
||||
$data['name'] = $this->convertString('name');
|
||||
$data['accounts'] = $this->parseAccounts($this->get('accounts'));
|
||||
$data['target_amount'] = $this->convertString('target_amount');
|
||||
$data['start_date'] = $this->getCarbonDate('start_date');
|
||||
$data['target_date'] = $this->getCarbonDate('target_date');
|
||||
$data['notes'] = $this->stringWithNewlines('notes');
|
||||
$data['object_group_id'] = $this->convertInteger('object_group_id');
|
||||
$data['transaction_currency_id'] = $this->convertInteger('transaction_currency_id');
|
||||
$data['transaction_currency_code'] = $this->convertString('transaction_currency_code');
|
||||
$data['object_group_title'] = $this->convertString('object_group_title');
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function parseAccounts(mixed $array): array
|
||||
{
|
||||
if (!is_array($array)) {
|
||||
return [];
|
||||
}
|
||||
$return = [];
|
||||
foreach ($array as $entry) {
|
||||
if (!is_array($entry)) {
|
||||
continue;
|
||||
}
|
||||
$return[] = [
|
||||
'account_id' => $this->integerFromValue((string) ($entry['account_id'] ?? '0')),
|
||||
'current_amount' => $this->clearString((string) ($entry['current_amount'] ?? '0')),
|
||||
];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The rules that the incoming request must be matched against.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|min:1|max:255|uniquePiggyBankForUser',
|
||||
'current_amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'account_id' => 'required|numeric|belongsToUser:accounts,id',
|
||||
'object_group_id' => 'numeric|belongsToUser:object_groups,id',
|
||||
'object_group_title' => ['min:1', 'max:255'],
|
||||
'target_amount' => ['required', new IsValidPositiveAmount()],
|
||||
'start_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable|after:start_date',
|
||||
'notes' => 'max:65000',
|
||||
'name' => 'required|min:1|max:255|uniquePiggyBankForUser',
|
||||
'accounts' => 'required',
|
||||
'accounts.*' => 'array|required',
|
||||
'accounts.*.account_id' => 'required|numeric|belongsToUser:accounts,id',
|
||||
'accounts.*.current_amount' => ['numeric', new IsValidZeroOrMoreAmount()],
|
||||
'object_group_id' => 'numeric|belongsToUser:object_groups,id',
|
||||
'object_group_title' => ['min:1', 'max:255'],
|
||||
'target_amount' => ['required', new IsValidZeroOrMoreAmount()],
|
||||
'start_date' => 'date|nullable',
|
||||
'transaction_currency_id' => 'exists:transaction_currencies,id|required_without:transaction_currency_code',
|
||||
'transaction_currency_code' => 'exists:transaction_currencies,code|required_without:transaction_currency_id',
|
||||
'target_date' => 'date|nullable|after:start_date',
|
||||
'notes' => 'max:65000',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Can only store money on liabilities and asset accounts.
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator): void {
|
||||
// validate start before end only if both are there.
|
||||
$data = $validator->getData();
|
||||
$currency = $this->getCurrencyFromData($data);
|
||||
$targetAmount = (string) ($data['target_amount'] ?? '0');
|
||||
$currentAmount = '0';
|
||||
if (array_key_exists('accounts', $data) && is_array($data['accounts'])) {
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$types = config('firefly.piggy_bank_account_types');
|
||||
foreach ($data['accounts'] as $index => $array) {
|
||||
$accountId = (int) ($array['account_id'] ?? 0);
|
||||
$account = $repository->find($accountId);
|
||||
if (null !== $account) {
|
||||
// check currency here.
|
||||
$accountCurrency = $repository->getAccountCurrency($account);
|
||||
$isMultiCurrency = $repository->getMetaValue($account, 'is_multi_currency');
|
||||
$currentAmount = bcadd($currentAmount, (string) ($array['current_amount'] ?? '0'));
|
||||
if ($accountCurrency->id !== $currency->id && 'true' !== $isMultiCurrency) {
|
||||
$validator->errors()->add(sprintf('accounts.%d', $index), trans('validation.invalid_account_currency'));
|
||||
}
|
||||
$type = $account->accountType->type;
|
||||
if (!in_array($type, $types, true)) {
|
||||
$validator->errors()->add(sprintf('accounts.%d', $index), trans('validation.invalid_account_type'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (-1 === bccomp($targetAmount, $currentAmount) && 1 === bccomp($targetAmount, '0')) {
|
||||
$validator->errors()->add('target_amount', trans('validation.current_amount_too_much'));
|
||||
}
|
||||
}
|
||||
);
|
||||
if ($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
private function getCurrencyFromData(array $data): TransactionCurrency
|
||||
{
|
||||
if (array_key_exists('transaction_currency_code', $data) && '' !== (string) $data['transaction_currency_code']) {
|
||||
$currency = TransactionCurrency::whereCode($data['transaction_currency_code'])->first();
|
||||
if (null !== $currency) {
|
||||
return $currency;
|
||||
}
|
||||
}
|
||||
if (array_key_exists('transaction_currency_id', $data) && '' !== (string) $data['transaction_currency_id']) {
|
||||
$currency = TransactionCurrency::find((int) $data['transaction_currency_id']);
|
||||
if (null !== $currency) {
|
||||
return $currency;
|
||||
}
|
||||
}
|
||||
|
||||
throw new FireflyException('Unexpected empty currency.');
|
||||
}
|
||||
}
|
||||
|
@@ -121,10 +121,10 @@ class StoreRequest extends FormRequest
|
||||
$current['moment'] = $repetition['moment'];
|
||||
}
|
||||
if (array_key_exists('skip', $repetition)) {
|
||||
$current['skip'] = (int)$repetition['skip'];
|
||||
$current['skip'] = (int) $repetition['skip'];
|
||||
}
|
||||
if (array_key_exists('weekend', $repetition)) {
|
||||
$current['weekend'] = (int)$repetition['weekend'];
|
||||
$current['weekend'] = (int) $repetition['weekend'];
|
||||
}
|
||||
|
||||
$return[] = $current;
|
||||
|
@@ -101,15 +101,15 @@ class UpdateRequest extends FormRequest
|
||||
}
|
||||
|
||||
if (array_key_exists('moment', $repetition)) {
|
||||
$current['moment'] = (string)$repetition['moment'];
|
||||
$current['moment'] = (string) $repetition['moment'];
|
||||
}
|
||||
|
||||
if (array_key_exists('skip', $repetition)) {
|
||||
$current['skip'] = (int)$repetition['skip'];
|
||||
$current['skip'] = (int) $repetition['skip'];
|
||||
}
|
||||
|
||||
if (array_key_exists('weekend', $repetition)) {
|
||||
$current['weekend'] = (int)$repetition['weekend'];
|
||||
$current['weekend'] = (int) $repetition['weekend'];
|
||||
}
|
||||
$return[] = $current;
|
||||
}
|
||||
@@ -154,7 +154,7 @@ class UpdateRequest extends FormRequest
|
||||
return [
|
||||
'title' => sprintf('min:1|max:255|uniqueObjectForUser:recurrences,title,%d', $recurrence->id),
|
||||
'description' => 'min:1|max:32768',
|
||||
'first_date' => 'date',
|
||||
'first_date' => 'date|after:1900-01-01|before:2099-12-31',
|
||||
'apply_rules' => [new IsBoolean()],
|
||||
'active' => [new IsBoolean()],
|
||||
'repeat_until' => 'nullable|date',
|
||||
|
@@ -74,9 +74,9 @@ class StoreRequest extends FormRequest
|
||||
$return[] = [
|
||||
'type' => $trigger['type'] ?? '',
|
||||
'value' => $trigger['value'] ?? null,
|
||||
'prohibited' => $this->convertBoolean((string)($trigger['prohibited'] ?? 'false')),
|
||||
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'true')),
|
||||
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
|
||||
'prohibited' => $this->convertBoolean((string) ($trigger['prohibited'] ?? 'false')),
|
||||
'active' => $this->convertBoolean((string) ($trigger['active'] ?? 'true')),
|
||||
'stop_processing' => $this->convertBoolean((string) ($trigger['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -93,8 +93,8 @@ class StoreRequest extends FormRequest
|
||||
$return[] = [
|
||||
'type' => $action['type'],
|
||||
'value' => $action['value'],
|
||||
'active' => $this->convertBoolean((string)($action['active'] ?? 'true')),
|
||||
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
|
||||
'active' => $this->convertBoolean((string) ($action['active'] ?? 'true')),
|
||||
'stop_processing' => $this->convertBoolean((string) ($action['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ class StoreRequest extends FormRequest
|
||||
'description' => 'min:1|max:32768|nullable',
|
||||
'rule_group_id' => 'belongsToUser:rule_groups|required_without:rule_group_title',
|
||||
'rule_group_title' => 'nullable|min:1|max:255|required_without:rule_group_id|belongsToUser:rule_groups,title',
|
||||
'trigger' => 'required|in:store-journal,update-journal',
|
||||
'trigger' => 'required|in:store-journal,update-journal,manual-activation',
|
||||
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers),
|
||||
'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue|max:1024',
|
||||
'triggers.*.stop_processing' => [new IsBoolean()],
|
||||
@@ -161,7 +161,7 @@ class StoreRequest extends FormRequest
|
||||
$triggers = $data['triggers'] ?? [];
|
||||
// need at least one trigger
|
||||
if (!is_countable($triggers) || 0 === count($triggers)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
|
||||
$validator->errors()->add('title', (string) trans('validation.at_least_one_trigger'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ class StoreRequest extends FormRequest
|
||||
$actions = $data['actions'] ?? [];
|
||||
// need at least one trigger
|
||||
if (!is_countable($actions) || 0 === count($actions)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
|
||||
$validator->errors()->add('title', (string) trans('validation.at_least_one_action'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ class StoreRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
if (true === $allInactive) {
|
||||
$validator->errors()->add(sprintf('triggers.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_trigger'));
|
||||
$validator->errors()->add(sprintf('triggers.%d.active', $inactiveIndex), (string) trans('validation.at_least_one_active_trigger'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ class StoreRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
if (true === $allInactive) {
|
||||
$validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
|
||||
$validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string) trans('validation.at_least_one_active_action'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -49,7 +49,7 @@ class TestRequest extends FormRequest
|
||||
|
||||
private function getPage(): int
|
||||
{
|
||||
return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page');
|
||||
return 0 === (int) $this->query('page') ? 1 : (int) $this->query('page');
|
||||
}
|
||||
|
||||
private function getDate(string $field): ?Carbon
|
||||
@@ -58,7 +58,7 @@ class TestRequest extends FormRequest
|
||||
if (is_array($value)) {
|
||||
return null;
|
||||
}
|
||||
$value = (string)$value;
|
||||
$value = (string) $value;
|
||||
|
||||
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
|
||||
}
|
||||
@@ -71,8 +71,8 @@ class TestRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date|after_or_equal:start',
|
||||
'start' => 'date|after:1900-01-01|before:2099-12-31',
|
||||
'end' => 'date|after_or_equal:start|after:1900-01-01|before:2099-12-31',
|
||||
'accounts' => '',
|
||||
'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts',
|
||||
];
|
||||
|
@@ -52,7 +52,7 @@ class TriggerRequest extends FormRequest
|
||||
if (is_array($value)) {
|
||||
return null;
|
||||
}
|
||||
$value = (string)$value;
|
||||
$value = (string) $value;
|
||||
|
||||
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
|
||||
}
|
||||
@@ -65,8 +65,8 @@ class TriggerRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date|after_or_equal:start',
|
||||
'start' => 'date|after:1900-01-01|before:2099-12-31',
|
||||
'end' => 'date|after_or_equal:start|after:1900-01-01|before:2099-12-31',
|
||||
'accounts' => '',
|
||||
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
|
||||
];
|
||||
|
@@ -109,8 +109,8 @@ class UpdateRequest extends FormRequest
|
||||
$return[] = [
|
||||
'type' => $action['type'],
|
||||
'value' => $action['value'],
|
||||
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
|
||||
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
|
||||
'active' => $this->convertBoolean((string) ($action['active'] ?? 'false')),
|
||||
'stop_processing' => $this->convertBoolean((string) ($action['stop_processing'] ?? 'false')),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -138,7 +138,7 @@ class UpdateRequest extends FormRequest
|
||||
'description' => 'min:1|max:32768|nullable',
|
||||
'rule_group_id' => 'belongsToUser:rule_groups',
|
||||
'rule_group_title' => 'nullable|min:1|max:255|belongsToUser:rule_groups,title',
|
||||
'trigger' => 'in:store-journal,update-journal',
|
||||
'trigger' => 'in:store-journal,update-journal.manual-activation',
|
||||
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers),
|
||||
'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue|max:1024',
|
||||
'triggers.*.stop_processing' => [new IsBoolean()],
|
||||
@@ -181,7 +181,7 @@ class UpdateRequest extends FormRequest
|
||||
$triggers = $data['triggers'] ?? null;
|
||||
// need at least one trigger
|
||||
if (is_array($triggers) && 0 === count($triggers)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
|
||||
$validator->errors()->add('title', (string) trans('validation.at_least_one_trigger'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ class UpdateRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
if (true === $allInactive) {
|
||||
$validator->errors()->add(sprintf('triggers.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_trigger'));
|
||||
$validator->errors()->add(sprintf('triggers.%d.active', $inactiveIndex), (string) trans('validation.at_least_one_active_trigger'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ class UpdateRequest extends FormRequest
|
||||
$actions = $data['actions'] ?? null;
|
||||
// need at least one action
|
||||
if (is_array($actions) && 0 === count($actions)) {
|
||||
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
|
||||
$validator->errors()->add('title', (string) trans('validation.at_least_one_action'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ class UpdateRequest extends FormRequest
|
||||
}
|
||||
}
|
||||
if (true === $allInactive) {
|
||||
$validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
|
||||
$validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string) trans('validation.at_least_one_active_action'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -52,7 +52,7 @@ class TestRequest extends FormRequest
|
||||
if (is_array($value)) {
|
||||
return null;
|
||||
}
|
||||
$value = (string)$value;
|
||||
$value = (string) $value;
|
||||
|
||||
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
|
||||
}
|
||||
@@ -65,8 +65,8 @@ class TestRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date|after_or_equal:start',
|
||||
'start' => 'date|after:1900-01-01|before:2099-12-31',
|
||||
'end' => 'date|after_or_equal:start|after:1900-01-01|before:2099-12-31',
|
||||
'accounts' => '',
|
||||
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
|
||||
];
|
||||
|
@@ -52,7 +52,7 @@ class TriggerRequest extends FormRequest
|
||||
if (is_array($value)) {
|
||||
return null;
|
||||
}
|
||||
$value = (string)$value;
|
||||
$value = (string) $value;
|
||||
|
||||
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
|
||||
}
|
||||
@@ -69,8 +69,8 @@ class TriggerRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date|after_or_equal:start',
|
||||
'start' => 'date|after:1900-01-01|before:2099-12-31',
|
||||
'end' => 'date|after_or_equal:start|after:1900-01-01|before:2099-12-31',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -62,7 +62,7 @@ class StoreRequest extends FormRequest
|
||||
$rules = [
|
||||
'tag' => 'required|min:1|uniqueObjectForUser:tags,tag|max:1024',
|
||||
'description' => 'min:1|nullable|max:32768',
|
||||
'date' => 'date|nullable',
|
||||
'date' => 'date|nullable|after:1900-01-01|before:2099-12-31',
|
||||
];
|
||||
|
||||
return Location::requestRules($rules);
|
||||
|
@@ -63,11 +63,10 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
/** @var Tag $tag */
|
||||
$tag = $this->route()->parameter('tagOrId');
|
||||
// TODO check if uniqueObjectForUser is obsolete
|
||||
$rules = [
|
||||
'tag' => 'min:1|max:1024|uniqueObjectForUser:tags,tag,'.$tag->id,
|
||||
'description' => 'min:1|nullable|max:32768',
|
||||
'date' => 'date|nullable',
|
||||
'date' => 'date|nullable|after:1900-01-01|before:2099-12-31',
|
||||
];
|
||||
|
||||
return Location::requestRules($rules);
|
||||
|
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Models\Transaction;
|
||||
|
||||
use FireflyIII\Models\Location;
|
||||
use FireflyIII\Rules\BelongsUser;
|
||||
use FireflyIII\Rules\IsBoolean;
|
||||
use FireflyIII\Rules\IsDateOrTime;
|
||||
@@ -82,82 +83,87 @@ class StoreRequest extends FormRequest
|
||||
foreach ($this->get('transactions') as $transaction) {
|
||||
$object = new NullArrayObject($transaction);
|
||||
$return[] = [
|
||||
'type' => $this->clearString($object['type']),
|
||||
'date' => $this->dateFromValue($object['date']),
|
||||
'order' => $this->integerFromValue((string)$object['order']),
|
||||
'type' => $this->clearString($object['type']),
|
||||
'date' => $this->dateFromValue($object['date']),
|
||||
'order' => $this->integerFromValue((string) $object['order']),
|
||||
|
||||
'currency_id' => $this->integerFromValue((string)$object['currency_id']),
|
||||
'currency_code' => $this->clearString((string)$object['currency_code']),
|
||||
'currency_id' => $this->integerFromValue((string) $object['currency_id']),
|
||||
'currency_code' => $this->clearString((string) $object['currency_code']),
|
||||
|
||||
// location
|
||||
'latitude' => $this->floatFromValue((string) $object['latitude']),
|
||||
'longitude' => $this->floatFromValue((string) $object['longitude']),
|
||||
'zoom_level' => $this->integerFromValue((string) $object['zoom_level']),
|
||||
|
||||
// foreign currency info:
|
||||
'foreign_currency_id' => $this->integerFromValue((string)$object['foreign_currency_id']),
|
||||
'foreign_currency_code' => $this->clearString((string)$object['foreign_currency_code']),
|
||||
'foreign_currency_id' => $this->integerFromValue((string) $object['foreign_currency_id']),
|
||||
'foreign_currency_code' => $this->clearString((string) $object['foreign_currency_code']),
|
||||
|
||||
// amount and foreign amount. Cannot be 0.
|
||||
'amount' => $this->clearString((string)$object['amount']),
|
||||
'foreign_amount' => $this->clearString((string)$object['foreign_amount']),
|
||||
'amount' => $this->clearString((string) $object['amount']),
|
||||
'foreign_amount' => $this->clearString((string) $object['foreign_amount']),
|
||||
|
||||
// description.
|
||||
'description' => $this->clearString($object['description']),
|
||||
'description' => $this->clearString($object['description']),
|
||||
|
||||
// source of transaction. If everything is null, assume cash account.
|
||||
'source_id' => $this->integerFromValue((string)$object['source_id']),
|
||||
'source_name' => $this->clearString((string)$object['source_name']),
|
||||
'source_iban' => $this->clearIban((string)$object['source_iban']),
|
||||
'source_number' => $this->clearString((string)$object['source_number']),
|
||||
'source_bic' => $this->clearString((string)$object['source_bic']),
|
||||
'source_id' => $this->integerFromValue((string) $object['source_id']),
|
||||
'source_name' => $this->clearString((string) $object['source_name']),
|
||||
'source_iban' => $this->clearIban((string) $object['source_iban']),
|
||||
'source_number' => $this->clearString((string) $object['source_number']),
|
||||
'source_bic' => $this->clearString((string) $object['source_bic']),
|
||||
|
||||
// destination of transaction. If everything is null, assume cash account.
|
||||
'destination_id' => $this->integerFromValue((string)$object['destination_id']),
|
||||
'destination_name' => $this->clearString((string)$object['destination_name']),
|
||||
'destination_iban' => $this->clearIban((string)$object['destination_iban']),
|
||||
'destination_number' => $this->clearString((string)$object['destination_number']),
|
||||
'destination_bic' => $this->clearString((string)$object['destination_bic']),
|
||||
'destination_id' => $this->integerFromValue((string) $object['destination_id']),
|
||||
'destination_name' => $this->clearString((string) $object['destination_name']),
|
||||
'destination_iban' => $this->clearIban((string) $object['destination_iban']),
|
||||
'destination_number' => $this->clearString((string) $object['destination_number']),
|
||||
'destination_bic' => $this->clearString((string) $object['destination_bic']),
|
||||
|
||||
// budget info
|
||||
'budget_id' => $this->integerFromValue((string)$object['budget_id']),
|
||||
'budget_name' => $this->clearString((string)$object['budget_name']),
|
||||
'budget_id' => $this->integerFromValue((string) $object['budget_id']),
|
||||
'budget_name' => $this->clearString((string) $object['budget_name']),
|
||||
|
||||
// category info
|
||||
'category_id' => $this->integerFromValue((string)$object['category_id']),
|
||||
'category_name' => $this->clearString((string)$object['category_name']),
|
||||
'category_id' => $this->integerFromValue((string) $object['category_id']),
|
||||
'category_name' => $this->clearString((string) $object['category_name']),
|
||||
|
||||
// journal bill reference. Optional. Will only work for withdrawals
|
||||
'bill_id' => $this->integerFromValue((string)$object['bill_id']),
|
||||
'bill_name' => $this->clearString((string)$object['bill_name']),
|
||||
'bill_id' => $this->integerFromValue((string) $object['bill_id']),
|
||||
'bill_name' => $this->clearString((string) $object['bill_name']),
|
||||
|
||||
// piggy bank reference. Optional. Will only work for transfers
|
||||
'piggy_bank_id' => $this->integerFromValue((string)$object['piggy_bank_id']),
|
||||
'piggy_bank_name' => $this->clearString((string)$object['piggy_bank_name']),
|
||||
'piggy_bank_id' => $this->integerFromValue((string) $object['piggy_bank_id']),
|
||||
'piggy_bank_name' => $this->clearString((string) $object['piggy_bank_name']),
|
||||
|
||||
// some other interesting properties
|
||||
'reconciled' => $this->convertBoolean((string)$object['reconciled']),
|
||||
'notes' => $this->clearStringKeepNewlines((string)$object['notes']),
|
||||
'tags' => $this->arrayFromValue($object['tags']),
|
||||
'reconciled' => $this->convertBoolean((string) $object['reconciled']),
|
||||
'notes' => $this->clearStringKeepNewlines((string) $object['notes']),
|
||||
'tags' => $this->arrayFromValue($object['tags']),
|
||||
|
||||
// all custom fields:
|
||||
'internal_reference' => $this->clearString((string)$object['internal_reference']),
|
||||
'external_id' => $this->clearString((string)$object['external_id']),
|
||||
'original_source' => sprintf('ff3-v%s', config('firefly.version')),
|
||||
'recurrence_id' => $this->integerFromValue($object['recurrence_id']),
|
||||
'bunq_payment_id' => $this->clearString((string)$object['bunq_payment_id']),
|
||||
'external_url' => $this->clearString((string)$object['external_url']),
|
||||
'internal_reference' => $this->clearString((string) $object['internal_reference']),
|
||||
'external_id' => $this->clearString((string) $object['external_id']),
|
||||
'original_source' => sprintf('ff3-v%s', config('firefly.version')),
|
||||
'recurrence_id' => $this->integerFromValue($object['recurrence_id']),
|
||||
'bunq_payment_id' => $this->clearString((string) $object['bunq_payment_id']),
|
||||
'external_url' => $this->clearString((string) $object['external_url']),
|
||||
|
||||
'sepa_cc' => $this->clearString((string)$object['sepa_cc']),
|
||||
'sepa_ct_op' => $this->clearString((string)$object['sepa_ct_op']),
|
||||
'sepa_ct_id' => $this->clearString((string)$object['sepa_ct_id']),
|
||||
'sepa_db' => $this->clearString((string)$object['sepa_db']),
|
||||
'sepa_country' => $this->clearString((string)$object['sepa_country']),
|
||||
'sepa_ep' => $this->clearString((string)$object['sepa_ep']),
|
||||
'sepa_ci' => $this->clearString((string)$object['sepa_ci']),
|
||||
'sepa_batch_id' => $this->clearString((string)$object['sepa_batch_id']),
|
||||
'sepa_cc' => $this->clearString((string) $object['sepa_cc']),
|
||||
'sepa_ct_op' => $this->clearString((string) $object['sepa_ct_op']),
|
||||
'sepa_ct_id' => $this->clearString((string) $object['sepa_ct_id']),
|
||||
'sepa_db' => $this->clearString((string) $object['sepa_db']),
|
||||
'sepa_country' => $this->clearString((string) $object['sepa_country']),
|
||||
'sepa_ep' => $this->clearString((string) $object['sepa_ep']),
|
||||
'sepa_ci' => $this->clearString((string) $object['sepa_ci']),
|
||||
'sepa_batch_id' => $this->clearString((string) $object['sepa_batch_id']),
|
||||
// custom date fields. Must be Carbon objects. Presence is optional.
|
||||
'interest_date' => $this->dateFromValue($object['interest_date']),
|
||||
'book_date' => $this->dateFromValue($object['book_date']),
|
||||
'process_date' => $this->dateFromValue($object['process_date']),
|
||||
'due_date' => $this->dateFromValue($object['due_date']),
|
||||
'payment_date' => $this->dateFromValue($object['payment_date']),
|
||||
'invoice_date' => $this->dateFromValue($object['invoice_date']),
|
||||
'interest_date' => $this->dateFromValue($object['interest_date']),
|
||||
'book_date' => $this->dateFromValue($object['book_date']),
|
||||
'process_date' => $this->dateFromValue($object['process_date']),
|
||||
'due_date' => $this->dateFromValue($object['due_date']),
|
||||
'payment_date' => $this->dateFromValue($object['payment_date']),
|
||||
'invoice_date' => $this->dateFromValue($object['invoice_date']),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -171,6 +177,7 @@ class StoreRequest extends FormRequest
|
||||
{
|
||||
app('log')->debug('Collect rules of TransactionStoreRequest');
|
||||
$validProtocols = config('firefly.valid_url_protocols');
|
||||
$locationRules = Location::requestRules([]);
|
||||
|
||||
return [
|
||||
// basic fields for group:
|
||||
@@ -178,6 +185,11 @@ class StoreRequest extends FormRequest
|
||||
'error_if_duplicate_hash' => [new IsBoolean()],
|
||||
'apply_rules' => [new IsBoolean()],
|
||||
|
||||
// location rules
|
||||
'transactions.*.latitude' => $locationRules['latitude'],
|
||||
'transactions.*.longitude' => $locationRules['longitude'],
|
||||
'transactions.*.zoom_level' => $locationRules['zoom_level'],
|
||||
|
||||
// transaction rules (in array for splits):
|
||||
'transactions.*.type' => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation',
|
||||
'transactions.*.date' => ['required', new IsDateOrTime()],
|
||||
|
@@ -137,7 +137,7 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
foreach ($this->integerFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->integerFromValue((string)$transaction[$fieldName]);
|
||||
$current[$fieldName] = $this->integerFromValue((string) $transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
foreach ($this->stringFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->clearString((string)$transaction[$fieldName]);
|
||||
$current[$fieldName] = $this->clearString((string) $transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
foreach ($this->textareaFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->clearStringKeepNewlines((string)$transaction[$fieldName]); // keep newlines
|
||||
$current[$fieldName] = $this->clearStringKeepNewlines((string) $transaction[$fieldName]); // keep newlines
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,8 +183,8 @@ class UpdateRequest extends FormRequest
|
||||
foreach ($this->dateFields as $fieldName) {
|
||||
app('log')->debug(sprintf('Now at date field %s', $fieldName));
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
app('log')->debug(sprintf('New value: "%s"', (string)$transaction[$fieldName]));
|
||||
$current[$fieldName] = $this->dateFromValue((string)$transaction[$fieldName]);
|
||||
app('log')->debug(sprintf('New value: "%s"', (string) $transaction[$fieldName]));
|
||||
$current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
foreach ($this->booleanFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->convertBoolean((string)$transaction[$fieldName]);
|
||||
$current[$fieldName] = $this->convertBoolean((string) $transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ class UpdateRequest extends FormRequest
|
||||
$current[$fieldName] = sprintf('%.12f', $value);
|
||||
}
|
||||
if (!is_float($value)) {
|
||||
$current[$fieldName] = (string)$value;
|
||||
$current[$fieldName] = (string) $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -98,8 +98,8 @@ class StoreRequest extends FormRequest
|
||||
$journalRepos->setUser($user);
|
||||
|
||||
$data = $validator->getData();
|
||||
$inwardId = (int)($data['inward_id'] ?? 0);
|
||||
$outwardId = (int)($data['outward_id'] ?? 0);
|
||||
$inwardId = (int) ($data['inward_id'] ?? 0);
|
||||
$outwardId = (int) ($data['outward_id'] ?? 0);
|
||||
$inward = $journalRepos->find($inwardId);
|
||||
$outward = $journalRepos->find($outwardId);
|
||||
|
||||
|
@@ -100,8 +100,8 @@ class UpdateRequest extends FormRequest
|
||||
|
||||
$inwardId = $data['inward_id'] ?? $existing->source_id;
|
||||
$outwardId = $data['outward_id'] ?? $existing->destination_id;
|
||||
$inward = $journalRepos->find((int)$inwardId);
|
||||
$outward = $journalRepos->find((int)$outwardId);
|
||||
$inward = $journalRepos->find((int) $inwardId);
|
||||
$outward = $journalRepos->find((int) $outwardId);
|
||||
if (null === $inward) {
|
||||
$inward = $existing->source;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user