Compare commits

..

80 Commits

Author SHA1 Message Date
github-actions[bot]
60b0dc6279 Merge pull request #10680 from firefly-iii/release-1754046611
🤖 Automatically merge the PR into the develop branch.
2025-08-01 13:10:21 +02:00
JC5
883994de19 🤖 Auto commit for release 'develop' on 2025-08-01 2025-08-01 13:10:11 +02:00
Sander Dorigo
cfb86c683e Replace native with primary 2025-08-01 12:40:54 +02:00
Sander Dorigo
6278662014 Replace native with primary where possible 2025-08-01 12:31:01 +02:00
Sander Dorigo
65dcad6898 remove a quote 2025-08-01 07:42:45 +02:00
Sander Dorigo
8e7bcbdd7b Merge branch 'develop' of https://github.com/firefly-iii/firefly-iii into develop 2025-08-01 07:41:28 +02:00
James Cole
084ce02c21 Rename "native" to "primary". 2025-08-01 06:12:36 +02:00
James Cole
ea6addafe6 Rename references to native amounts 2025-07-31 20:55:30 +02:00
James Cole
da36d84b79 Rename "native" references to "primary" or "pc". 2025-07-31 20:47:20 +02:00
James Cole
d6d9f665c7 Rename references to "native". 2025-07-31 20:38:57 +02:00
James Cole
73d2621255 Remove v2 api 2025-07-31 20:36:16 +02:00
James Cole
4299ba033c Remove v2 transformers. 2025-07-31 20:36:06 +02:00
James Cole
6007687bcc Rename from "native" to "primary". 2025-07-31 20:35:44 +02:00
James Cole
6d3f2bd5e7 Rename many references from native to primary. 2025-07-31 20:24:19 +02:00
James Cole
210bd83bd4 Rename method. 2025-07-31 20:17:46 +02:00
James Cole
65a926874b Rename "native" to "primary". 2025-07-31 20:16:16 +02:00
James Cole
d0e7681e56 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-07-31 18:17:02 +02:00
James Cole
33bde854ec Add conversion 2025-07-31 18:16:54 +02:00
github-actions[bot]
da874c97f4 Merge pull request #10677 from firefly-iii/release-1753977340
🤖 Automatically merge the PR into the develop branch.
2025-07-31 17:55:52 +02:00
JC5
aa7ec95a59 🤖 Auto commit for release 'develop' on 2025-07-31 2025-07-31 17:55:40 +02:00
James Cole
4dd77303f7 Fix filtered list. 2025-07-31 17:51:07 +02:00
Sander Dorigo
166d4bd842 Add quote 2025-07-31 15:55:43 +02:00
github-actions[bot]
54bf56bbb0 Merge pull request #10676 from firefly-iii/release-1753963346
🤖 Automatically merge the PR into the develop branch.
2025-07-31 14:02:37 +02:00
JC5
3d8c6671f4 🤖 Auto commit for release 'develop' on 2025-07-31 2025-07-31 14:02:26 +02:00
Sander Dorigo
4e33de9c29 Fix missing filter 2025-07-31 13:54:12 +02:00
Sander Dorigo
27d46eb3fa Merge branch 'develop' of https://github.com/firefly-iii/firefly-iii into develop 2025-07-31 11:32:36 +02:00
Sander Dorigo
e1e7a2e497 Update file 2025-07-31 11:32:31 +02:00
github-actions[bot]
a476b4259c Merge pull request #10675 from firefly-iii/release-1753950988
🤖 Automatically merge the PR into the develop branch.
2025-07-31 10:36:37 +02:00
JC5
0c03ec5ddd 🤖 Auto commit for release 'develop' on 2025-07-31 2025-07-31 10:36:28 +02:00
Sander Dorigo
2d95b7f8ef Update bill transformers with enrichments 2025-07-31 10:00:05 +02:00
github-actions[bot]
34cc79ce4f Merge pull request #10674 from firefly-iii/release-1753940049
🤖 Automatically merge the PR into the develop branch.
2025-07-31 07:34:18 +02:00
JC5
6ff9943fe0 🤖 Auto commit for release 'develop' on 2025-07-31 2025-07-31 07:34:09 +02:00
James Cole
a0166b45e4 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop
# Conflicts:
#	app/Api/V1/Controllers/Models/Bill/ShowController.php
#	app/Support/JsonApi/Enrichments/SubscriptionEnrichment.php
#	app/Transformers/BillTransformer.php
2025-07-31 07:30:25 +02:00
James Cole
d27b035b20 Clean up transformer. 2025-07-31 07:28:25 +02:00
github-actions[bot]
f3b387fc22 Merge pull request #10673 from firefly-iii/release-1753936796
🤖 Automatically merge the PR into the develop branch.
2025-07-31 06:40:05 +02:00
JC5
03904ffcde 🤖 Auto commit for release 'develop' on 2025-07-31 2025-07-31 06:39:56 +02:00
James Cole
a7973190c2 Start improving bill overview. 2025-07-30 20:35:28 +02:00
James Cole
671ff95f22 Improved subscription overview 2025-07-30 18:57:32 +02:00
github-actions[bot]
01181ceea9 Merge pull request #10672 from firefly-iii/release-1753879077
🤖 Automatically merge the PR into the develop branch.
2025-07-30 14:38:08 +02:00
JC5
97643639d1 🤖 Auto commit for release 'develop' on 2025-07-30 2025-07-30 14:37:57 +02:00
James Cole
424783c47b Add convertToNative to cache key. 2025-07-30 14:33:26 +02:00
James Cole
ea0ced70b2 Clean up sankey. 2025-07-30 11:24:00 +02:00
James Cole
1a633e64ef Category chart will also convert. 2025-07-30 10:20:35 +02:00
James Cole
30da3f4399 Also include budget in currency conversion. 2025-07-30 09:59:52 +02:00
github-actions[bot]
6bdff95d87 Merge pull request #10671 from firefly-iii/release-1753858574
🤖 Automatically merge the PR into the develop branch.
2025-07-30 08:56:22 +02:00
JC5
895ae279d5 🤖 Auto commit for release 'develop' on 2025-07-30 2025-07-30 08:56:14 +02:00
James Cole
8b57f45963 Return the promise. 2025-07-30 08:37:19 +02:00
James Cole
a2d2b7edd3 Add warning to translations. 2025-07-30 07:27:00 +02:00
James Cole
3d65f00c6e Correct tag date and add warning. 2025-07-30 07:26:50 +02:00
James Cole
333004c4d9 Upgrade to font awesome 7, make sure chart includes currencies outside of limits. 2025-07-30 06:59:58 +02:00
James Cole
7451659824 Merge pull request #10661 from firefly-iii/dependabot/npm_and_yarn/develop/cross-env-10.0.0
Bump cross-env from 7.0.3 to 10.0.0
2025-07-28 20:44:31 +02:00
mergify[bot]
ec89c23ace Merge branch 'develop' into dependabot/npm_and_yarn/develop/cross-env-10.0.0 2025-07-28 05:08:38 +00:00
James Cole
92d07d346f Merge pull request #10660 from firefly-iii/dependabot/npm_and_yarn/develop/fortawesome/fontawesome-free-7.0.0
Bump @fortawesome/fontawesome-free from 6.7.2 to 7.0.0
2025-07-28 07:08:02 +02:00
mergify[bot]
a7ac894af2 Merge branch 'develop' into dependabot/npm_and_yarn/develop/cross-env-10.0.0 2025-07-28 04:39:49 +00:00
dependabot[bot]
20f89e3a7c Bump cross-env from 7.0.3 to 10.0.0
Bumps [cross-env](https://github.com/kentcdodds/cross-env) from 7.0.3 to 10.0.0.
- [Release notes](https://github.com/kentcdodds/cross-env/releases)
- [Changelog](https://github.com/kentcdodds/cross-env/blob/main/CHANGELOG.md)
- [Commits](https://github.com/kentcdodds/cross-env/compare/v7.0.3...v10.0.0)

---
updated-dependencies:
- dependency-name: cross-env
  dependency-version: 10.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-28 04:39:15 +00:00
mergify[bot]
5d2f11c3c7 Merge branch 'develop' into dependabot/npm_and_yarn/develop/fortawesome/fontawesome-free-7.0.0 2025-07-28 04:38:58 +00:00
dependabot[bot]
1eea79e431 Bump @fortawesome/fontawesome-free from 6.7.2 to 7.0.0
Bumps [@fortawesome/fontawesome-free](https://github.com/FortAwesome/Font-Awesome) from 6.7.2 to 7.0.0.
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/7.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/6.7.2...7.0.0)

---
updated-dependencies:
- dependency-name: "@fortawesome/fontawesome-free"
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-28 04:38:22 +00:00
James Cole
1aaaac67ca Merge pull request #10659 from firefly-iii/dependabot/composer/develop/phpstan/phpstan-2.1.20
Bump phpstan/phpstan from 2.1.19 to 2.1.20
2025-07-28 06:38:11 +02:00
mergify[bot]
1eb86639c9 Merge branch 'develop' into dependabot/composer/develop/phpstan/phpstan-2.1.20 2025-07-28 04:31:47 +00:00
dependabot[bot]
28b911c4ee Bump phpstan/phpstan from 2.1.19 to 2.1.20
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 2.1.19 to 2.1.20.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/2.1.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/2.1.19...2.1.20)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-version: 2.1.20
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-28 04:31:06 +00:00
github-actions[bot]
c525c70ec0 Merge pull request #10657 from firefly-iii/release-1753673814
🤖 Automatically merge the PR into the develop branch.
2025-07-28 05:37:03 +02:00
JC5
1f7d6e218b 🤖 Auto commit for release 'develop' on 2025-07-28 2025-07-28 05:36:54 +02:00
James Cole
a69b6d9ce2 Respond to "convert to native". 2025-07-27 20:45:08 +02:00
James Cole
28b2ddde18 Account chart can do live update 2025-07-27 07:36:23 +02:00
James Cole
a16cc73c77 Sync "convert to native" 2025-07-26 19:17:26 +02:00
James Cole
46395e350a Improved budget chart. 2025-07-26 06:47:21 +02:00
Sander Dorigo
f62e49090c Merge branch 'main' into develop 2025-07-25 11:18:24 +02:00
James Cole
af3b40a314 Delete .github/workflows/sonarcloud.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2025-07-25 11:10:05 +02:00
James Cole
c3cea0fa9e Update cleanup.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2025-07-25 11:09:55 +02:00
James Cole
6cbdb2ce70 Update index.js
Fix thnigie

Signed-off-by: James Cole <james@firefly-iii.org>
2025-07-25 10:56:42 +02:00
James Cole
b78460100d Fix #10646 2025-07-25 05:44:03 +02:00
github-actions[bot]
bf6e1cb0e1 Merge pull request #10642 from firefly-iii/release-1753333227
🤖 Automatically merge the PR into the develop branch.
2025-07-24 07:00:35 +02:00
JC5
6a53f5031c 🤖 Auto commit for release 'develop' on 2025-07-24 2025-07-24 07:00:27 +02:00
James Cole
ae15ec01e8 Merge branch 'main' into develop 2025-07-24 06:56:07 +02:00
James Cole
fe3c7c47c4 Filter list of bills. 2025-07-24 06:55:53 +02:00
James Cole
68b934010c Merge pull request #10640 from firefly-iii/dependabot/npm_and_yarn/npm_and_yarn-25988072ba
Bump the npm_and_yarn group across 1 directory with 2 updates
2025-07-23 19:37:09 +02:00
dependabot[bot]
22852bd238 Bump the npm_and_yarn group across 1 directory with 2 updates
Bumps the npm_and_yarn group with 1 update in the / directory: [axios](https://github.com/axios/axios).


Updates `axios` from 1.10.0 to 1.11.0
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.10.0...v1.11.0)

Updates `form-data` from 4.0.3 to 4.0.4
- [Release notes](https://github.com/form-data/form-data/releases)
- [Changelog](https://github.com/form-data/form-data/blob/master/CHANGELOG.md)
- [Commits](https://github.com/form-data/form-data/compare/v4.0.3...v4.0.4)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.11.0
  dependency-type: direct:development
  dependency-group: npm_and_yarn
- dependency-name: form-data
  dependency-version: 4.0.4
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-23 16:51:30 +00:00
github-actions[bot]
5b3b1804f3 Merge pull request #10638 from firefly-iii/release-1753247140
🤖 Automatically merge the PR into the develop branch.
2025-07-23 07:05:49 +02:00
JC5
f2588eb343 🤖 Auto commit for release 'develop' on 2025-07-23 2025-07-23 07:05:40 +02:00
James Cole
64a643ceec Expand balances. 2025-07-23 07:01:10 +02:00
321 changed files with 3710 additions and 11122 deletions

View File

@@ -406,20 +406,20 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.84.0",
"version": "v3.85.1",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "38dad0767bf2a9b516b976852200ae722fe984ca"
"reference": "2fb6d7f6c3398dca5786a1635b27405d73a417ba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/38dad0767bf2a9b516b976852200ae722fe984ca",
"reference": "38dad0767bf2a9b516b976852200ae722fe984ca",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/2fb6d7f6c3398dca5786a1635b27405d73a417ba",
"reference": "2fb6d7f6c3398dca5786a1635b27405d73a417ba",
"shasum": ""
},
"require": {
"clue/ndjson-react": "^1.0",
"clue/ndjson-react": "^1.3",
"composer/semver": "^3.4",
"composer/xdebug-handler": "^3.0.5",
"ext-filter": "*",
@@ -429,12 +429,12 @@
"fidry/cpu-core-counter": "^1.2",
"php": "^7.4 || ^8.0",
"react/child-process": "^0.6.6",
"react/event-loop": "^1.0",
"react/promise": "^2.11 || ^3.0",
"react/socket": "^1.0",
"react/stream": "^1.0",
"react/event-loop": "^1.5",
"react/promise": "^3.2",
"react/socket": "^1.16",
"react/stream": "^1.4",
"sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0",
"symfony/console": "^5.4.45 || ^6.4.13 || ^7.0",
"symfony/console": "^5.4.47 || ^6.4.13 || ^7.0",
"symfony/event-dispatcher": "^5.4.45 || ^6.4.13 || ^7.0",
"symfony/filesystem": "^5.4.45 || ^6.4.13 || ^7.0",
"symfony/finder": "^5.4.45 || ^6.4.17 || ^7.0",
@@ -499,7 +499,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.84.0"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.85.1"
},
"funding": [
{
@@ -507,7 +507,7 @@
"type": "github"
}
],
"time": "2025-07-15T18:21:57+00:00"
"time": "2025-07-29T22:22:50+00:00"
},
{
"name": "psr/container",
@@ -1257,16 +1257,16 @@
},
{
"name": "symfony/console",
"version": "v7.3.1",
"version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "9e27aecde8f506ba0fd1d9989620c04a87697101"
"reference": "5f360ebc65c55265a74d23d7fe27f957870158a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/9e27aecde8f506ba0fd1d9989620c04a87697101",
"reference": "9e27aecde8f506ba0fd1d9989620c04a87697101",
"url": "https://api.github.com/repos/symfony/console/zipball/5f360ebc65c55265a74d23d7fe27f957870158a1",
"reference": "5f360ebc65c55265a74d23d7fe27f957870158a1",
"shasum": ""
},
"require": {
@@ -1331,7 +1331,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v7.3.1"
"source": "https://github.com/symfony/console/tree/v7.3.2"
},
"funding": [
{
@@ -1342,12 +1342,16 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-06-27T19:55:54+00:00"
"time": "2025-07-30T17:13:41+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -1574,16 +1578,16 @@
},
{
"name": "symfony/filesystem",
"version": "v7.3.0",
"version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb"
"reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
"reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd",
"reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd",
"shasum": ""
},
"require": {
@@ -1620,7 +1624,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v7.3.0"
"source": "https://github.com/symfony/filesystem/tree/v7.3.2"
},
"funding": [
{
@@ -1631,25 +1635,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-10-25T15:15:23+00:00"
"time": "2025-07-07T08:17:47+00:00"
},
{
"name": "symfony/finder",
"version": "v7.3.0",
"version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d"
"reference": "2a6614966ba1074fa93dae0bc804227422df4dfe"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/ec2344cf77a48253bbca6939aa3d2477773ea63d",
"reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d",
"url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe",
"reference": "2a6614966ba1074fa93dae0bc804227422df4dfe",
"shasum": ""
},
"require": {
@@ -1684,7 +1692,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v7.3.0"
"source": "https://github.com/symfony/finder/tree/v7.3.2"
},
"funding": [
{
@@ -1695,25 +1703,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-12-30T19:00:26+00:00"
"time": "2025-07-15T13:41:35+00:00"
},
{
"name": "symfony/options-resolver",
"version": "v7.3.0",
"version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
"reference": "afb9a8038025e5dbc657378bfab9198d75f10fca"
"reference": "119bcf13e67dbd188e5dbc74228b1686f66acd37"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/afb9a8038025e5dbc657378bfab9198d75f10fca",
"reference": "afb9a8038025e5dbc657378bfab9198d75f10fca",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/119bcf13e67dbd188e5dbc74228b1686f66acd37",
"reference": "119bcf13e67dbd188e5dbc74228b1686f66acd37",
"shasum": ""
},
"require": {
@@ -1751,7 +1763,7 @@
"options"
],
"support": {
"source": "https://github.com/symfony/options-resolver/tree/v7.3.0"
"source": "https://github.com/symfony/options-resolver/tree/v7.3.2"
},
"funding": [
{
@@ -1762,12 +1774,16 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-04-04T13:12:05+00:00"
"time": "2025-07-15T11:36:08+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -2452,16 +2468,16 @@
},
{
"name": "symfony/string",
"version": "v7.3.0",
"version": "v7.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125"
"reference": "42f505aff654e62ac7ac2ce21033818297ca89ca"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125",
"reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125",
"url": "https://api.github.com/repos/symfony/string/zipball/42f505aff654e62ac7ac2ce21033818297ca89ca",
"reference": "42f505aff654e62ac7ac2ce21033818297ca89ca",
"shasum": ""
},
"require": {
@@ -2519,7 +2535,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v7.3.0"
"source": "https://github.com/symfony/string/tree/v7.3.2"
},
"funding": [
{
@@ -2530,12 +2546,16 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-04-20T20:19:01+00:00"
"time": "2025-07-10T08:47:49+00:00"
}
],
"packages-dev": [],

View File

@@ -66,7 +66,6 @@ jobs:
'label-actions.yml',
'lock.yml',
'release.yml',
'sonarcloud.yml',
'stale.yml'
]

View File

@@ -93,14 +93,14 @@ class AccountController extends Controller
/** @var Account $account */
foreach ($result as $account) {
$nameWithBalance = $account->name;
$currency = $this->repository->getAccountCurrency($account) ?? $this->nativeCurrency;
$currency = $this->repository->getAccountCurrency($account) ?? $this->primaryCurrency;
$useCurrency = $currency;
if (in_array($account->accountType->type, $this->balanceTypes, true)) {
// this one is correct.
Log::debug(sprintf('accounts: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
$balance = Steam::finalAccountBalance($account, $date);
$key = $this->convertToNative && $currency->id !== $this->nativeCurrency->id ? 'native_balance' : 'balance';
$useCurrency = $this->convertToNative && $currency->id !== $this->nativeCurrency->id ? $this->nativeCurrency : $currency;
$key = $this->convertToPrimary && $currency->id !== $this->primaryCurrency->id ? 'pc_balance' : 'balance';
$useCurrency = $this->convertToPrimary && $currency->id !== $this->primaryCurrency->id ? $this->primaryCurrency : $currency;
$amount = $balance[$key] ?? '0';
$nameWithBalance = sprintf(
'%s (%s)',

View File

@@ -24,16 +24,16 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Chart;
use FireflyIII\Exceptions\ValidationException;
use FireflyIII\Models\TransactionCurrency;
use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Chart\ChartRequest;
use FireflyIII\Api\V1\Requests\Data\DateRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Exceptions\ValidationException;
use FireflyIII\Models\Account;
use FireflyIII\Models\Preference;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Chart\ChartData;
use FireflyIII\Support\Facades\Preferences;
@@ -42,6 +42,7 @@ use FireflyIII\Support\Http\Api\ApiSupport;
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
/**
* Class AccountController
@@ -86,10 +87,12 @@ class AccountController extends Controller
// move date to end of day
$queryParameters['start']->startOfDay();
$queryParameters['end']->endOfDay();
Log::debug(sprintf('dashboard(), convert to primary: %s', var_export($this->convertToPrimary, true)));
// loop each account, and collect info:
/** @var Account $account */
foreach ($accounts as $account) {
Log::debug(sprintf('Account #%d ("%s")', $account->id, $account->name));
$this->renderAccountData($queryParameters, $account);
}
@@ -101,7 +104,14 @@ class AccountController extends Controller
*/
private function renderAccountData(array $params, Account $account): void
{
Log::debug(sprintf('Now in %s(array, #%d)', __METHOD__, $account->id));
$currency = $this->repository->getAccountCurrency($account);
$currentStart = clone $params['start'];
$range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToPrimary);
$previous = array_values($range)[0]['balance'];
$pcPrevious = null;
if (!$currency instanceof TransactionCurrency) {
$currency = $this->default;
}
@@ -109,7 +119,7 @@ class AccountController extends Controller
'label' => $account->name,
// the currency that belongs to the account.
'currency_id' => (string) $currency->id,
'currency_id' => (string)$currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
@@ -121,18 +131,33 @@ class AccountController extends Controller
'period' => '1D',
'entries' => [],
];
$currentStart = clone $params['start'];
$range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative);
if ($this->convertToPrimary) {
$currentSet['pc_entries'] = [];
$currentSet['primary_currency_id'] = (string)$this->primaryCurrency->id;
$currentSet['primary_currency_code'] = $this->primaryCurrency->code;
$currentSet['primary_currency_symbol'] = $this->primaryCurrency->symbol;
$currentSet['primary_currency_decimal_places'] = $this->primaryCurrency->decimal_places;
$pcPrevious = array_values($range)[0]['pc_balance'];
}
$previous = array_values($range)[0]['balance'];
while ($currentStart <= $params['end']) {
$format = $currentStart->format('Y-m-d');
$label = $currentStart->toAtomString();
$balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous;
$previous = $balance;
$currentSet['entries'][$label] = $balance;
// do the same for the primary currency balance, if relevant:
$pcBalance = null;
if ($this->convertToPrimary) {
$pcBalance = array_key_exists($format, $range) ? $range[$format]['pc_balance'] : $pcPrevious;
$pcPrevious = $pcBalance;
$currentSet['pc_entries'][$label] = $pcBalance;
}
$currentStart->addDay();
$currentSet['entries'][$label] = $balance;
}
$this->chartData->add($currentSet);
}
@@ -146,19 +171,84 @@ class AccountController extends Controller
public function overview(DateRequest $request): JsonResponse
{
// parameters for chart:
$dates = $request->getAll();
$dates = $request->getAll();
/** @var Carbon $start */
$start = $dates['start'];
$start = $dates['start'];
/** @var Carbon $end */
$end = $dates['end'];
$end = $dates['end'];
// set dates to end of day + start of day:
$start->startOfDay();
$end->endOfDay();
// user's preferences
$frontPageIds = $this->getFrontPageAccountIds();
$accounts = $this->repository->getAccountsById($frontPageIds);
$chartData = [];
/** @var Account $account */
foreach ($accounts as $account) {
Log::debug(sprintf('Rendering chart data for account %s (%d)', $account->name, $account->id));
$currency = $this->repository->getAccountCurrency($account) ?? $this->primaryCurrency;
$currentStart = clone $start;
$range = Steam::finalAccountBalanceInRange($account, $start, clone $end, $this->convertToPrimary);
$previous = array_values($range)[0]['balance'];
$pcPrevious = null;
$currentSet = [
'label' => $account->name,
'currency_id' => (string)$currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'start_date' => $start->toAtomString(),
'end_date' => $end->toAtomString(),
'type' => 'line', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [],
];
// add "pc_entries" if convertToPrimary is true:
if ($this->convertToPrimary) {
$currentSet['pc_entries'] = [];
$currentSet['primary_currency_id'] = (string)$this->primaryCurrency->id;
$currentSet['primary_currency_code'] = $this->primaryCurrency->code;
$currentSet['primary_currency_symbol'] = $this->primaryCurrency->symbol;
$currentSet['primary_currency_decimal_places'] = $this->primaryCurrency->decimal_places;
$pcPrevious = array_values($range)[0]['pc_balance'];
}
// also get the primary balance if convertToPrimary is true:
while ($currentStart <= $end) {
$format = $currentStart->format('Y-m-d');
$label = $currentStart->toAtomString();
// balance is based on "balance" from the $range variable.
$balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous;
$previous = $balance;
$currentSet['entries'][$label] = $balance;
// do the same for the primary balance, if relevant:
$pcBalance = null;
if ($this->convertToPrimary) {
$pcBalance = array_key_exists($format, $range) ? $range[$format]['pc_balance'] : $pcPrevious;
$pcPrevious = $pcBalance;
$currentSet['pc_entries'][$label] = $pcBalance;
}
$currentStart->addDay();
}
$chartData[] = $currentSet;
}
return response()->json($chartData);
}
private function getFrontPageAccountIds(): array
{
$defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
/** @var Preference $frontpage */
@@ -169,41 +259,6 @@ class AccountController extends Controller
$frontpage->save();
}
// get accounts:
$accounts = $this->repository->getAccountsById($frontpage->data);
$chartData = [];
/** @var Account $account */
foreach ($accounts as $account) {
$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_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'start_date' => $start->toAtomString(),
'end_date' => $end->toAtomString(),
'type' => 'line', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [],
];
// TODO this code is also present in the V2 chart account controller so this method is due to be deprecated.
$currentStart = clone $start;
$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][$field] : $previous;
$previous = $balance;
$currentStart->addDay();
$currentSet['entries'][$label] = $balance;
}
$chartData[] = $currentSet;
}
return response()->json($chartData);
return $frontpage->data ?? $defaultSet;
}
}

View File

@@ -36,6 +36,7 @@ use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
@@ -77,6 +78,8 @@ class BudgetController extends Controller
/**
* TODO see autocomplete/accountcontroller
*
* @throws FireflyException
*/
public function dashboard(DateRequest $request): JsonResponse
{
@@ -107,23 +110,41 @@ class BudgetController extends Controller
private function processBudget(Budget $budget, Carbon $start, Carbon $end): array
{
// get all limits:
$limits = $this->blRepository->getBudgetLimits($budget, $start, $end);
$rows = [];
$limits = $this->blRepository->getBudgetLimits($budget, $start, $end);
$rows = [];
$spent = $this->opsRepository->listExpenses($start, $end, null, new Collection([$budget]));
$expenses = $this->processExpenses($budget->id, $spent, $start, $end);
/**
* @var int $currencyId
* @var array $row
*/
foreach ($expenses as $currencyId => $row) {
// budgeted, left and overspent are now 0.
$limit = $this->filterLimit($currencyId, $limits);
if (null !== $limit) {
$row['budgeted'] = $limit->amount;
$row['left'] = bcsub($row['budgeted'], bcmul($row['spent'], '-1'));
$row['overspent'] = bcmul($row['left'], '-1');
$row['left'] = 1 === bccomp($row['left'], '0') ? $row['left'] : '0';
$row['overspent'] = 1 === bccomp($row['overspent'], '0') ? $row['overspent'] : '0';
}
$rows[] = $row;
}
// if no limits
if (0 === $limits->count()) {
// return as a single item in an array
$rows = $this->noBudgetLimits($budget, $start, $end);
}
if ($limits->count() > 0) {
$rows = $this->budgetLimits($budget, $limits);
}
// if (0 === $limits->count()) {
// return as a single item in an array
// $rows = $this->noBudgetLimits($budget, $start, $end);
// }
// is always an array
$return = [];
$return = [];
foreach ($rows as $row) {
$current = [
'label' => $budget->name,
'currency_id' => (string) $row['currency_id'],
'currency_id' => (string)$row['currency_id'],
'currency_code' => $row['currency_code'],
'currency_name' => $row['currency_name'],
'currency_decimal_places' => $row['currency_decimal_places'],
@@ -131,6 +152,7 @@ class BudgetController extends Controller
'start' => $row['start'],
'end' => $row['end'],
'entries' => [
'budgeted' => $row['budgeted'],
'spent' => $row['spent'],
'left' => $row['left'],
'overspent' => $row['overspent'],
@@ -159,11 +181,9 @@ class BudgetController extends Controller
* Shared between the "noBudgetLimits" function and "processLimit". Will take a single set of expenses and return
* its info.
*
* @param array<int, array<int, string>> $array
*
* @throws FireflyException
*/
private function processExpenses(int $budgetId, array $array, Carbon $start, Carbon $end): array
private function processExpenses(int $budgetId, array $spent, Carbon $start, Carbon $end): array
{
$return = [];
@@ -174,16 +194,17 @@ class BudgetController extends Controller
* @var int $currencyId
* @var array $block
*/
foreach ($array as $currencyId => $block) {
foreach ($spent as $currencyId => $block) {
$this->currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
$return[$currencyId] ??= [
'currency_id' => (string) $currencyId,
'currency_id' => (string)$currencyId,
'currency_code' => $block['currency_code'],
'currency_name' => $block['currency_name'],
'currency_symbol' => $block['currency_symbol'],
'currency_decimal_places' => (int) $block['currency_decimal_places'],
'currency_decimal_places' => (int)$block['currency_decimal_places'],
'start' => $start->toAtomString(),
'end' => $end->toAtomString(),
'budgeted' => '0',
'spent' => '0',
'left' => '0',
'overspent' => '0',
@@ -193,7 +214,7 @@ class BudgetController extends Controller
// var_dump($return);
/** @var array $journal */
foreach ($currentBudgetArray['transaction_journals'] as $journal) {
$return[$currencyId]['spent'] = bcadd($return[$currencyId]['spent'], (string) $journal['amount']);
$return[$currencyId]['spent'] = bcadd($return[$currencyId]['spent'], (string)$journal['amount']);
}
}
@@ -240,16 +261,52 @@ class BudgetController extends Controller
$filtered = array_filter($spent, fn ($entry) => $entry['currency_id'] === $limitCurrencyId);
$result = $this->processExpenses($budget->id, $filtered, $limit->start_date, $end);
if (1 === count($result)) {
$compare = bccomp($limit->amount, (string) app('steam')->positive($result[$limitCurrencyId]['spent']));
$compare = bccomp($limit->amount, (string)app('steam')->positive($result[$limitCurrencyId]['spent']));
$result[$limitCurrencyId]['budgeted'] = $limit->amount;
if (1 === $compare) {
// convert this amount into the native currency:
$result[$limitCurrencyId]['left'] = bcadd($limit->amount, (string) $result[$limitCurrencyId]['spent']);
// convert this amount into the primary currency:
$result[$limitCurrencyId]['left'] = bcadd($limit->amount, (string)$result[$limitCurrencyId]['spent']);
}
if ($compare <= 0) {
$result[$limitCurrencyId]['overspent'] = app('steam')->positive(bcadd($limit->amount, (string) $result[$limitCurrencyId]['spent']));
$result[$limitCurrencyId]['overspent'] = app('steam')->positive(bcadd($limit->amount, (string)$result[$limitCurrencyId]['spent']));
}
}
return $result;
}
private function filterLimit(int $currencyId, Collection $limits): ?BudgetLimit
{
$amount = '0';
$limit = null;
$converter = new ExchangeRateConverter();
/** @var BudgetLimit $current */
foreach ($limits as $current) {
if (true === $this->convertToPrimary) {
if ($current->transaction_currency_id === $this->primaryCurrency->id) {
// simply add it.
$amount = bcadd($amount, (string)$current->amount);
Log::debug(sprintf('Set amount in limit to %s', $amount));
}
if ($current->transaction_currency_id !== $this->primaryCurrency->id) {
// convert and then add it.
$converted = $converter->convert($current->transactionCurrency, $this->primaryCurrency, $limit->start_date, $limit->amount);
$amount = bcadd($amount, $converted);
Log::debug(sprintf('Budgeted in limit #%d: %s %s, converted to %s %s', $current->id, $current->transactionCurrency->code, $current->amount, $this->primaryCurrency->code, $converted));
Log::debug(sprintf('Set amount in limit to %s', $amount));
}
}
if ($current->transaction_currency_id === $currencyId) {
$limit = $current;
}
}
if (null !== $limit && true === $this->convertToPrimary) {
// convert and add all amounts.
$limit->amount = app('steam')->positive($amount);
Log::debug(sprintf('Final amount in limit with converted amount %s', $limit->amount));
}
return $limit;
}
}

View File

@@ -25,17 +25,20 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
/**
* Class BudgetController
@@ -45,6 +48,8 @@ class CategoryController extends Controller
use CleansChartData;
use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
private AccountRepositoryInterface $accountRepos;
private CurrencyRepositoryInterface $currencyRepos;
@@ -79,9 +84,10 @@ class CategoryController extends Controller
/** @var Carbon $end */
$end = $this->parameters->get('end');
$accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]);
$accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value]);
$currencies = [];
$return = [];
$converter = new ExchangeRateConverter();
// get journals for entire period:
/** @var GroupCollectorInterface $collector */
@@ -93,20 +99,40 @@ class CategoryController extends Controller
/** @var array $journal */
foreach ($journals as $journal) {
$currencyId = (int) $journal['currency_id'];
$currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId);
$currencies[$currencyId] = $currency;
$categoryName = $journal['category_name'] ?? (string) trans('firefly.no_category');
$amount = app('steam')->positive($journal['amount']);
$key = sprintf('%s-%s', $categoryName, $currency->code);
// find journal:
$journalCurrencyId = (int)$journal['currency_id'];
$currency = $currencies[$journalCurrencyId] ?? $this->currencyRepos->find($journalCurrencyId);
$currencies[$journalCurrencyId] = $currency;
$currencyId = (int)$currency->id;
$currencyName = (string)$currency->name;
$currencyCode = (string)$currency->code;
$currencySymbol = (string)$currency->symbol;
$currencyDecimalPlaces = (int)$currency->decimal_places;
$amount = app('steam')->positive($journal['amount']);
// overrule if necessary:
if ($this->convertToPrimary && $journalCurrencyId !== $this->primaryCurrency->id) {
$currencyId = (int)$this->primaryCurrency->id;
$currencyName = (string)$this->primaryCurrency->name;
$currencyCode = (string)$this->primaryCurrency->code;
$currencySymbol = (string)$this->primaryCurrency->symbol;
$currencyDecimalPlaces = (int)$this->primaryCurrency->decimal_places;
$convertedAmount = $converter->convert($currency, $this->primaryCurrency, $journal['date'], $amount);
Log::debug(sprintf('Converted %s %s to %s %s', $journal['currency_code'], $amount, $this->primaryCurrency->code, $convertedAmount));
$amount = $convertedAmount;
}
$categoryName = $journal['category_name'] ?? (string)trans('firefly.no_category');
$key = sprintf('%s-%s', $categoryName, $currencyCode);
// create arrays
$return[$key] ??= [
'label' => $categoryName,
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_name' => $currency->name,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'currency_id' => (string)$currencyId,
'currency_code' => $currencyCode,
'currency_name' => $currencyName,
'currency_symbol' => $currencySymbol,
'currency_decimal_places' => $currencyDecimalPlaces,
'period' => null,
'start' => $start->toAtomString(),
'end' => $end->toAtomString(),
@@ -114,12 +140,12 @@ class CategoryController extends Controller
];
// add monies
$return[$key]['amount'] = bcadd($return[$key]['amount'], (string) $amount);
$return[$key]['amount'] = bcadd($return[$key]['amount'], (string)$amount);
}
$return = array_values($return);
// order by amount
usort($return, static fn (array $a, array $b) => (float) $a['amount'] < (float) $b['amount'] ? 1 : -1);
usort($return, static fn (array $a, array $b) => (float)$a['amount'] < (float)$b['amount'] ? 1 : -1);
return response()->json($this->clean($return));
}

View File

@@ -62,14 +62,14 @@ abstract class Controller extends BaseController
use ValidatesRequests;
use ValidatesUserGroupTrait;
protected const string CONTENT_TYPE = 'application/vnd.api+json';
protected const string JSON_CONTENT_TYPE = 'application/json';
protected array $accepts = ['application/json', 'application/vnd.api+json'];
protected const string CONTENT_TYPE = 'application/vnd.api+json';
protected const string JSON_CONTENT_TYPE = 'application/json';
protected array $accepts = ['application/json', 'application/vnd.api+json'];
/** @var array<int, string> */
protected array $allowedSort;
protected bool $convertToNative = false;
protected TransactionCurrency $nativeCurrency;
protected bool $convertToPrimary = false;
protected TransactionCurrency $primaryCurrency;
protected ParameterBag $parameters;
/**
@@ -83,9 +83,9 @@ abstract class Controller extends BaseController
function ($request, $next) {
$this->parameters = $this->getParameters();
if (auth()->check()) {
$language = Steam::getLanguage();
$this->convertToNative = Amount::convertToNative();
$this->nativeCurrency = Amount::getNativeCurrency();
$language = Steam::getLanguage();
$this->convertToPrimary = Amount::convertToPrimary();
$this->primaryCurrency = Amount::getPrimaryCurrency();
app()->setLocale($language);
}

View File

@@ -65,13 +65,13 @@ class BillController extends Controller
*/
public function bill(GenericRequest $request): JsonResponse
{
$accounts = $request->getAssetAccounts();
$bills = $request->getBills();
$start = $request->getStart();
$end = $request->getEnd();
$convertToNative = Amount::convertToNative();
$default = Amount::getNativeCurrency();
$response = [];
$accounts = $request->getAssetAccounts();
$bills = $request->getBills();
$start = $request->getStart();
$end = $request->getEnd();
$convertToPrimary = Amount::convertToPrimary();
$primary = Amount::getPrimaryCurrency();
$response = [];
// get all bills:
if (0 === $bills->count()) {
@@ -79,25 +79,25 @@ 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'];
$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 the primary amount if the user wants to convert to primary currency
if ($convertToPrimary && $currencyId !== $primary->id) {
$currencyId = $primary->id;
$currencyCode = $primary->code;
$field = 'pc_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']) {
if ($convertToPrimary && $journal['currency_id'] !== $primary->id && $primary->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'));
@@ -129,33 +129,33 @@ class BillController extends Controller
*/
public function noBill(GenericRequest $request): JsonResponse
{
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$convertToNative = Amount::convertToNative();
$default = Amount::getNativeCurrency();
$response = [];
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$convertToPrimary = Amount::convertToPrimary();
$primary = Amount::getPrimaryCurrency();
$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'];
$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 the primary amount if the user wants to convert to primary currency
if ($convertToPrimary && $currencyId !== $primary->id) {
$currencyId = $primary->id;
$currencyCode = $primary->code;
$field = 'pc_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']) {
if ($convertToPrimary && $journal['currency_id'] !== $primary->id && $primary->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'));

View File

@@ -43,35 +43,35 @@ class PeriodController extends Controller
*/
public function total(GenericRequest $request): JsonResponse
{
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToNative = Amount::convertToNative();
$default = Amount::getNativeCurrency();
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToPrimary = Amount::convertToPrimary();
$primary = Amount::getPrimaryCurrency();
// 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) {
// 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) {
if ($convertToPrimary) {
$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 ($primary->id !== (int) $journal['currency_id'] && $primary->id !== (int) $journal['foreign_currency_id']) {
$currencyId = $primary->id;
$currencyCode = $primary->code;
}
if ($default->id !== (int) $journal['currency_id'] && $default->id === (int) $journal['foreign_currency_id']) {
if ($primary->id !== (int) $journal['currency_id'] && $primary->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) {
if (!$convertToPrimary) {
// ignore the amount in foreign currency.
Log::debug(sprintf('[b] Add amount %s %s', $currencyCode, $journal['amount']));
$amount = $journal['amount'];

View File

@@ -64,38 +64,38 @@ class TagController extends Controller
*/
public function noTag(GenericRequest $request): JsonResponse
{
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToNative = Amount::convertToNative();
$default = Amount::getNativeCurrency();
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToPrimary = Amount::convertToPrimary();
$primary = Amount::getPrimaryCurrency();
// 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) {
// 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) {
if ($convertToPrimary) {
$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 ($primary->id !== (int) $journal['currency_id'] && $primary->id !== (int) $journal['foreign_currency_id']) {
$currencyId = $primary->id;
$currencyCode = $primary->code;
}
if ($default->id !== (int) $journal['currency_id'] && $default->id === (int) $journal['foreign_currency_id']) {
if ($primary->id !== (int) $journal['currency_id'] && $primary->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) {
if (!$convertToPrimary) {
// ignore the amount in foreign currency.
Log::debug(sprintf('[b] Add amount %s %s', $currencyCode, $journal['amount']));
$amount = $journal['amount'];

View File

@@ -42,30 +42,30 @@ class PeriodController extends Controller
*/
public function total(GenericRequest $request): JsonResponse
{
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToNative = Amount::convertToNative();
$default = Amount::getNativeCurrency();
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToPrimary = Amount::convertToPrimary();
$primary = Amount::getPrimaryCurrency();
// 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) {
// currency
$currencyId = $journal['currency_id'];
$currencyCode = $journal['currency_code'];
$field = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount';
$field = $convertToPrimary && $currencyId !== $primary->id ? 'pc_amount' : 'amount';
// perhaps use default currency instead?
if ($convertToNative && $journal['currency_id'] !== $default->id) {
$currencyId = $default->id;
$currencyCode = $default->code;
if ($convertToPrimary && $journal['currency_id'] !== $primary->id) {
$currencyId = $primary->id;
$currencyCode = $primary->code;
}
// use foreign amount when the foreign currency IS the default currency.
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
if ($convertToPrimary && $journal['currency_id'] !== $primary->id && $primary->id === $journal['foreign_currency_id']) {
$field = 'foreign_amount';
}

View File

@@ -64,33 +64,33 @@ class TagController extends Controller
*/
public function noTag(GenericRequest $request): JsonResponse
{
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToNative = Amount::convertToNative();
$default = Amount::getNativeCurrency();
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToPrimary = Amount::convertToPrimary();
$primary = Amount::getPrimaryCurrency();
// 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) {
// currency
$currencyId = $journal['currency_id'];
$currencyCode = $journal['currency_code'];
$field = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount';
$field = $convertToPrimary && $currencyId !== $primary->id ? 'pc_amount' : 'amount';
// perhaps use default currency instead?
if ($convertToNative && $journal['currency_id'] !== $default->id) {
$currencyId = $default->id;
$currencyCode = $default->code;
if ($convertToPrimary && $journal['currency_id'] !== $primary->id) {
$currencyId = $primary->id;
$currencyCode = $primary->code;
}
// use foreign amount when the foreign currency IS the default currency.
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
if ($convertToPrimary && $journal['currency_id'] !== $primary->id && $primary->id === $journal['foreign_currency_id']) {
$field = 'foreign_amount';
}

View File

@@ -42,30 +42,30 @@ class PeriodController extends Controller
*/
public function total(GenericRequest $request): JsonResponse
{
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToNative = Amount::convertToNative();
$default = Amount::getNativeCurrency();
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToPrimary = Amount::convertToPrimary();
$primary = Amount::getPrimaryCurrency();
// collect all expenses in this period (regardless of type)
$collector = app(GroupCollectorInterface::class);
$collector = app(GroupCollectorInterface::class);
$collector->setTypes([TransactionTypeEnum::TRANSFER->value])->setRange($start, $end)->setDestinationAccounts($accounts);
$genericSet = $collector->getExtractedJournals();
$genericSet = $collector->getExtractedJournals();
foreach ($genericSet as $journal) {
// currency
$currencyId = $journal['currency_id'];
$currencyCode = $journal['currency_code'];
$field = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount';
$field = $convertToPrimary && $currencyId !== $primary->id ? 'pc_amount' : 'amount';
// perhaps use default currency instead?
if ($convertToNative && $journal['currency_id'] !== $default->id) {
$currencyId = $default->id;
$currencyCode = $default->code;
if ($convertToPrimary && $journal['currency_id'] !== $primary->id) {
$currencyId = $primary->id;
$currencyCode = $primary->code;
}
// use foreign amount when the foreign currency IS the default currency.
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
if ($convertToPrimary && $journal['currency_id'] !== $primary->id && $primary->id === $journal['foreign_currency_id']) {
$field = 'foreign_amount';
}

View File

@@ -62,34 +62,34 @@ class TagController extends Controller
*/
public function noTag(GenericRequest $request): JsonResponse
{
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToNative = Amount::convertToNative();
$default = Amount::getNativeCurrency();
$accounts = $request->getAssetAccounts();
$start = $request->getStart();
$end = $request->getEnd();
$response = [];
$convertToPrimary = Amount::convertToPrimary();
$primary = Amount::getPrimaryCurrency();
// 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::TRANSFER->value])->setRange($start, $end)->setDestinationAccounts($accounts);
$collector->withoutTags();
$genericSet = $collector->getExtractedJournals();
$genericSet = $collector->getExtractedJournals();
foreach ($genericSet as $journal) {
// currency
$currencyId = $journal['currency_id'];
$currencyCode = $journal['currency_code'];
$field = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount';
$field = $convertToPrimary && $currencyId !== $primary->id ? 'pc_amount' : 'amount';
// perhaps use default currency instead?
if ($convertToNative && $journal['currency_id'] !== $default->id) {
$currencyId = $default->id;
$currencyCode = $default->code;
if ($convertToPrimary && $journal['currency_id'] !== $primary->id) {
$currencyId = $primary->id;
$currencyCode = $primary->code;
}
// use foreign amount when the foreign currency IS the default currency.
if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) {
if ($convertToPrimary && $journal['currency_id'] !== $primary->id && $primary->id === $journal['foreign_currency_id']) {
$field = 'foreign_amount';
}

View File

@@ -97,7 +97,7 @@ class ShowController extends Controller
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$enrichment->setUser($admin);
$enrichment->setNative($this->nativeCurrency);
$enrichment->setPrimary($this->primaryCurrency);
$accounts = $enrichment->enrich($accounts);
// make paginator:
@@ -132,7 +132,7 @@ class ShowController extends Controller
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$enrichment->setUser($admin);
$enrichment->setNative($this->nativeCurrency);
$enrichment->setPrimary($this->primaryCurrency);
$account = $enrichment->enrichSingle($account);

View File

@@ -76,7 +76,7 @@ class StoreController extends Controller
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$enrichment->setUser($admin);
$enrichment->setNative($this->nativeCurrency);
$enrichment->setPrimary($this->primaryCurrency);
$account = $enrichment->enrichSingle($account);
/** @var AccountTransformer $transformer */

View File

@@ -81,7 +81,7 @@ class UpdateController extends Controller
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$enrichment->setUser($admin);
$enrichment->setNative($this->nativeCurrency);
$enrichment->setPrimary($this->primaryCurrency);
$account = $enrichment->enrichSingle($account);
/** @var AccountTransformer $transformer */

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment;
use FireflyIII\Transformers\BillTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
@@ -76,6 +78,17 @@ class ShowController extends Controller
$bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimary($this->primaryCurrency);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$bills = $enrichment->enrich($bills);
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);
$transformer->setParameters($this->parameters);
@@ -96,6 +109,17 @@ class ShowController extends Controller
{
$manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimary($this->primaryCurrency);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$bill = $enrichment->enrichSingle($bill);
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);
$transformer->setParameters($this->parameters);

View File

@@ -29,7 +29,9 @@ use FireflyIII\Api\V1\Requests\Models\Bill\StoreRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment;
use FireflyIII\Transformers\BillTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use League\Fractal\Resource\Item;
@@ -72,6 +74,17 @@ class StoreController extends Controller
$bill = $this->repository->store($data);
$manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimary($this->primaryCurrency);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$bill = $enrichment->enrichSingle($bill);
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);
$transformer->setParameters($this->parameters);

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\Bill\UpdateRequest;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment;
use FireflyIII\Transformers\BillTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use League\Fractal\Resource\Item;
@@ -67,6 +69,17 @@ class UpdateController extends Controller
$bill = $this->repository->update($bill, $data);
$manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimary($this->primaryCurrency);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$bill = $enrichment->enrichSingle($bill);
/** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class);
$transformer->setParameters($this->parameters);

View File

@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\ObjectGroup;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment;
use FireflyIII\Transformers\BillTransformer;
use FireflyIII\Transformers\PiggyBankTransformer;
use FireflyIII\User;
@@ -79,6 +80,17 @@ class ListController extends Controller
$count = $collection->count();
$bills = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimary($this->primaryCurrency);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$bills = $enrichment->enrich($bills);
// make paginator:
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.bills', [$objectGroup->id]).$this->buildParams());

View File

@@ -84,7 +84,7 @@ class ListController extends Controller
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$enrichment->setUser($admin);
$enrichment->setNative($this->nativeCurrency);
$enrichment->setPrimary($this->primaryCurrency);
$accounts = $enrichment->enrich($accounts);
// make paginator:

View File

@@ -147,6 +147,7 @@ class ShowController extends Controller
$enrichment->setUser($admin);
$selectedGroup = $enrichment->enrichSingle($selectedGroup);
/** @var TransactionGroupTransformer $transformer */
$transformer = app(TransactionGroupTransformer::class);
$transformer->setParameters($this->parameters);

View File

@@ -43,6 +43,7 @@ use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment;
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
use FireflyIII\Transformers\AccountTransformer;
use FireflyIII\Transformers\AvailableBudgetTransformer;
@@ -107,7 +108,7 @@ class ListController extends Controller
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$enrichment->setUser($admin);
$enrichment->setNative($this->nativeCurrency);
$enrichment->setPrimary($this->primaryCurrency);
$accounts = $enrichment->enrich($accounts);
// make paginator:
@@ -182,6 +183,17 @@ class ListController extends Controller
$count = $collection->count();
$bills = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimary($this->primaryCurrency);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$bills = $enrichment->enrichSingle($bills);
// make paginator:
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.bills', [$currency->code]).$this->buildParams());

View File

@@ -107,7 +107,7 @@ class ShowController extends Controller
/** @var User $user */
$user = auth()->user();
$manager = $this->getManager();
$this->parameters->set('nativeCurrency', $this->nativeCurrency);
$this->parameters->set('primaryCurrency', $this->primaryCurrency);
// update fields with user info.
$currency->refreshForUser($user);
@@ -122,9 +122,6 @@ class ShowController extends Controller
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/getNativeCurrency
*
* Show a currency.
*
* @throws FireflyException
@@ -134,7 +131,7 @@ class ShowController extends Controller
/** @var User $user */
$user = auth()->user();
$manager = $this->getManager();
$currency = $this->nativeCurrency;
$currency = $this->primaryCurrency;
// update fields with user info.
$currency->refreshForUser($user);

View File

@@ -99,11 +99,6 @@ class UpdateController extends Controller
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/nativeCurrency
*
* Make the currency a default currency.
*
* @throws FireflyException
*/
public function makeDefault(TransactionCurrency $currency): JsonResponse

View File

@@ -89,7 +89,7 @@ class AccountController extends Controller
$admin = auth()->user();
$enrichment = new AccountEnrichment();
$enrichment->setUser($admin);
$enrichment->setNative($this->nativeCurrency);
$enrichment->setPrimary($this->primaryCurrency);
$accounts = $enrichment->enrich($accounts);
/** @var AccountTransformer $transformer */

View File

@@ -127,56 +127,56 @@ class BasicController extends Controller
{
Log::debug('getBalanceInformation');
// some config settings
$convertToNative = Amount::convertToNative();
$default = Amount::getNativeCurrency();
$convertToPrimary = Amount::convertToPrimary();
$primary = Amount::getPrimaryCurrency();
// prep some arrays:
$sums = [];
$return = [];
$currencies = [
$default->id => $default,
$sums = [];
$return = [];
$currencies = [
$primary->id => $primary,
];
// collect income of user using the new group collector.
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$summarizer = new TransactionSummarizer();
$set = $collector->setRange($start, $end)->setTypes([TransactionTypeEnum::DEPOSIT->value])->getExtractedJournals();
$incomes = $summarizer->groupByCurrencyId($set, 'positive', false);
$collector = app(GroupCollectorInterface::class);
$summarizer = new TransactionSummarizer();
$set = $collector->setRange($start, $end)->setTypes([TransactionTypeEnum::DEPOSIT->value])->getExtractedJournals();
$incomes = $summarizer->groupByCurrencyId($set, 'positive', false);
// collect expenses of user.
// collect expenses of user using the new group collector.
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$set = $collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->getExtractedJournals();
$expenses = $summarizer->groupByCurrencyId($set, 'negative', false);
$collector = app(GroupCollectorInterface::class);
$set = $collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->getExtractedJournals();
$expenses = $summarizer->groupByCurrencyId($set, 'negative', false);
// if convert to native, do so right now.
if ($convertToNative) {
// if convert to primary, do so right now.
if ($convertToPrimary) {
$newExpenses = [
$default->id => [
'currency_id' => $default->id,
'currency_code' => $default->code,
'currency_symbol' => $default->symbol,
'currency_decimal_places' => $default->decimal_places,
$primary->id => [
'currency_id' => $primary->id,
'currency_code' => $primary->code,
'currency_symbol' => $primary->symbol,
'currency_decimal_places' => $primary->decimal_places,
'sum' => '0',
],
];
$newIncomes = [
$default->id => [
'currency_id' => $default->id,
'currency_code' => $default->code,
'currency_symbol' => $default->symbol,
'currency_decimal_places' => $default->decimal_places,
$primary->id => [
'currency_id' => $primary->id,
'currency_code' => $primary->code,
'currency_symbol' => $primary->symbol,
'currency_decimal_places' => $primary->decimal_places,
'sum' => '0',
],
];
$sums = [
$default->id => [
'currency_id' => $default->id,
'currency_code' => $default->code,
'currency_symbol' => $default->symbol,
'currency_decimal_places' => $default->decimal_places,
$primary->id => [
'currency_id' => $primary->id,
'currency_code' => $primary->code,
'currency_symbol' => $primary->symbol,
'currency_decimal_places' => $primary->decimal_places,
'sum' => '0',
],
];
@@ -188,36 +188,36 @@ class BasicController extends Controller
// loop over either one.
foreach ($array as $entry) {
// if it is the native currency already.
if ($entry['currency_id'] === $default->id) {
$sums[$default->id]['sum'] = bcadd((string) $entry['sum'], $sums[$default->id]['sum']);
// if it is the primary currency already.
if ($entry['currency_id'] === $primary->id) {
$sums[$primary->id]['sum'] = bcadd((string) $entry['sum'], $sums[$primary->id]['sum']);
// don't forget to add it to newExpenses and newIncome
if (0 === $index) {
$newExpenses[$default->id]['sum'] = bcadd($newExpenses[$default->id]['sum'], (string) $entry['sum']);
$newExpenses[$primary->id]['sum'] = bcadd($newExpenses[$primary->id]['sum'], (string) $entry['sum']);
}
if (1 === $index) {
$newIncomes[$default->id]['sum'] = bcadd($newIncomes[$default->id]['sum'], (string) $entry['sum']);
$newIncomes[$primary->id]['sum'] = bcadd($newIncomes[$primary->id]['sum'], (string) $entry['sum']);
}
continue;
}
$currencies[$entry['currency_id']] ??= $this->currencyRepos->find($entry['currency_id']);
$convertedSum = $converter->convert($currencies[$entry['currency_id']], $default, $start, $entry['sum']);
$sums[$default->id]['sum'] = bcadd($sums[$default->id]['sum'], $convertedSum);
$convertedSum = $converter->convert($currencies[$entry['currency_id']], $primary, $start, $entry['sum']);
$sums[$primary->id]['sum'] = bcadd($sums[$primary->id]['sum'], $convertedSum);
if (0 === $index) {
$newExpenses[$default->id]['sum'] = bcadd($newExpenses[$default->id]['sum'], $convertedSum);
$newExpenses[$primary->id]['sum'] = bcadd($newExpenses[$primary->id]['sum'], $convertedSum);
}
if (1 === $index) {
$newIncomes[$default->id]['sum'] = bcadd($newIncomes[$default->id]['sum'], $convertedSum);
$newIncomes[$primary->id]['sum'] = bcadd($newIncomes[$primary->id]['sum'], $convertedSum);
}
}
}
$incomes = $newIncomes;
$expenses = $newExpenses;
}
if (!$convertToNative) {
if (!$convertToPrimary) {
foreach ([$expenses, $incomes] as $array) {
foreach ($array as $entry) {
$currencyId = $entry['currency_id'];
@@ -233,7 +233,7 @@ class BasicController extends Controller
}
}
// format amounts:
$keys = array_keys($sums);
$keys = array_keys($sums);
foreach ($keys as $currencyId) {
$currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId);
if (null === $currency) {
@@ -279,7 +279,7 @@ class BasicController extends Controller
];
}
if (0 === count($return)) {
$currency = $this->nativeCurrency;
$currency = $this->primaryCurrency;
// create objects for big array.
$return[] = [
'key' => sprintf('balance-in-%s', $currency->code),
@@ -333,26 +333,26 @@ class BasicController extends Controller
$paidAmount = $this->billRepository->sumPaidInRange($start, $end);
$unpaidAmount = $this->billRepository->sumUnpaidInRange($start, $end);
$currencies = [
$this->nativeCurrency->id => $this->nativeCurrency,
$this->primaryCurrency->id => $this->primaryCurrency,
];
if ($this->convertToNative) {
if ($this->convertToPrimary) {
$converter = new ExchangeRateConverter();
$newPaidAmount = [[
'id' => $this->nativeCurrency->id,
'name' => $this->nativeCurrency->name,
'symbol' => $this->nativeCurrency->symbol,
'code' => $this->nativeCurrency->code,
'decimal_places' => $this->nativeCurrency->decimal_places,
'id' => $this->primaryCurrency->id,
'name' => $this->primaryCurrency->name,
'symbol' => $this->primaryCurrency->symbol,
'code' => $this->primaryCurrency->code,
'decimal_places' => $this->primaryCurrency->decimal_places,
'sum' => '0',
]];
$newUnpaidAmount = [[
'id' => $this->nativeCurrency->id,
'name' => $this->nativeCurrency->name,
'symbol' => $this->nativeCurrency->symbol,
'code' => $this->nativeCurrency->code,
'decimal_places' => $this->nativeCurrency->decimal_places,
'id' => $this->primaryCurrency->id,
'name' => $this->primaryCurrency->name,
'symbol' => $this->primaryCurrency->symbol,
'code' => $this->primaryCurrency->code,
'decimal_places' => $this->primaryCurrency->decimal_places,
'sum' => '0',
]];
foreach ([$paidAmount, $unpaidAmount] as $index => $array) {
@@ -360,25 +360,25 @@ class BasicController extends Controller
$currencyId = (int) $item['id'];
if (0 === $index) {
// paid amount
if ($currencyId === $this->nativeCurrency->id) {
if ($currencyId === $this->primaryCurrency->id) {
$newPaidAmount[0]['sum'] = bcadd($newPaidAmount[0]['sum'], (string) $item['sum']);
continue;
}
$currencies[$currencyId] ??= $this->currencyRepos->find($currencyId);
$convertedAmount = $converter->convert($currencies[$currencyId], $this->nativeCurrency, $start, $item['sum']);
$convertedAmount = $converter->convert($currencies[$currencyId], $this->primaryCurrency, $start, $item['sum']);
$newPaidAmount[0]['sum'] = bcadd($newPaidAmount[0]['sum'], $convertedAmount);
continue;
}
// unpaid amount
if ($currencyId === $this->nativeCurrency->id) {
if ($currencyId === $this->primaryCurrency->id) {
$newUnpaidAmount[0]['sum'] = bcadd($newUnpaidAmount[0]['sum'], (string) $item['sum']);
continue;
}
$currencies[$currencyId] ??= $this->currencyRepos->find($currencyId);
$convertedAmount = $converter->convert($currencies[$currencyId], $this->nativeCurrency, $start, $item['sum']);
$convertedAmount = $converter->convert($currencies[$currencyId], $this->primaryCurrency, $start, $item['sum']);
$newUnpaidAmount[0]['sum'] = bcadd($newUnpaidAmount[0]['sum'], $convertedAmount);
}
}
@@ -432,7 +432,7 @@ class BasicController extends Controller
Log::debug(sprintf('Done with getBillInformation("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d-')));
if (0 === count($return)) {
$currency = $this->nativeCurrency;
$currency = $this->primaryCurrency;
unset($info, $amount);
$return[] = [
@@ -577,7 +577,7 @@ class BasicController extends Controller
// $amount = '0';
// // $days
// // fill in by money spent, just count it.
// $currency = $this->nativeCurrency;
// $currency = $this->primaryCurrency;
// $return[$currency->id] = [
// 'key' => sprintf('left-to-spend-in-%s', $currency->code),
// 'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $currency->symbol]),
@@ -626,7 +626,7 @@ class BasicController extends Controller
$netWorthSet = $netWorthHelper->byAccounts($filtered, $end);
$return = [];
foreach ($netWorthSet as $key => $data) {
if ('native' === $key) {
if ('pc' === $key) {
continue;
}
$amount = $data['balance'];
@@ -649,14 +649,14 @@ class BasicController extends Controller
}
if (0 === count($return)) {
$return[] = [
'key' => sprintf('net-worth-in-%s', $this->nativeCurrency->code),
'title' => trans('firefly.box_net_worth_in_currency', ['currency' => $this->nativeCurrency->symbol]),
'key' => sprintf('net-worth-in-%s', $this->primaryCurrency->code),
'title' => trans('firefly.box_net_worth_in_currency', ['currency' => $this->primaryCurrency->symbol]),
'monetary_value' => '0',
'currency_id' => (string) $this->nativeCurrency->id,
'currency_code' => $this->nativeCurrency->code,
'currency_symbol' => $this->nativeCurrency->symbol,
'currency_decimal_places' => $this->nativeCurrency->decimal_places,
'value_parsed' => app('amount')->formatFlat($this->nativeCurrency->symbol, $this->nativeCurrency->decimal_places, '0', false),
'currency_id' => (string) $this->primaryCurrency->id,
'currency_code' => $this->primaryCurrency->code,
'currency_symbol' => $this->primaryCurrency->symbol,
'currency_decimal_places' => $this->primaryCurrency->decimal_places,
'value_parsed' => app('amount')->formatFlat($this->primaryCurrency->symbol, $this->primaryCurrency->decimal_places, '0', false),
'local_icon' => 'line-chart',
'sub_title' => '',
];

View File

@@ -85,7 +85,7 @@ class PreferencesController extends Controller
$manager = $this->getManager();
if ('currencyPreference' === $preference->name) {
throw new FireflyException('Please use api/v1/currencies/native instead.');
throw new FireflyException('Please use api/v1/currencies/primary instead.');
}
/** @var PreferenceTransformer $transformer */
@@ -132,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/native instead.');
throw new FireflyException('Please use api/v1/currencies/primary instead.');
}
$manager = $this->getManager();

View File

@@ -39,9 +39,9 @@ class UpdateRequest extends FormRequest
public function getData(): array
{
$fields = [
'title' => ['title', 'convertString'],
'native_currency_id' => ['native_currency_id', 'convertInteger'],
'native_currency_code' => ['native_currency_code', 'convertString'],
'title' => ['title', 'convertString'],
'primary_currency_id' => ['primary_currency_id', 'convertInteger'],
'primary_currency_code' => ['primary_currency_code', 'convertString'],
];
return $this->getAllData($fields);
@@ -53,9 +53,9 @@ class UpdateRequest extends FormRequest
public function rules(): array
{
return [
'title' => ['required', 'min:1', 'max:255'],
'native_currency_id' => 'exists:transaction_currencies,id',
'native_currency_code' => 'exists:transaction_currencies,code',
'title' => ['required', 'min:1', 'max:255'],
'primary_currency_id' => 'exists:transaction_currencies,id',
'primary_currency_code' => 'exists:transaction_currencies,code',
];
}
}

View File

@@ -1,140 +0,0 @@
<?php
/*
* AccountController.php
* Copyright (c) 2022 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\V2\Controllers\Autocomplete;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Autocomplete\AutocompleteRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountBalance;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
/**
* Class AccountController
*/
class AccountController extends Controller
{
private ExchangeRateConverter $converter;
private TransactionCurrency $default;
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$userGroup = $this->validateUserGroup($request);
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setUserGroup($userGroup);
$this->default = app('amount')->getNativeCurrency();
$this->converter = app(ExchangeRateConverter::class);
return $next($request);
}
);
}
/**
* Documentation: https://api-docs.firefly-iii.org/?urls.primaryName=2.1.0%20(v2)#/autocomplete/getAccountsAC
*/
public function accounts(AutocompleteRequest $request): JsonResponse
{
$params = $request->getParameters();
$result = $this->repository->searchAccount($params['query'], $params['account_types'], $params['size']);
$return = [];
/** @var Account $account */
foreach ($result as $account) {
$return[] = $this->parseAccount($account);
}
return response()->json($return);
}
private function parseAccount(Account $account): array
{
$currency = $this->repository->getAccountCurrency($account);
return [
'id' => (string) $account->id,
'title' => $account->name,
'meta' => [
'type' => $account->accountType->type,
// TODO is multi currency property.
'currency_id' => $currency instanceof TransactionCurrency ? (string) $currency->id : null,
'currency_code' => $currency?->code,
'currency_symbol' => $currency?->symbol,
'currency_decimal_places' => $currency?->decimal_places,
'account_balances' => $this->getAccountBalances($account),
],
];
}
private function getAccountBalances(Account $account): array
{
$return = [];
$balances = $this->repository->getAccountBalances($account);
/** @var AccountBalance $balance */
foreach ($balances as $balance) {
try {
$return[] = $this->parseAccountBalance($balance);
} catch (FireflyException $e) {
Log::error(sprintf('Could not parse convert account balance: %s', $e->getMessage()));
}
}
return $return;
}
/**
* @throws FireflyException
*/
private function parseAccountBalance(AccountBalance $balance): array
{
$currency = $balance->transactionCurrency;
return [
'title' => $balance->title,
'native_amount' => $this->converter->convert($currency, $this->default, today(), $balance->balance),
'amount' => app('steam')->bcround($balance->balance, $currency->decimal_places),
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'native_currency_id' => (string) $this->default->id,
'native_currency_code' => $this->default->code,
'native_currency_symbol' => $this->default->symbol,
'native_currency_decimal_places' => $this->default->decimal_places,
];
}
}

View File

@@ -1,73 +0,0 @@
<?php
/*
* CategoryController.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\V2\Controllers\Autocomplete;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use Illuminate\Http\JsonResponse;
/**
* Class CategoryController
*/
class CategoryController extends Controller
{
private CategoryRepositoryInterface $repository;
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(CategoryRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
/**
* Documentation: https://api-docs.firefly-iii.org/?urls.primaryName=2.1.0%20(v2)#/autocomplete/getCategoriesAC
*/
public function categories(AutocompleteRequest $request): JsonResponse
{
$queryParameters = $request->getParameters();
$result = $this->repository->searchCategory($queryParameters['query'], $queryParameters['size']);
$filtered = $result->map(
static fn (Category $item) => [
'id' => (string) $item->id,
'title' => $item->name,
'meta' => [],
]
);
return response()->json($filtered);
}
}

View File

@@ -1,75 +0,0 @@
<?php
/*
* CategoryController.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\V2\Controllers\Autocomplete;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Illuminate\Http\JsonResponse;
/**
* Class TagController
*/
class TagController extends Controller
{
private TagRepositoryInterface $repository;
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(TagRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
/**
* Documentation: https://api-docs.firefly-iii.org/?urls.primaryName=2.1.0%20(v2)#/autocomplete/getTagsAC
*/
public function tags(AutocompleteRequest $request): JsonResponse
{
$queryParameters = $request->getParameters();
$result = $this->repository->searchTag($queryParameters['query']);
$filtered = $result->map(
static fn (Tag $item) => [
'id' => (string) $item->id,
'title' => $item->tag,
'value' => (string) $item->id,
'label' => $item->tag,
'meta' => [],
]
);
return response()->json($filtered);
}
}

View File

@@ -1,81 +0,0 @@
<?php
/*
* TransactionController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Autocomplete;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Http\JsonResponse;
/**
* Class TransactionController
*/
class TransactionController extends Controller
{
private JournalRepositoryInterface $repository;
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(JournalRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
/**
* Documentation: https://api-docs.firefly-iii.org/?urls.primaryName=2.1.0%20(v2)#/autocomplete/getTransactionsAC
*/
public function transactionDescriptions(AutocompleteRequest $request): JsonResponse
{
$queryParameters = $request->getParameters();
$result = $this->repository->searchJournalDescriptions($queryParameters['query'], $queryParameters['size']);
// limit and unique
$filtered = $result->unique('description');
$array = [];
/** @var TransactionJournal $journal */
foreach ($filtered as $journal) {
$array[] = [
'id' => (string) $journal->id,
'title' => $journal->description,
'meta' => [
'transaction_group_id' => (string) $journal->transaction_group_id,
],
];
}
return response()->json($array);
}
}

View File

@@ -1,140 +0,0 @@
<?php
/*
* AccountController.php
* Copyright (c) 2022 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\V2\Controllers\Chart;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Chart\ChartRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Chart\ChartData;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse;
/**
* Class AccountController
*/
class AccountController extends Controller
{
use CleansChartData;
use CollectsAccountsFromFilter;
use ValidatesUserGroupTrait;
private ChartData $chartData;
private TransactionCurrency $default;
private AccountRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
$this->chartData = new ChartData();
$this->default = app('amount')->getNativeCurrency();
return $next($request);
}
);
}
/**
* TODO fix documentation
*
* @throws FireflyException
*/
public function dashboard(ChartRequest $request): JsonResponse
{
$queryParameters = $request->getParameters();
$accounts = $this->getAccountList($queryParameters);
// move date to end of day
$queryParameters['start']->startOfDay();
$queryParameters['end']->endOfDay();
// loop each account, and collect info:
/** @var Account $account */
foreach ($accounts as $account) {
$this->renderAccountData($queryParameters, $account);
}
return response()->json($this->chartData->render());
}
/**
* @throws FireflyException
*/
private function renderAccountData(array $params, Account $account): void
{
$currency = $this->repository->getAccountCurrency($account);
if (!$currency instanceof TransactionCurrency) {
$currency = $this->default;
}
$currentSet = [
'label' => $account->name,
// the currency that belongs to the account.
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
// the default currency of the user (could be the same!)
'native_currency_id' => (string) $this->default->id,
'native_currency_code' => $this->default->code,
'native_currency_symbol' => $this->default->symbol,
'native_currency_decimal_places' => $this->default->decimal_places,
'date' => $params['start']->toAtomString(),
'start' => $params['start']->toAtomString(),
'end' => $params['end']->toAtomString(),
'period' => '1D',
'entries' => [],
'native_entries' => [],
];
$currentStart = clone $params['start'];
$range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative);
$previous = array_values($range)[0]['balance'];
$previousNative = array_values($range)[0]['native_balance'];
while ($currentStart <= $params['end']) {
$format = $currentStart->format('Y-m-d');
$label = $currentStart->toAtomString();
$balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous;
$balanceNative = array_key_exists($format, $range) ? $range[$format]['balance_native'] : $previousNative;
$previous = $balance;
$previousNative = $balanceNative;
$currentStart->addDay();
$currentSet['entries'][$label] = $balance;
$currentSet['native_entries'][$label] = $balanceNative;
}
$this->chartData->add($currentSet);
}
}

View File

@@ -1,116 +0,0 @@
<?php
/*
* BalanceController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Chart;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Chart\ChartRequest;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Chart\ChartData;
use FireflyIII\Support\Http\Api\AccountBalanceGrouped;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;
use Illuminate\Http\JsonResponse;
/**
* Class BalanceController
*/
class BalanceController extends Controller
{
use CleansChartData;
use CollectsAccountsFromFilter;
private ChartData $chartData;
private GroupCollectorInterface $collector;
private AccountRepositoryInterface $repository;
// private TransactionCurrency $default;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
$this->collector = app(GroupCollectorInterface::class);
$userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup);
$this->collector->setUserGroup($userGroup);
$this->chartData = new ChartData();
// $this->default = app('amount')->getNativeCurrency();
return $next($request);
}
);
}
/**
* The code is practically a duplicate of ReportController::operations.
*
* Currency is up to the account/transactions in question, but conversion to the default
* currency is possible.
*
* If the transaction being processed is already in native currency OR if the
* foreign amount is in the native currency, the amount will not be converted.
*
* @throws FireflyException
*/
public function balance(ChartRequest $request): JsonResponse
{
$queryParameters = $request->getParameters();
$accounts = $this->getAccountList($queryParameters);
// prepare for currency conversion and data collection:
/** @var TransactionCurrency $default */
$default = app('amount')->getNativeCurrency();
// get journals for entire period:
$this->collector->setRange($queryParameters['start'], $queryParameters['end'])
->withAccountInformation()
->setXorAccounts($accounts)
->setTypes([TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::DEPOSIT->value, TransactionTypeEnum::RECONCILIATION->value, TransactionTypeEnum::TRANSFER->value])
;
$journals = $this->collector->getExtractedJournals();
$object = new AccountBalanceGrouped();
$object->setPreferredRange($queryParameters['period']);
$object->setDefault($default);
$object->setAccounts($accounts);
$object->setJournals($journals);
$object->setStart($queryParameters['start']);
$object->setEnd($queryParameters['end']);
$object->groupByCurrencyAndPeriod();
$data = $object->convertToChartData();
foreach ($data as $entry) {
$this->chartData->add($entry);
}
return response()->json($this->chartData->render());
}
}

View File

@@ -1,293 +0,0 @@
<?php
/*
* BudgetController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
/**
* Class BudgetController
*/
class BudgetController extends Controller
{
use CleansChartData;
use ValidatesUserGroupTrait;
protected OperationsRepositoryInterface $opsRepository;
private BudgetLimitRepositoryInterface $blRepository;
private array $currencies = [];
private TransactionCurrency $currency;
private BudgetRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(BudgetRepositoryInterface::class);
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
$this->opsRepository = app(OperationsRepositoryInterface::class);
$this->currency = app('amount')->getNativeCurrency();
$userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup);
$this->opsRepository->setUserGroup($userGroup);
return $next($request);
}
);
}
/**
* TODO see autocomplete/accountcontroller
*/
public function dashboard(DateRequest $request): JsonResponse
{
$params = $request->getAll();
/** @var Carbon $start */
$start = $params['start'];
/** @var Carbon $end */
$end = $params['end'];
// code from FrontpageChartGenerator, but not in separate class
$budgets = $this->repository->getActiveBudgets();
$data = [];
/** @var Budget $budget */
foreach ($budgets as $budget) {
// could return multiple arrays, so merge.
$data = array_merge($data, $this->processBudget($budget, $start, $end));
}
return response()->json($this->clean($data));
}
/**
* @throws FireflyException
*/
private function processBudget(Budget $budget, Carbon $start, Carbon $end): array
{
// get all limits:
$limits = $this->blRepository->getBudgetLimits($budget, $start, $end);
$rows = [];
// if no limits
if (0 === $limits->count()) {
// return as a single item in an array
$rows = $this->noBudgetLimits($budget, $start, $end);
}
if ($limits->count() > 0) {
$rows = $this->budgetLimits($budget, $limits);
}
// is always an array
$return = [];
foreach ($rows as $row) {
$current = [
'label' => $budget->name,
'currency_id' => (string) $row['currency_id'],
'currency_code' => $row['currency_code'],
'currency_name' => $row['currency_name'],
'currency_decimal_places' => $row['currency_decimal_places'],
'native_currency_id' => (string) $row['native_currency_id'],
'native_currency_code' => $row['native_currency_code'],
'native_currency_name' => $row['native_currency_name'],
'native_currency_decimal_places' => $row['native_currency_decimal_places'],
'period' => null,
'start' => $row['start'],
'end' => $row['end'],
'entries' => [
'spent' => $row['spent'],
'left' => $row['left'],
'overspent' => $row['overspent'],
],
'native_entries' => [
'spent' => $row['native_spent'],
'left' => $row['native_left'],
'overspent' => $row['native_overspent'],
],
];
$return[] = $current;
}
return $return;
}
/**
* When no budget limits are present, the expenses of the whole period are collected and grouped.
* This is grouped per currency. Because there is no limit set, "left to spend" and "overspent" are empty.
*
* @throws FireflyException
*/
private function noBudgetLimits(Budget $budget, Carbon $start, Carbon $end): array
{
$spent = $this->opsRepository->listExpenses($start, $end, null, new Collection([$budget]));
return $this->processExpenses($budget->id, $spent, $start, $end);
}
/**
* Shared between the "noBudgetLimits" function and "processLimit". Will take a single set of expenses and return
* its info.
*
* @param array<int, array<int, string>> $array
*
* @throws FireflyException
*/
private function processExpenses(int $budgetId, array $array, Carbon $start, Carbon $end): array
{
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
$converter = new ExchangeRateConverter();
$return = [];
/**
* This array contains the expenses in this budget. Grouped per currency.
* The grouping is on the main currency only.
*
* @var int $currencyId
* @var array $block
*/
foreach ($array as $currencyId => $block) {
$this->currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
$return[$currencyId] ??= [
'currency_id' => (string) $currencyId,
'currency_code' => $block['currency_code'],
'currency_name' => $block['currency_name'],
'currency_symbol' => $block['currency_symbol'],
'currency_decimal_places' => (int) $block['currency_decimal_places'],
'native_currency_id' => (string) $this->currency->id,
'native_currency_code' => $this->currency->code,
'native_currency_name' => $this->currency->name,
'native_currency_symbol' => $this->currency->symbol,
'native_currency_decimal_places' => $this->currency->decimal_places,
'start' => $start->toAtomString(),
'end' => $end->toAtomString(),
'spent' => '0',
'native_spent' => '0',
'left' => '0',
'native_left' => '0',
'overspent' => '0',
'native_overspent' => '0',
];
$currentBudgetArray = $block['budgets'][$budgetId];
// var_dump($return);
/** @var array $journal */
foreach ($currentBudgetArray['transaction_journals'] as $journal) {
// convert the amount to the native currency.
$rate = $converter->getCurrencyRate($this->currencies[$currencyId], $this->currency, $journal['date']);
$convertedAmount = bcmul((string) $journal['amount'], $rate);
if ($journal['foreign_currency_id'] === $this->currency->id) {
$convertedAmount = $journal['foreign_amount'];
}
$return[$currencyId]['spent'] = bcadd($return[$currencyId]['spent'], (string) $journal['amount']);
$return[$currencyId]['native_spent'] = bcadd($return[$currencyId]['native_spent'], (string) $convertedAmount);
}
}
$converter->summarize();
return $return;
}
/**
* Function that processes each budget limit (per budget).
*
* If you have a budget limit in EUR, only transactions in EUR will be considered.
* If you have a budget limit in GBP, only transactions in GBP will be considered.
*
* If you have a budget limit in EUR, and a transaction in GBP, it will not be considered for the EUR budget limit.
*
* @throws FireflyException
*/
private function budgetLimits(Budget $budget, Collection $limits): array
{
app('log')->debug(sprintf('Now in budgetLimits(#%d)', $budget->id));
$data = [];
/** @var BudgetLimit $limit */
foreach ($limits as $limit) {
$data = array_merge($data, $this->processLimit($budget, $limit));
}
return $data;
}
/**
* @throws FireflyException
*/
private function processLimit(Budget $budget, BudgetLimit $limit): array
{
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
$end = clone $limit->end_date;
$end->endOfDay();
$spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection([$budget]));
$limitCurrencyId = $limit->transaction_currency_id;
$limitCurrency = $limit->transactionCurrency;
$converter = new ExchangeRateConverter();
$filtered = [];
$rate = $converter->getCurrencyRate($limitCurrency, $this->currency, $limit->start_date);
$convertedLimitAmount = bcmul($limit->amount, $rate);
/** @var array $entry */
foreach ($spent as $currencyId => $entry) {
// only spent the entry where the entry's currency matches the budget limit's currency
// so $filtered will only have 1 or 0 entries
if ($entry['currency_id'] === $limitCurrencyId) {
$filtered[$currencyId] = $entry;
}
}
$result = $this->processExpenses($budget->id, $filtered, $limit->start_date, $end);
if (1 === count($result)) {
$compare = bccomp($limit->amount, (string) app('steam')->positive($result[$limitCurrencyId]['spent']));
if (1 === $compare) {
// convert this amount into the native currency:
$result[$limitCurrencyId]['left'] = bcadd($limit->amount, (string) $result[$limitCurrencyId]['spent']);
$result[$limitCurrencyId]['native_left'] = bcadd($convertedLimitAmount, (string) $result[$limitCurrencyId]['native_spent']);
}
if ($compare <= 0) {
$result[$limitCurrencyId]['overspent'] = app('steam')->positive(bcadd($limit->amount, (string) $result[$limitCurrencyId]['spent']));
$result[$limitCurrencyId]['native_overspent'] = app('steam')->positive(bcadd($convertedLimitAmount, (string) $result[$limitCurrencyId]['native_spent']));
}
}
$converter->summarize();
return $result;
}
}

View File

@@ -1,142 +0,0 @@
<?php
/*
* CategoryController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
/**
* Class BudgetController
*/
class CategoryController extends Controller
{
use CleansChartData;
use ValidatesUserGroupTrait;
private AccountRepositoryInterface $accountRepos;
private CurrencyRepositoryInterface $currencyRepos;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
$this->accountRepos->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
/**
* TODO may be worth to move to a handler but the data is simple enough.
* TODO see autoComplete/account controller
*
* @throws FireflyException
*
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function dashboard(DateRequest $request): JsonResponse
{
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
/** @var Carbon $start */
$start = $this->parameters->get('start');
/** @var Carbon $end */
$end = $this->parameters->get('end');
$accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]);
$default = app('amount')->getNativeCurrency();
$converter = new ExchangeRateConverter();
$currencies = [];
$return = [];
// get journals for entire period:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setRange($start, $end)->withAccountInformation();
$collector->setXorAccounts($accounts)->withCategoryInformation();
$collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::RECONCILIATION->value]);
$journals = $collector->getExtractedJournals();
/** @var array $journal */
foreach ($journals as $journal) {
$currencyId = (int) $journal['currency_id'];
$currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId);
$currencies[$currencyId] = $currency;
$categoryName = $journal['category_name'] ?? (string) trans('firefly.no_category');
$amount = app('steam')->positive($journal['amount']);
$nativeAmount = $converter->convert($default, $currency, $journal['date'], $amount);
$key = sprintf('%s-%s', $categoryName, $currency->code);
if ((int) $journal['foreign_currency_id'] === $default->id) {
$nativeAmount = app('steam')->positive($journal['foreign_amount']);
}
// create arrays
$return[$key] ??= [
'label' => $categoryName,
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_name' => $currency->name,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'native_currency_id' => (string) $default->id,
'native_currency_code' => $default->code,
'native_currency_name' => $default->name,
'native_currency_symbol' => $default->symbol,
'native_currency_decimal_places' => $default->decimal_places,
'period' => null,
'start' => $start->toAtomString(),
'end' => $end->toAtomString(),
'amount' => '0',
'native_amount' => '0',
];
// add monies
$return[$key]['amount'] = bcadd($return[$key]['amount'], (string) $amount);
$return[$key]['native_amount'] = bcadd($return[$key]['native_amount'], (string) $nativeAmount);
}
$return = array_values($return);
// order by native amount
usort($return, static fn (array $a, array $b) => (float) $a['native_amount'] < (float) $b['native_amount'] ? 1 : -1);
$converter->summarize();
return response()->json($this->clean($return));
}
}

View File

@@ -1,195 +0,0 @@
<?php
/*
* Controller.php
* Copyright (c) 2022 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\V2\Controllers;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidDateException;
use Carbon\Exceptions\InvalidFormatException;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\AbstractTransformer;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Routing\Controller as BaseController;
use League\Fractal\Manager;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection;
use League\Fractal\Resource\Item;
use League\Fractal\Serializer\JsonApiSerializer;
use Psr\Container\ContainerExceptionInterface;
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
use Symfony\Component\HttpFoundation\ParameterBag;
/**
* Class Controller
*
* @SuppressWarnings("PHPMD.CouplingBetweenObjects")
* @SuppressWarnings("PHPMD.NumberOfChildren")
*/
class Controller extends BaseController
{
use ValidatesUserGroupTrait;
protected const string CONTENT_TYPE = 'application/vnd.api+json';
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
protected bool $convertToNative = false;
protected ParameterBag $parameters;
public function __construct()
{
$this->middleware(
function ($request, $next) {
$this->parameters = $this->getParameters();
return $next($request);
}
);
}
/**
* TODO duplicate from V1 controller
* Method to grab all parameters from the URL.
*
* @SuppressWarnings("PHPMD.NPathComplexity")
*/
private function getParameters(): ParameterBag
{
$bag = new ParameterBag();
$bag->set('limit', 50);
try {
$page = (int) request()->get('page');
} catch (ContainerExceptionInterface) {
$page = 1;
}
$integers = ['limit', 'administration'];
$dates = ['start', 'end', 'date'];
if ($page < 1) {
$page = 1;
}
if ($page > 2 ** 16) {
$page = 2 ** 16;
}
$bag->set('page', $page);
// some date fields:
foreach ($dates as $field) {
$date = null;
$obj = null;
try {
$date = request()->query->get($field);
} catch (BadRequestException $e) {
app('log')->error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $field));
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
}
if (null !== $date) {
try {
$obj = Carbon::parse((string) $date, config('app.timezone'));
} catch (InvalidDateException|InvalidFormatException $e) {
// don't care
app('log')->warning(sprintf('Ignored invalid date "%s" in API v2 controller parameter check: %s', substr((string) $date, 0, 20), $e->getMessage()));
}
// out of range? set to null.
if ($obj instanceof Carbon && ($obj->year <= 1970 || $obj->year > 2038)) {
app('log')->warning(sprintf('Refuse to use date "%s" in API v2 controller parameter check: %s', $field, $obj->toAtomString()));
$obj = null;
}
}
if (null !== $date && 'end' === $field) {
$obj->endOfDay();
}
$bag->set($field, $obj);
}
// integer fields:
foreach ($integers as $integer) {
try {
$value = request()->query->get($integer);
} catch (BadRequestException $e) {
app('log')->error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $integer));
app('log')->error($e->getMessage());
$value = null;
}
if (null !== $value) {
$bag->set($integer, (int) $value);
}
if (null === $value && 'limit' === $integer && auth()->check()) {
// set default for user:
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$bag->set($integer, $pageSize);
}
}
// sort fields:
// return $this->getSortParameters($bag);
return $bag;
}
final protected function jsonApiList(string $key, LengthAwarePaginator $paginator, AbstractTransformer $transformer): array
{
$manager = new Manager();
$baseUrl = request()->getSchemeAndHttpHost().'/api/v2';
// 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 = request()->getSchemeAndHttpHost().'/api/v2';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
// $transformer->collectMetaData(new Collection([$object]));
$resource = new Item($object, $transformer, $key);
return $manager->createData($resource)->toArray();
}
}

View File

@@ -1,32 +0,0 @@
<?php
/*
* AccountController.php
* Copyright (c) 2022 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\V2\Controllers\Data\Bulk;
use FireflyIII\Api\V2\Controllers\Controller;
/**
* Class AccountController
*/
class AccountController extends Controller {}

View File

@@ -1,32 +0,0 @@
<?php
/*
* AccountController.php
* Copyright (c) 2022 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\V2\Controllers\Data\Export;
use FireflyIII\Api\V2\Controllers\Controller;
/**
* Class AccountController
*/
class AccountController extends Controller {}

View File

@@ -1,32 +0,0 @@
<?php
/*
* AccountController.php
* Copyright (c) 2022 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\V2\Controllers\Data\MassDestroy;
use FireflyIII\Api\V2\Controllers\Controller;
/**
* Class AccountController
*/
class AccountController extends Controller {}

View File

@@ -1,97 +0,0 @@
<?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\V2\Controllers\Model\Account;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\Account\IndexRequest;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Transformers\AccountTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Log;
class IndexController extends Controller
{
public const string RESOURCE_KEY = 'accounts';
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup);
return $next($request);
}
);
}
/**
* TODO the sort instructions need proper repeatable documentation.
* TODO see autocomplete/account controller for list.
*/
public function index(IndexRequest $request): JsonResponse
{
$this->repository->resetAccountOrder();
$types = $request->getAccountTypes();
$sorting = $request->getSortInstructions('accounts');
$filters = $request->getFilterInstructions('accounts');
$accounts = $this->repository->getAccountsByType($types, $sorting);
$pageSize = $this->parameters->get('limit');
$count = $accounts->count();
// depending on the sort parameters, this list must not be split, because the
// order is calculated in the account transformer and by that time it's too late.
$first = array_key_first($sorting);
$disablePagination = in_array($first, ['last_activity', 'balance', 'balance_difference'], true);
Log::debug(sprintf('Will disable pagination in account index v2? %s', var_export($disablePagination, true)));
if (!$disablePagination) {
$accounts = $accounts->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
}
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
$transformer = new AccountTransformer();
$this->parameters->set('disablePagination', $disablePagination);
$this->parameters->set('pageSize', $pageSize);
$this->parameters->set('sort', $sorting);
$this->parameters->set('filters', $filters);
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList('accounts', $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,76 +0,0 @@
<?php
/*
* ShowController.php
* Copyright (c) 2022 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\V2\Controllers\Model\Account;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Transformers\AccountTransformer;
use Illuminate\Http\JsonResponse;
/**
* Show = show a single account.
* Index = show all accounts
* Class ShowController
*/
class ShowController extends Controller
{
public const string RESOURCE_KEY = 'accounts';
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup);
return $next($request);
}
);
}
/**
* TODO this endpoint is not yet reachable.
*/
public function show(Account $account): JsonResponse
{
$transformer = new AccountTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('accounts', $account, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,76 +0,0 @@
<?php
/*
* UpdateController.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\V2\Controllers\Model\Account;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\Account\UpdateRequest;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Transformers\AccountTransformer;
use Illuminate\Http\JsonResponse;
class UpdateController extends Controller
{
public const string RESOURCE_KEY = 'accounts';
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
/**
* TODO this endpoint is not yet reachable.
*/
public function update(UpdateRequest $request, Account $account): JsonResponse
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
$data = $request->getUpdateData();
$data['type'] = config('firefly.shortNamesByFullName.'.$account->accountType->type);
$account = $this->repository->update($account, $data);
$account->refresh();
app('preferences')->mark();
$transformer = new AccountTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('accounts', $account, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,75 +0,0 @@
<?php
/*
* ShowController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\Bill;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\BillTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
/**
* Class ShowController
*/
class IndexController extends Controller
{
use ValidatesUserGroupTrait;
private BillRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(BillRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
/**
* TODO see autocomplete/accountcontroller for list.
*/
public function index(): JsonResponse
{
$this->repository->correctOrder();
$bills = $this->repository->getBills();
$pageSize = $this->parameters->get('limit');
$count = $bills->count();
$bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
$transformer = new BillTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList('subscriptions', $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,69 +0,0 @@
<?php
/*
* ShowController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\Bill;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\BillTransformer;
use Illuminate\Http\JsonResponse;
/**
* Class ShowController
*/
class ShowController extends Controller
{
use ValidatesUserGroupTrait;
private BillRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(BillRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
/**
* TODO this endpoint is not documented
*/
public function show(Bill $bill): JsonResponse
{
$transformer = new BillTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('subscriptions', $bill, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,86 +0,0 @@
<?php
/*
* SumController.php
* Copyright (c) 2022 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\V2\Controllers\Model\Bill;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse;
/**
* Class SumController
*/
class SumController extends Controller
{
use ValidatesUserGroupTrait;
private BillRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(BillRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/transactions-sum/getBillsPaidTrSum
*
* TODO see autocomplete/accountcontroller for list.
*
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function paid(DateRequest $request): JsonResponse
{
$result = $this->repository->sumPaidInRange($this->parameters->get('start'), $this->parameters->get('end'));
// convert to JSON response:
return response()->api(array_values($result));
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/transactions-sum/getBillsUnpaidTrSum
*
* TODO see autocomplete/accountcontroller for list.
*
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function unpaid(DateRequest $request): JsonResponse
{
$result = $this->repository->sumUnpaidInRange($this->parameters->get('start'), $this->parameters->get('end'));
// convert to JSON response:
return response()->api(array_values($result));
}
}

View File

@@ -1,71 +0,0 @@
<?php
/*
* ListController.php
* Copyright (c) 2022 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\V2\Controllers\Model\Budget;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Transformers\BudgetTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
/**
* Class IndexController
*/
class IndexController extends Controller
{
private BudgetRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(BudgetRepositoryInterface::class);
return $next($request);
}
);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/budgets/listBudgets
*/
public function index(): JsonResponse
{
$pageSize = $this->parameters->get('limit');
$collection = $this->repository->getActiveBudgets();
$total = $collection->count();
$collection->slice($pageSize * $this->parameters->get('page'), $pageSize);
$paginator = new LengthAwarePaginator($collection, $total, $pageSize, $this->parameters->get('page'));
$transformer = new BudgetTransformer();
return response()
->api($this->jsonApiList('budgets', $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,94 +0,0 @@
<?php
/*
* ShowController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\Budget;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Transformers\BudgetTransformer;
use Illuminate\Http\JsonResponse;
/**
* Class ShowController
* TODO lots of deprecated code here.
*/
class ShowController extends Controller
{
private BudgetRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(BudgetRepositoryInterface::class);
return $next($request);
}
);
}
/**
* 2023-10-29 removed the cerSum reference, not sure where this is used atm
* so removed from api.php. Also applies to "spent" method.
*
* This endpoint is documented at:
* TODO add URL
*/
public function budgeted(DateRequest $request, Budget $budget): JsonResponse
{
$data = $request->getAll();
$result = $this->repository->budgetedInPeriodForBudget($budget, $data['start'], $data['end']);
return response()->json($result);
}
/**
* Show a budget.
*/
public function show(Budget $budget): JsonResponse
{
$transformer = new BudgetTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('budgets', $budget, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
/**
* This endpoint is documented at:
* TODO add URL
*/
public function spent(DateRequest $request, Budget $budget): JsonResponse
{
$data = $request->getAll();
$result = $this->repository->spentInPeriodForBudget($budget, $data['start'], $data['end']);
return response()->json($result);
}
}

View File

@@ -1,74 +0,0 @@
<?php
/*
* SumController.php
* Copyright (c) 2022 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\V2\Controllers\Model\Budget;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Http\JsonResponse;
/**
* Class SumController
*/
class SumController extends Controller
{
private BudgetRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(BudgetRepositoryInterface::class);
return $next($request);
}
);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/budgets/getBudgetedForBudget
*/
public function budgeted(DateRequest $request): JsonResponse
{
$data = $request->getAll();
$result = $this->repository->budgetedInPeriod($data['start'], $data['end']);
return response()->json($result);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/budgets/getSpentForBudget
*/
public function spent(DateRequest $request): JsonResponse
{
$data = $request->getAll();
$result = $this->repository->spentInPeriod($data['start'], $data['end']);
return response()->json($result);
}
}

View File

@@ -1,66 +0,0 @@
<?php
/*
* IndexController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\BudgetLimit;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Transformers\BudgetLimitTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
class IndexController extends Controller
{
private BudgetLimitRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(BudgetLimitRepositoryInterface::class);
return $next($request);
}
);
}
/**
* This endpoint is documented at:
* TODO add URL
*/
public function index(Budget $budget): JsonResponse
{
$pageSize = $this->parameters->get('limit');
$collection = $this->repository->getBudgetLimits($budget);
$total = $collection->count();
$collection->slice($pageSize * $this->parameters->get('page'), $pageSize);
$paginator = new LengthAwarePaginator($collection, $total, $pageSize, $this->parameters->get('page'));
$transformer = new BudgetLimitTransformer();
return response()->api($this->jsonApiList('budget-limits', $paginator, $transformer))->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@@ -1,71 +0,0 @@
<?php
/*
* ListController.php
* Copyright (c) 2022 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\V2\Controllers\Model\BudgetLimit;
use FireflyIII\Api\V2\Controllers\Controller;
use Illuminate\Http\JsonResponse;
/**
* Class ListController
*/
class ListController extends Controller
{
// private BudgetLimitRepositoryInterface $repository;
//
// public function __construct()
// {
// parent::__construct();
// $this->middleware(
// function ($request, $next) {
// $this->repository = app(BudgetLimitRepositoryInterface::class);
//
// return $next($request);
// }
// );
// }
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/budgets/listBudgetLimitByBudget
* // DateRequest $request, Budget $budget
*/
public function index(): JsonResponse
{
return response()->json();
// throw new FireflyException('Needs refactoring, move to IndexController.');
// $pageSize = $this->parameters->get('limit');
// $dates = $request->getAll();
// $collection = $this->repository->getBudgetLimits($budget, $dates['start'], $dates['end']);
// $total = $collection->count();
// $collection->slice($pageSize * $this->parameters->get('page'), $pageSize);
//
// $paginator = new LengthAwarePaginator($collection, $total, $pageSize, $this->parameters->get('page'));
// $transformer = new BudgetLimitTransformer();
//
// return response()
// ->api($this->jsonApiList('budget-limits', $paginator, $transformer))
// ->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@@ -1,72 +0,0 @@
<?php
/*
* IndexController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\Currency;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Transformers\CurrencyTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
/**
* Class IndexController
*/
class IndexController extends Controller
{
private CurrencyRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(CurrencyRepositoryInterface::class);
return $next($request);
}
);
}
/**
* TODO This endpoint is not yet documented.
*
* Display a listing of the resource.
*/
public function index(): JsonResponse
{
$bills = $this->repository->getAll();
$pageSize = $this->parameters->get('limit');
$count = $bills->count();
$bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
$transformer = new CurrencyTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList('currencies', $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,74 +0,0 @@
<?php
/*
* ShowController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\PiggyBank;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\PiggyBankTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
/**
* Class ShowController
*/
class IndexController extends Controller
{
use ValidatesUserGroupTrait;
private PiggyBankRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(PiggyBankRepositoryInterface::class);
$this->repository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
}
/**
* TODO see autocomplete/accountcontroller for list.
*/
public function index(): JsonResponse
{
$piggies = $this->repository->getPiggyBanks();
$pageSize = $this->parameters->get('limit');
$count = $piggies->count();
$piggies = $piggies->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($piggies, $count, $pageSize, $this->parameters->get('page'));
$transformer = new PiggyBankTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList('piggy-banks', $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,44 +0,0 @@
<?php
/*
* ShowController.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\V2\Controllers\Model\Transaction;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Transformers\TransactionGroupTransformer;
use Illuminate\Http\JsonResponse;
class ShowController extends Controller
{
/**
* TODO this endpoint is not yet reachable.
*/
public function show(TransactionGroup $transactionGroup): JsonResponse
{
$transformer = new TransactionGroupTransformer();
$transformer->setParameters($this->parameters);
return response()->api($this->jsonApiObject('transactions', $transactionGroup, $transformer))->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@@ -1,130 +0,0 @@
<?php
/*
* StoreController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\Transaction;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\Transaction\StoreRequest;
use FireflyIII\Events\StoredTransactionGroup;
use FireflyIII\Exceptions\DuplicateTransactionException;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
use FireflyIII\Rules\IsDuplicateTransaction;
use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
/**
* Class StoreController
*/
class StoreController extends Controller
{
private TransactionGroupRepositoryInterface $groupRepository;
/**
* TransactionController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
return $next($request);
}
);
}
/**
* TODO this method is practically the same as the V1 method and borrows as much code as possible.
*
* @throws FireflyException
* @throws ValidationException
*/
public function post(StoreRequest $request): JsonResponse
{
app('log')->debug('Now in API v2 StoreController::store()');
$data = $request->getAll();
$userGroup = $request->getUserGroup();
$data['user_group'] = $userGroup;
// overrule user group and see where we end up.
// what happens when we refer to a budget that is not in this user group?
app('log')->channel('audit')->info('Store new transaction over API.', $data);
try {
$transactionGroup = $this->groupRepository->store($data);
} 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);
} 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);
}
app('preferences')->mark();
$applyRules = $data['apply_rules'] ?? true;
$fireWebhooks = $data['fire_webhooks'] ?? true;
event(new StoredTransactionGroup($transactionGroup, $applyRules, $fireWebhooks));
/** @var User $admin */
$admin = auth()->user();
// use new group collector:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
->setUser($admin)
// filter on transaction group.
->setTransactionGroup($transactionGroup)
;
$selectedGroup = $collector->getGroups()->first();
if (null === $selectedGroup) {
throw new FireflyException('200032: Cannot find transaction. Possibly, a rule deleted this transaction after its creation.');
}
$transformer = new TransactionGroupTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('transactions', $selectedGroup, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,94 +0,0 @@
<?php
/*
* UpdateController.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\V2\Controllers\Model\Transaction;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\Transaction\UpdateRequest;
use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
class UpdateController extends Controller
{
private TransactionGroupRepositoryInterface $groupRepository;
/**
* TransactionController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
return $next($request);
}
);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/transactions/updateTransaction
*
* Update a transaction.
*
* @throws FireflyException
*/
public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
{
app('log')->debug('Now in update routine for transaction group [v2]!');
$data = $request->getAll();
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
$applyRules = $data['apply_rules'] ?? true;
$fireWebhooks = $data['fire_webhooks'] ?? true;
event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks, true));
app('preferences')->mark();
/** @var User $admin */
$admin = auth()->user();
// use new group collector:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($admin)->setTransactionGroup($transactionGroup);
$selectedGroup = $collector->getGroups()->first();
if (null === $selectedGroup) {
throw new FireflyException('200032: Cannot find transaction. Possibly, a rule deleted this transaction after its creation.');
}
$transformer = new TransactionGroupTransformer();
$transformer->setParameters($this->parameters);
return response()->api($this->jsonApiObject('transactions', $selectedGroup, $transformer))->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@@ -1,85 +0,0 @@
<?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\V2\Controllers\Model\TransactionCurrency;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\TransactionCurrency\IndexRequest;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Transformers\CurrencyTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
class IndexController extends Controller
{
public const string RESOURCE_KEY = 'transaction-currencies';
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
private CurrencyRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(CurrencyRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup);
return $next($request);
}
);
}
public function index(IndexRequest $request): JsonResponse
{
$settings = $request->getAll();
$currencies = new Collection();
if (true === $settings['enabled']) {
$currencies = $this->repository->get();
}
if (true !== $settings['enabled']) {
$currencies = $this->repository->getAll();
}
$pageSize = $this->parameters->get('limit');
$count = $currencies->count();
// depending on the sort parameters, this list must not be split, because the
// order is calculated in the account transformer and by that time it's too late.
$accounts = $currencies->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
$transformer = new CurrencyTransformer();
$this->parameters->set('pageSize', $pageSize);
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList(self::RESOURCE_KEY, $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,80 +0,0 @@
<?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\V2\Controllers\Model\TransactionCurrency;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Transformers\CurrencyTransformer;
use Illuminate\Http\JsonResponse;
/**
* Class ShowController
*/
class ShowController extends Controller
{
public const string RESOURCE_KEY = 'transaction-currencies';
private CurrencyRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(CurrencyRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup);
return $next($request);
}
);
}
public function show(TransactionCurrency $currency): JsonResponse
{
$groups = $currency->userGroups()->where('user_groups.id', $this->repository->getUserGroup()->id)->get();
$enabled = $groups->count() > 0;
$default = false;
/** @var UserGroup $group */
foreach ($groups as $group) {
$default = 1 === $group->pivot->group_default;
}
$currency->userGroupEnabled = $enabled;
$currency->userGroupNative = $default;
$transformer = new CurrencyTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject(self::RESOURCE_KEY, $currency, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,32 +0,0 @@
<?php
/*
* AccountController.php
* Copyright (c) 2022 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\V2\Controllers\Search;
use FireflyIII\Api\V2\Controllers\Controller;
/**
* Class AccountController
*/
class AccountController extends Controller {}

View File

@@ -1,412 +0,0 @@
<?php
/*
* SummaryController.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\V2\Controllers\Summary;
use Exception;
use Carbon\Carbon;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Helpers\Report\NetWorthInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Http\Api\SummaryBalanceGrouped;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
/**
* Class BasicController
*/
class BasicController extends Controller
{
use ValidatesUserGroupTrait;
private AvailableBudgetRepositoryInterface $abRepository;
private AccountRepositoryInterface $accountRepository;
private BillRepositoryInterface $billRepository;
private BudgetRepositoryInterface $budgetRepository;
private CurrencyRepositoryInterface $currencyRepos;
private OperationsRepositoryInterface $opsRepository;
/**
* BasicController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->abRepository = app(AvailableBudgetRepositoryInterface::class);
$this->accountRepository = app(AccountRepositoryInterface::class);
$this->billRepository = app(BillRepositoryInterface::class);
$this->budgetRepository = app(BudgetRepositoryInterface::class);
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
$this->opsRepository = app(OperationsRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request);
$this->abRepository->setUserGroup($userGroup);
$this->accountRepository->setUserGroup($userGroup);
$this->billRepository->setUserGroup($userGroup);
$this->budgetRepository->setUserGroup($userGroup);
$this->opsRepository->setUserGroup($userGroup);
return $next($request);
}
);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/summary/getBasicSummary
*
* @throws Exception
*
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function basic(DateRequest $request): JsonResponse
{
// parameters for boxes:
$start = $this->parameters->get('start');
$end = $this->parameters->get('end');
// balance information:
$balanceData = $this->getBalanceInformation($start, $end);
$billData = $this->getBillInformation($start, $end);
$spentData = $this->getLeftToSpendInfo($start, $end);
$netWorthData = $this->getNetWorthInfo($start, $end);
$total = array_merge($balanceData, $billData, $spentData, $netWorthData);
return response()->json($total);
}
/**
* @throws FireflyException
*/
private function getBalanceInformation(Carbon $start, Carbon $end): array
{
$object = new SummaryBalanceGrouped();
$default = app('amount')->getNativeCurrency();
$object->setDefault($default);
/** @var User $user */
$user = auth()->user();
// collect income of user using the new group collector.
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
->setRange($start, $end)
->setUserGroup($user->userGroup)
// set page to retrieve
->setPage($this->parameters->get('page'))
// set types of transactions to return.
->setTypes([TransactionTypeEnum::DEPOSIT->value])
->setRange($start, $end)
;
$set = $collector->getExtractedJournals();
$object->groupTransactions('income', $set);
// collect expenses of user using the new group collector.
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
->setRange($start, $end)
->setUserGroup($user->userGroup)
// set page to retrieve
->setPage($this->parameters->get('page'))
// set types of transactions to return.
->setTypes([TransactionTypeEnum::WITHDRAWAL->value])
->setRange($start, $end)
;
$set = $collector->getExtractedJournals();
$object->groupTransactions('expense', $set);
return $object->groupData();
}
private function getBillInformation(Carbon $start, Carbon $end): array
{
/*
* Since both this method and the chart use the exact same data, we can suffice
* with calling the one method in the bill repository that will get this amount.
*/
$paidAmount = $this->billRepository->sumPaidInRange($start, $end);
$unpaidAmount = $this->billRepository->sumUnpaidInRange($start, $end);
$return = [];
/**
* @var array $info
*/
foreach ($paidAmount as $info) {
$amount = bcmul((string) $info['sum'], '-1');
$nativeAmount = bcmul((string) $info['native_sum'], '-1');
$return[] = [
'key' => sprintf('bills-paid-in-%s', $info['currency_code']),
'value' => $amount,
'currency_id' => (string) $info['currency_id'],
'currency_code' => $info['currency_code'],
'currency_symbol' => $info['currency_symbol'],
'currency_decimal_places' => $info['currency_decimal_places'],
];
$return[] = [
'key' => 'bills-paid-in-native',
'value' => $nativeAmount,
'currency_id' => (string) $info['native_currency_id'],
'currency_code' => $info['native_currency_code'],
'currency_symbol' => $info['native_currency_symbol'],
'currency_decimal_places' => $info['native_currency_decimal_places'],
];
}
/**
* @var array $info
*/
foreach ($unpaidAmount as $info) {
$amount = bcmul((string) $info['sum'], '-1');
$nativeAmount = bcmul((string) $info['native_sum'], '-1');
$return[] = [
'key' => sprintf('bills-unpaid-in-%s', $info['currency_code']),
'value' => $amount,
'currency_id' => (string) $info['currency_id'],
'currency_code' => $info['currency_code'],
'currency_symbol' => $info['currency_symbol'],
'currency_decimal_places' => $info['currency_decimal_places'],
];
$return[] = [
'key' => 'bills-unpaid-in-native',
'value' => $nativeAmount,
'currency_id' => (string) $info['native_currency_id'],
'currency_code' => $info['native_currency_code'],
'currency_symbol' => $info['native_currency_symbol'],
'currency_decimal_places' => $info['native_currency_decimal_places'],
];
}
return $return;
}
/**
* @SuppressWarnings("PHPMD.ExcessiveMethodLength")
*/
private function getLeftToSpendInfo(Carbon $start, Carbon $end): array
{
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
app('log')->debug('Now in getLeftToSpendInfo');
$return = [];
$today = today(config('app.timezone'));
$available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end);
$budgets = $this->budgetRepository->getActiveBudgets();
$spent = $this->opsRepository->listExpenses($start, $end, null, $budgets);
$default = app('amount')->getNativeCurrency();
$currencies = [];
$converter = new ExchangeRateConverter();
// native info:
$nativeLeft = [
'key' => 'left-to-spend-in-native',
'value' => '0',
'currency_id' => (string) $default->id,
'currency_code' => $default->code,
'currency_symbol' => $default->symbol,
'currency_decimal_places' => $default->decimal_places,
];
$nativePerDay = [
'key' => 'left-per-day-to-spend-in-native',
'value' => '0',
'currency_id' => (string) $default->id,
'currency_code' => $default->code,
'currency_symbol' => $default->symbol,
'currency_decimal_places' => $default->decimal_places,
];
/**
* @var int $currencyId
* @var array $row
*/
foreach ($spent as $currencyId => $row) {
app('log')->debug(sprintf('Processing spent array in currency #%d', $currencyId));
$spent = '0';
$spentNative = '0';
// get the sum from the array of transactions (double loop but who cares)
/** @var array $budget */
foreach ($row['budgets'] as $budget) {
app('log')->debug(sprintf('Processing expenses in budget "%s".', $budget['name']));
/** @var array $journal */
foreach ($budget['transaction_journals'] as $journal) {
$journalCurrencyId = $journal['currency_id'];
$currency = $currencies[$journalCurrencyId] ?? $this->currencyRepos->find($journalCurrencyId);
$currencies[$currencyId] = $currency;
$amount = app('steam')->negative($journal['amount']);
$amountNative = $converter->convert($default, $currency, $start, $amount);
if ((int) $journal['foreign_currency_id'] === $default->id) {
$amountNative = $journal['foreign_amount'];
}
$spent = bcadd($spent, (string) $amount);
$spentNative = bcadd($spentNative, (string) $amountNative);
}
app('log')->debug(sprintf('Total spent in budget "%s" is %s', $budget['name'], $spent));
}
// either an amount was budgeted or 0 is available.
$currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId);
$currencies[$currencyId] = $currency;
$amount = $available[$currencyId]['amount'] ?? '0';
$amountNative = $available[$currencyId]['native_amount'] ?? '0';
$left = bcadd($amount, $spent);
$leftNative = bcadd($amountNative, $spentNative);
app('log')->debug(sprintf('Available amount is %s', $amount));
app('log')->debug(sprintf('Amount left is %s', $left));
// how much left per day?
$days = (int) $today->diffInDays($end, true) + 1;
$perDay = '0';
$perDayNative = '0';
if (0 !== $days && bccomp($left, '0') > -1) {
$perDay = bcdiv($left, (string) $days);
}
if (0 !== $days && bccomp($leftNative, '0') > -1) {
$perDayNative = bcdiv($leftNative, (string) $days);
}
// left
$return[] = [
'key' => sprintf('left-to-spend-in-%s', $row['currency_code']),
'value' => $left,
'currency_id' => (string) $row['currency_id'],
'currency_code' => $row['currency_code'],
'currency_symbol' => $row['currency_symbol'],
'currency_decimal_places' => (int) $row['currency_decimal_places'],
];
// left (native)
$nativeLeft['value'] = $leftNative;
// left per day:
$return[] = [
'key' => sprintf('left-per-day-to-spend-in-%s', $row['currency_code']),
'value' => $perDay,
'currency_id' => (string) $row['currency_id'],
'currency_code' => $row['currency_code'],
'currency_symbol' => $row['currency_symbol'],
'currency_decimal_places' => (int) $row['currency_decimal_places'],
];
// left per day (native)
$nativePerDay['value'] = $perDayNative;
}
$return[] = $nativeLeft;
$return[] = $nativePerDay;
$converter->summarize();
return $return;
}
private function getNetWorthInfo(Carbon $start, Carbon $end): array
{
/** @var UserGroup $userGroup */
$userGroup = auth()->user()->userGroup;
$date = today(config('app.timezone'))->startOfDay();
// start and end in the future? use $end
if ($this->notInDateRange($date, $start, $end)) {
/** @var Carbon $date */
$date = session('end', today(config('app.timezone'))->endOfMonth());
}
/** @var NetWorthInterface $netWorthHelper */
$netWorthHelper = app(NetWorthInterface::class);
$netWorthHelper->setUserGroup($userGroup);
$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(
function (Account $account) {
$includeNetWorth = $this->accountRepository->getMetaValue($account, 'include_net_worth');
return null === $includeNetWorth || '1' === $includeNetWorth;
}
);
$netWorthSet = $netWorthHelper->byAccounts($filtered, $date);
$return = [];
// in native amount
$return[] = [
'key' => 'net-worth-in-native',
'value' => $netWorthSet['native']['balance'],
'currency_id' => (string) $netWorthSet['native']['currency_id'],
'currency_code' => $netWorthSet['native']['currency_code'],
'currency_symbol' => $netWorthSet['native']['currency_symbol'],
'currency_decimal_places' => $netWorthSet['native']['currency_decimal_places'],
];
foreach ($netWorthSet as $key => $data) {
if ('native' === $key) {
continue;
}
$return[] = [
'key' => sprintf('net-worth-in-%s', $data['currency_code']),
'value' => $data['balance'],
'currency_id' => (string) $data['currency_id'],
'currency_code' => $data['currency_code'],
'currency_symbol' => $data['currency_symbol'],
'currency_decimal_places' => $data['currency_decimal_places'],
];
}
return $return;
}
/**
* Check if date is outside session range.
*/
protected function notInDateRange(Carbon $date, Carbon $start, Carbon $end): bool // Validate a preference
{
if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) {
return true;
}
// start and end in the past? use $end
if ($start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date)) {
return true;
}
return false;
}
}

View File

@@ -1,86 +0,0 @@
<?php
/*
* NetWorthController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Summary;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\SingleDateRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Helpers\Report\NetWorthInterface;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse;
/**
* Class NetWorthController
*/
class NetWorthController extends Controller
{
use ValidatesUserGroupTrait;
private NetWorthInterface $netWorth;
private AccountRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->netWorth = app(NetWorthInterface::class);
$this->repository = app(AccountRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
$this->netWorth->setUserGroup($userGroup);
$this->repository->setUserGroup($userGroup);
return $next($request);
}
);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/net-worth/getNetWorth
*/
public function get(SingleDateRequest $request): JsonResponse
{
$date = $request->getDate();
$accounts = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value]);
// filter list on preference of being included.
$filtered = $accounts->filter(
function (Account $account) {
$includeNetWorth = $this->repository->getMetaValue($account, 'include_net_worth');
return null === $includeNetWorth || '1' === $includeNetWorth;
}
);
// skip accounts that should not be in the net worth
$result = $this->netWorth->byAccounts($filtered, $date);
return response()->api($result);
}
}

View File

@@ -1,30 +0,0 @@
<?php
/*
* ConfigurationController.php
* Copyright (c) 2022 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\V2\Controllers\System;
/**
* Class ConfigurationController
*/
class ConfigurationController {}

View File

@@ -1,32 +0,0 @@
<?php
/*
* DebugController.php
* Copyright (c) 2022 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\V2\Controllers\System;
use FireflyIII\Api\V2\Controllers\Controller;
/**
* Class DebugController
*/
class DebugController extends Controller {}

View File

@@ -1,48 +0,0 @@
<?php
/*
* PreferencesController.php
* Copyright (c) 2022 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\V2\Controllers\System;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Models\Preference;
use FireflyIII\Transformers\PreferenceTransformer;
use Illuminate\Http\JsonResponse;
/**
* Class PreferencesController
*/
class PreferencesController extends Controller
{
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/preferences/getPreference
*/
public function get(Preference $preference): JsonResponse
{
return response()
->json($this->jsonApiObject('preferences', $preference, new PreferenceTransformer()))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,32 +0,0 @@
<?php
/*
* VersionUpdateController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\System;
use FireflyIII\Api\V2\Controllers\Controller;
/**
* Class VersionUpdateController
*/
class VersionUpdateController extends Controller {}

View File

@@ -1,89 +0,0 @@
<?php
/*
* AccountController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Transaction\List;
use Carbon\Carbon;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\Transaction\ListRequest;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Account;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\TransactionGroupTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
/**
* Class AccountController
*/
class AccountController extends Controller
{
use TransactionFilter;
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v2)#/accounts/listTransactionByAccount
*/
public function list(ListRequest $request, Account $account): JsonResponse
{
// collect transactions:
$page = $request->getPage();
$page = max($page, 1);
$pageSize = $this->parameters->get('limit');
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))
->withAPIInformation()
->setLimit($pageSize)
->setPage($page)
->setTypes($request->getTransactionTypes())
;
$start = $request->getStartDate();
$end = $request->getEndDate();
if ($start instanceof Carbon) {
app('log')->debug(sprintf('Set start date to %s', $start->toIso8601String()));
$collector->setStart($start);
}
if ($end instanceof Carbon) {
app('log')->debug(sprintf('Set end date to %s', $start->toIso8601String()));
$collector->setEnd($end);
}
$paginator = $collector->getPaginatedGroups();
$paginator->setPath(
sprintf(
'%s?%s',
route('api.v2.accounts.transactions', [$account->id]),
$request->buildParams($pageSize)
)
);
return response()
->json($this->jsonApiList('transactions', $paginator, new TransactionGroupTransformer()))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,120 +0,0 @@
<?php
/*
* TransactionController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Transaction\List;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\Transaction\InfiniteListRequest;
use FireflyIII\Api\V2\Request\Model\Transaction\ListRequest;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Transformers\TransactionGroupTransformer;
use Illuminate\Http\JsonResponse;
/**
* Class TransactionController
*/
class TransactionController extends Controller
{
public function infiniteList(InfiniteListRequest $request): JsonResponse
{
// get sort instructions
$instructions = $request->getSortInstructions('transactions');
// collect transactions:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUserGroup(auth()->user()->userGroup)
->withAPIInformation()
->setStartRow($request->getStartRow())
->setEndRow($request->getEndRow())
->setTypes($request->getTransactionTypes())
->setSorting($instructions)
;
$start = $this->parameters->get('start');
$end = $this->parameters->get('end');
if (null !== $start) {
$collector->setStart($start);
}
if (null !== $end) {
$collector->setEnd($end);
}
$paginator = $collector->getPaginatedGroups();
$params = $request->buildParams();
$paginator->setPath(
sprintf(
'%s?%s',
route('api.v2.infinite.transactions.list'),
$params
)
);
return response()
->json($this->jsonApiList('transactions', $paginator, new TransactionGroupTransformer()))
->header('Content-Type', self::CONTENT_TYPE)
;
}
public function list(ListRequest $request): JsonResponse
{
// collect transactions:
$pageSize = $this->parameters->get('limit');
$page = $request->getPage();
$page = max($page, 1);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUserGroup(auth()->user()->userGroup)
->withAPIInformation()
->setLimit($pageSize)
->setPage($page)
->setTypes($request->getTransactionTypes())
;
$start = $this->parameters->get('start');
$end = $this->parameters->get('end');
if (null !== $start) {
$collector->setStart($start);
}
if (null !== $end) {
$collector->setEnd($end);
}
$paginator = $collector->getPaginatedGroups();
$params = $request->buildParams($pageSize);
$paginator->setPath(
sprintf(
'%s?%s',
route('api.v2.transactions.list'),
$params
)
);
return response()
->json($this->jsonApiList('transactions', $paginator, new TransactionGroupTransformer()))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,32 +0,0 @@
<?php
/*
* BillController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Transaction\Sum;
use FireflyIII\Api\V2\Controllers\Controller;
/**
* Class BillController
*/
class BillController extends Controller {}

View File

@@ -1,68 +0,0 @@
<?php
/*
* DestroyController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\UserGroup;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Class DestroyController
*/
class DestroyController extends Controller
{
private UserGroupRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(UserGroupRepositoryInterface::class);
return $next($request);
}
);
}
public function destroy(UserGroup $userGroup): JsonResponse
{
/** @var User $user */
$user = auth()->user();
// to access this function: must be group owner or sysadmin.
// need owner role or system owner role to delete user group.
$access = $user->hasSpecificRoleInGroup($userGroup, UserRoleEnum::OWNER) || $user->hasRole('owner');
if (false === $access) {
throw new NotFoundHttpException();
}
$this->repository->destroy($userGroup);
return response()->json([], 204);
}
}

View File

@@ -1,74 +0,0 @@
<?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\V2\Controllers\UserGroup;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\Account\IndexRequest;
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);
}
);
}
/**
* TODO see autocomplete/accountcontroller for list.
*/
public function index(IndexRequest $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)
;
}
}

View File

@@ -1,88 +0,0 @@
<?php
/*
* ShowController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\UserGroup;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\Transformers\UserGroupTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
/**
* Class ShowController
*/
class ShowController extends Controller
{
private UserGroupRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(UserGroupRepositoryInterface::class);
return $next($request);
}
);
}
public function index(): JsonResponse
{
$collection = new Collection();
$pageSize = $this->parameters->get('limit');
// if the user has the system owner role, get all. Otherwise, get only the users' groups.
if (!auth()->user()->hasRole('owner')) {
$collection = $this->repository->get();
}
if (auth()->user()->hasRole('owner')) {
$collection = $this->repository->getAll();
}
$count = $collection->count();
$userGroups = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($userGroups, $count, $pageSize, $this->parameters->get('page'));
$transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList('user-groups', $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
public function show(UserGroup $userGroup): JsonResponse
{
$transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('user-groups', $userGroup, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,64 +0,0 @@
<?php
/*
* StoreController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\UserGroup;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\UserGroup\StoreRequest;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\Transformers\UserGroupTransformer;
use Illuminate\Http\JsonResponse;
/**
* Class StoreController
*/
class StoreController extends Controller
{
private UserGroupRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(UserGroupRepositoryInterface::class);
return $next($request);
}
);
}
public function store(StoreRequest $request): JsonResponse
{
$all = $request->getAll();
$userGroup = $this->repository->store($all);
$transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('user-groups', $userGroup, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
}

View File

@@ -1,90 +0,0 @@
<?php
/*
* UpdateController.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\UserGroup;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\UserGroup\UpdateMembershipRequest;
use FireflyIII\Api\V2\Request\UserGroup\UpdateRequest;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\Transformers\UserGroupTransformer;
use Illuminate\Http\JsonResponse;
/**
* Class UpdateController
*/
class UpdateController extends Controller
{
// basic update van group
// add user, add rights, remove user, remove rights.
private UserGroupRepositoryInterface $repository;
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
{
$all = $request->getAll();
$userGroup = $this->repository->update($userGroup, $all);
$transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('user-groups', $userGroup, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
public function updateMembership(UpdateMembershipRequest $request, UserGroup $userGroup): JsonResponse
{
$all = $request->getAll();
$userGroup = $this->repository->updateMembership($userGroup, $all);
$transformer = new UserGroupTransformer();
$transformer->setParameters($this->parameters);
return response()
->api($this->jsonApiObject('user-groups', $userGroup, $transformer))
->header('Content-Type', self::CONTENT_TYPE)
;
}
public function useUserGroup(UserGroup $userGroup): JsonResponse
{
// group validation is already in place, so can just update the user.
$this->repository->useUserGroup($userGroup);
return response()->json([], 204);
}
}

View File

@@ -1,97 +0,0 @@
<?php
/*
* AutocompleteRequest.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Autocomplete;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class AutocompleteRequest
*/
class AutocompleteRequest extends FormRequest
{
use AccountFilter;
use ChecksLogin;
use ConvertsDataTypes;
/**
* Loops over all possible query parameters (these are shared over ALL auto complete requests)
* and returns a validated array of parameters.
*
* The advantage is a single class. But you may also submit "account types" to an endpoint that doesn't use these.
*/
public function getParameters(): array
{
$array = [
'date' => $this->convertDateTime('date'),
'query' => $this->clearString((string) $this->get('query')),
'size' => $this->integerFromValue('size'),
'page' => $this->integerFromValue('page'),
'account_types' => $this->arrayFromValue($this->get('account_types')),
'transaction_types' => $this->arrayFromValue($this->get('transaction_types')),
];
$array['size'] = $array['size'] < 1 || $array['size'] > 100 ? 15 : $array['size'];
$array['page'] = max($array['page'], 1);
if (null === $array['account_types']) {
$array['account_types'] = [];
}
if (null === $array['transaction_types']) {
$array['transaction_types'] = [];
}
// remove 'initial balance' from allowed types. its internal
$array['account_types'] = array_diff($array['account_types'], [AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::RECONCILIATION->value, AccountTypeEnum::CREDITCARD->value]);
$array['account_types'] = $this->getAccountTypeParameter($array['account_types']);
return $array;
}
private function getAccountTypeParameter(array $types): array
{
$return = [];
foreach ($types as $type) {
$return = array_merge($return, $this->mapAccountTypes($type));
}
return array_unique($return);
}
public function rules(): array
{
$valid = array_keys($this->types);
return [
'date' => 'nullable|date|after:1970-01-02|before:2038-01-17',
'query' => 'nullable|string',
'size' => 'nullable|integer|min:1|max:100',
'page' => 'nullable|integer|min:1',
'account_types' => sprintf('nullable|in:%s', implode(',', $valid)),
'transaction_types' => 'nullable|in:todo',
];
}
}

View File

@@ -1,90 +0,0 @@
<?php
/*
* BalanceChartRequest.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Chart;
use Illuminate\Contracts\Validation\Validator;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Log;
/**
* Class BalanceChartRequest
*/
class BalanceChartRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
/**
* Get all data from the request.
*/
public function getAll(): array
{
return [
'accounts' => $this->getAccountList(),
'period' => $this->convertString('period'),
];
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'start' => 'required|date|after:1970-01-02|before:2038-01-17',
'end' => 'required|date|after_or_equal:start|before:2038-01-17|after:1970-01-02',
'accounts.*' => 'required|exists:accounts,id',
'period' => sprintf('required|in:%s', implode(',', config('firefly.valid_view_ranges'))),
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
static function (Validator $validator): void {
// validate transaction query data.
$data = $validator->getData();
if (!array_key_exists('accounts', $data)) {
$validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts']));
return;
}
if (!is_array($data['accounts'])) {
$validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts']));
}
}
);
if ($validator->fails()) {
Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray());
}
}
}

View File

@@ -1,92 +0,0 @@
<?php
/*
* DashboardChartRequest.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Chart;
use Illuminate\Contracts\Validation\Validator;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Log;
/**
* Class ChartRequest
*/
class ChartRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
public function getParameters(): array
{
// $queryParameters = QueryParameters::cast($this->all());
return [
'start' => $this->convertDateTime('start')?->startOfDay(),
'end' => $this->convertDateTime('end')?->endOfDay(),
'preselected' => $this->convertString('preselected', 'empty'),
'period' => $this->convertString('period', '1M'),
'accounts' => $this->arrayFromValue($this->get('accounts')),
];
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'start' => 'required|date|after:1970-01-02|before:2038-01-17|before_or_equal:end',
'end' => 'required|date|after:1970-01-02|before:2038-01-17|after_or_equal:start',
'preselected' => sprintf('nullable|in:%s', implode(',', config('firefly.preselected_accounts'))),
'period' => sprintf('nullable|in:%s', implode(',', config('firefly.valid_view_ranges'))),
'accounts.*' => 'exists:accounts,id',
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
static function (Validator $validator): void {
// validate transaction query data.
$data = $validator->getData();
if (!array_key_exists('accounts', $data)) {
// $validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts']));
return;
}
if (!is_array($data['accounts'])) {
$validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts']));
}
}
);
if ($validator->fails()) {
Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray());
}
}
}

View File

@@ -1,89 +0,0 @@
<?php
/*
* DashboardChartRequest.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Chart;
use Illuminate\Contracts\Validation\Validator;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Log;
/**
* Class DashboardChartRequest
*/
class DashboardChartRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
/**
* Get all data from the request.
*/
public function getAll(): array
{
return [
'accounts' => $this->getAccountList(),
'preselected' => $this->convertString('preselected'),
];
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'start' => 'required|date|after:1970-01-02|before:2038-01-17',
'end' => 'required|date|after_or_equal:start|before:2038-01-17|after:1970-01-02',
'preselected' => sprintf('in:%s', implode(',', config('firefly.preselected_accounts'))),
'accounts.*' => 'exists:accounts,id',
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
static function (Validator $validator): void {
// validate transaction query data.
$data = $validator->getData();
if (!array_key_exists('accounts', $data)) {
// $validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts']));
return;
}
if (!is_array($data['accounts'])) {
$validator->errors()->add('accounts', trans('validation.filled', ['attribute' => 'accounts']));
}
}
);
if ($validator->fails()) {
Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray());
}
}
}

View File

@@ -1,62 +0,0 @@
<?php
/*
* DateRequest.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Generic;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Request class for end points that require date parameters.
*
* Class DateRequest
*/
class DateRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
/**
* Get all data from the request.
*/
public function getAll(): array
{
return [
'start' => $this->getCarbonDate('start')->startOfDay(),
'end' => $this->getCarbonDate('end')->endOfDay(),
];
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'start' => 'required|date|after:1970-01-02|before:2038-01-17',
'end' => 'required|date|after_or_equal:start|before:2038-01-17|after:1970-01-02',
];
}
}

View File

@@ -1,59 +0,0 @@
<?php
/*
* DateRequest.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Generic;
use Carbon\Carbon;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Request class for end points that require a date parameter.
*
* Class SingleDateRequest
*/
class SingleDateRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
/**
* Get all data from the request.
*/
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:1970-01-02|before:2038-01-17',
];
}
}

View File

@@ -1,71 +0,0 @@
<?php
/*
* IndexRequest.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\V2\Request\Model\Account;
use Carbon\Carbon;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetFilterInstructions;
use FireflyIII\Support\Request\GetSortInstructions;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class IndexRequest
*
* Lots of code stolen from the SingleDateRequest.
*/
class IndexRequest extends FormRequest
{
use AccountFilter;
use ChecksLogin;
use ConvertsDataTypes;
use GetFilterInstructions;
use GetSortInstructions;
public function getAccountTypes(): array
{
$type = (string) $this->get('type', 'default');
return $this->mapAccountTypes($type);
}
public function getDate(): Carbon
{
return $this->getCarbonDate('date');
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'date' => 'date|after:1970-01-02|before:2038-01-17',
'start' => 'date|after:1970-01-02|before:2038-01-17|before:end|required_with:end',
'end' => 'date|after:1970-01-02|before:2038-01-17|after:start|required_with:start',
];
}
}

View File

@@ -1,117 +0,0 @@
<?php
/*
* UpdateRequest.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\V2\Request\Model\Account;
use FireflyIII\Models\Account;
use FireflyIII\Models\Location;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\UniqueAccountNumber;
use FireflyIII\Rules\UniqueIban;
use FireflyIII\Support\Request\AppendsLocationData;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
class UpdateRequest extends FormRequest
{
use AppendsLocationData;
use ChecksLogin;
use ConvertsDataTypes;
/**
* TODO is a duplicate of the v1 update thing.
*/
public function getUpdateData(): array
{
$fields = [
'name' => ['name', 'convertString'],
'active' => ['active', 'boolean'],
'include_net_worth' => ['include_net_worth', 'boolean'],
'account_type_name' => ['type', 'convertString'],
'virtual_balance' => ['virtual_balance', 'convertString'],
'iban' => ['iban', 'convertString'],
'BIC' => ['bic', 'convertString'],
'account_number' => ['account_number', 'convertString'],
'account_role' => ['account_role', 'convertString'],
'liability_type' => ['liability_type', 'convertString'],
'opening_balance' => ['opening_balance', 'convertString'],
'opening_balance_date' => ['opening_balance_date', 'convertDateTime'],
'cc_type' => ['credit_card_type', 'convertString'],
'cc_monthly_payment_date' => ['monthly_payment_date', 'convertDateTime'],
'notes' => ['notes', 'stringWithNewlines'],
'interest' => ['interest', 'convertString'],
'interest_period' => ['interest_period', 'convertString'],
'order' => ['order', 'convertInteger'],
'currency_id' => ['currency_id', 'convertInteger'],
'currency_code' => ['currency_code', 'convertString'],
'liability_direction' => ['liability_direction', 'convertString'],
'liability_amount' => ['liability_amount', 'convertString'],
'liability_start_date' => ['liability_start_date', 'date'],
];
$data = $this->getAllData($fields);
return $this->appendLocationData($data, null);
}
/**
* TODO is a duplicate of the v1 UpdateRequest method.
*
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
/** @var Account $account */
$account = $this->route()->parameter('account');
$accountRoles = implode(',', config('firefly.accountRoles'));
$types = implode(',', array_keys(config('firefly.subTitlesByIdentifier')));
$ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes')));
$rules = [
'name' => sprintf('min:1|max:1024|uniqueAccountForUser:%d', $account->id),
'type' => sprintf('in:%s', $types),
'iban' => ['iban', 'nullable', new UniqueIban($account, $this->convertString('type'))],
'bic' => 'bic|nullable',
'account_number' => ['min:1', 'max:255', 'nullable', new UniqueAccountNumber($account, $this->convertString('type'))],
'opening_balance' => 'numeric|required_with:opening_balance_date|nullable',
'opening_balance_date' => 'date|required_with:opening_balance|nullable',
'virtual_balance' => 'numeric|nullable',
'order' => 'numeric|nullable',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
'active' => [new IsBoolean()],
'include_net_worth' => [new IsBoolean()],
'account_role' => sprintf('in:%s|nullable|required_if:type,asset', $accountRoles),
'credit_card_type' => sprintf('in:%s|nullable|required_if:account_role,ccAsset', $ccPaymentTypes),
'monthly_payment_date' => 'date|nullable|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull',
'liability_type' => 'required_if:type,liability|in:loan,debt,mortgage',
'liability_direction' => 'required_if:type,liability|in:credit,debit',
'interest' => 'required_if:type,liability|min:0|max:100|numeric',
'interest_period' => 'required_if:type,liability|in:daily,monthly,yearly',
'notes' => 'min:0|max:32768',
];
return Location::requestRules($rules);
}
}

View File

@@ -1,118 +0,0 @@
<?php
/*
* ListRequest.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Model\Transaction;
use Carbon\Carbon;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetSortInstructions;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class InfiniteListRequest
* Used specifically to list transactions.
*/
class InfiniteListRequest extends FormRequest
{
use AccountFilter;
use ChecksLogin;
use ConvertsDataTypes;
use GetSortInstructions;
use TransactionFilter;
public function buildParams(): string
{
$array = [
'start_row' => $this->getStartRow(),
'end_row' => $this->getEndRow(),
];
$start = $this->getStartDate();
$end = $this->getEndDate();
if ($start instanceof Carbon && $end instanceof Carbon) {
$array['start'] = $start->format('Y-m-d');
$array['end'] = $end->format('Y-m-d');
}
return http_build_query($array);
}
public function getStartRow(): int
{
$startRow = $this->convertInteger('start_row');
return $startRow < 0 || $startRow > 4294967296 ? 0 : $startRow;
}
public function getEndRow(): int
{
$endRow = $this->convertInteger('end_row');
return $endRow <= 0 || $endRow > 4294967296 ? 100 : $endRow;
}
public function getStartDate(): ?Carbon
{
return $this->getCarbonDate('start');
}
public function getEndDate(): ?Carbon
{
return $this->getCarbonDate('end');
}
public function getAccountTypes(): array
{
$type = (string) $this->get('type', 'default');
return $this->mapAccountTypes($type);
}
public function getPage(): int
{
$page = $this->convertInteger('page');
return 0 === $page || $page > 65536 ? 1 : $page;
}
public function getTransactionTypes(): array
{
$type = (string) $this->get('type', 'default');
return $this->mapTransactionTypes($type);
}
public function rules(): array
{
return [
'start' => 'date|after:1970-01-02|before:2038-01-17',
'end' => 'date|after:start|after:1970-01-02|before:2038-01-17',
'start_row' => 'integer|min:0|max:4294967296',
'end_row' => 'integer|min:0|max:4294967296|gt:start_row',
];
}
}

View File

@@ -1,91 +0,0 @@
<?php
/*
* ListRequest.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Model\Transaction;
use Carbon\Carbon;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class ListRequest
* Used specifically to list transactions.
*/
class ListRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
use TransactionFilter;
public function buildParams(int $pageSize): string
{
$array = [
'page' => $this->getPage(),
'limit' => $pageSize,
];
$start = $this->getStartDate();
$end = $this->getEndDate();
if ($start instanceof Carbon && $end instanceof Carbon) {
$array['start'] = $start->format('Y-m-d');
$array['end'] = $end->format('Y-m-d');
}
return http_build_query($array);
}
public function getPage(): int
{
$page = $this->convertInteger('page');
return 0 === $page || $page > 65536 ? 1 : $page;
}
public function getStartDate(): ?Carbon
{
return $this->getCarbonDate('start');
}
public function getEndDate(): ?Carbon
{
return $this->getCarbonDate('end');
}
public function getTransactionTypes(): array
{
$type = (string) $this->get('type', 'default');
return $this->mapTransactionTypes($type);
}
public function rules(): array
{
return [
'start' => 'date|after:1970-01-02|before:2038-01-17',
'end' => 'date|after:start|after:1970-01-02|before:2038-01-17',
];
}
}

View File

@@ -1,317 +0,0 @@
<?php
/*
* StoreRequest.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Model\Transaction;
use Illuminate\Contracts\Validation\Validator;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\UserGroup;
use FireflyIII\Rules\BelongsUserGroup;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsDateOrTime;
use FireflyIII\Rules\IsValidPositiveAmount;
use FireflyIII\Support\NullArrayObject;
use FireflyIII\Support\Request\AppendsLocationData;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\User;
use FireflyIII\Validation\CurrencyValidation;
use FireflyIII\Validation\GroupValidation;
use FireflyIII\Validation\TransactionValidation;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Log;
/**
* Class StoreRequest
*
* TODO this class is basically the same as the v1 request. However, it does not accept
* TODO models, objects and references that are NOT part of the designated user group (aka administration).
* TODO this distinction is already made in the CheckLogin trait, where there is also a convenient function
* TODO to grab the current UserGroup. This code is slightly different from other v2 apis that use
* TODO the "administration_id", those will have to be updated later on.
*/
class StoreRequest extends FormRequest
{
use AppendsLocationData;
use ChecksLogin;
use ConvertsDataTypes;
use CurrencyValidation;
use GroupValidation;
use TransactionValidation;
protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS];
/**
* Get all data.
*/
public function getAll(): array
{
app('log')->debug('V2: Get all data in TransactionStoreRequest');
return [
'group_title' => $this->convertString('group_title'),
'error_if_duplicate_hash' => $this->boolean('error_if_duplicate_hash'),
'apply_rules' => $this->boolean('apply_rules', true),
'fire_webhooks' => $this->boolean('fire_webhooks', true),
'transactions' => $this->getTransactionData(),
];
}
/**
* Get transaction data.
*/
private function getTransactionData(): array
{
$return = [];
/**
* @var array $transaction
*/
foreach ($this->get('transactions') as $transaction) {
$object = new NullArrayObject($transaction);
$result = [
'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']),
// foreign currency info:
'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']),
// 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->clearString((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->clearString((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']),
// category info
'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']),
// 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']),
// some other interesting properties
'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']),
'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']),
];
$result = $this->addFromromTransactionStore($transaction, $result);
$return[] = $result;
}
return $return;
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
app('log')->debug('V2: Collect rules of TransactionStoreRequest');
// at this point the userGroup can't be NULL because the
// authorize() method will complain. Loudly.
/** @var UserGroup $userGroup */
$userGroup = $this->getUserGroup();
return [
// basic fields for group:
'group_title' => 'min:1|max:1000|nullable',
'error_if_duplicate_hash' => [new IsBoolean()],
'apply_rules' => [new IsBoolean()],
// transaction rules (in array for splits):
'transactions.*.type' => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation',
'transactions.*.date' => ['required', new IsDateOrTime()],
'transactions.*.order' => 'numeric|min:0',
// currency info
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
'transactions.*.currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
'transactions.*.foreign_currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
// amount
'transactions.*.amount' => ['required', new IsValidPositiveAmount()],
'transactions.*.foreign_amount' => ['nullable', new IsValidPositiveAmount()],
// description
'transactions.*.description' => 'nullable|min:1|max:1000',
// source of transaction
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUserGroup($userGroup)],
'transactions.*.source_name' => 'min:1|max:255|nullable',
'transactions.*.source_iban' => 'min:1|max:255|nullable|iban',
'transactions.*.source_number' => 'min:1|max:255|nullable',
'transactions.*.source_bic' => 'min:1|max:255|nullable|bic',
// destination of transaction
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUserGroup($userGroup)],
'transactions.*.destination_name' => 'min:1|max:255|nullable',
'transactions.*.destination_iban' => 'min:1|max:255|nullable|iban',
'transactions.*.destination_number' => 'min:1|max:255|nullable',
'transactions.*.destination_bic' => 'min:1|max:255|nullable|bic',
// budget, category, bill and piggy
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUserGroup($userGroup)],
'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)],
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUserGroup($userGroup), 'nullable'],
'transactions.*.category_name' => 'min:1|max:255|nullable',
'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUserGroup($userGroup)],
'transactions.*.bill_name' => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)],
'transactions.*.piggy_bank_id' => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUserGroup($userGroup)],
'transactions.*.piggy_bank_name' => ['min:1', 'max:255', 'nullable', new BelongsUserGroup($userGroup)],
// other interesting fields
'transactions.*.reconciled' => [new IsBoolean()],
'transactions.*.notes' => 'min:1|max:32768|nullable',
'transactions.*.tags' => 'min:0|max:255',
'transactions.*.tags.*' => 'min:0|max:255',
// meta info fields
'transactions.*.internal_reference' => 'min:1|max:255|nullable',
'transactions.*.external_id' => 'min:1|max:255|nullable',
'transactions.*.recurrence_id' => 'min:1|max:255|nullable',
'transactions.*.bunq_payment_id' => 'min:1|max:255|nullable',
'transactions.*.external_url' => 'min:1|max:255|nullable|url',
// SEPA fields:
'transactions.*.sepa_cc' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_op' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_id' => 'min:1|max:255|nullable',
'transactions.*.sepa_db' => 'min:1|max:255|nullable',
'transactions.*.sepa_country' => 'min:1|max:255|nullable',
'transactions.*.sepa_ep' => 'min:1|max:255|nullable',
'transactions.*.sepa_ci' => 'min:1|max:255|nullable',
'transactions.*.sepa_batch_id' => 'min:1|max:255|nullable',
// dates
'transactions.*.interest_date' => 'date|nullable',
'transactions.*.book_date' => 'date|nullable',
'transactions.*.process_date' => 'date|nullable',
'transactions.*.due_date' => 'date|nullable',
'transactions.*.payment_date' => 'date|nullable',
'transactions.*.invoice_date' => 'date|nullable',
// TODO include location and ability to process it.
];
}
/**
* Configure the validator instance.
*/
public function withValidator(Validator $validator): void
{
/** @var User $user */
$user = auth()->user();
/** @var UserGroup $userGroup */
$userGroup = $this->getUserGroup();
$validator->after(
function (Validator $validator) use ($user, $userGroup): void {
// must be valid array.
$this->validateTransactionArray($validator); // does not need group validation.
// must submit at least one transaction.
app('log')->debug('Now going to validateOneTransaction');
$this->validateOneTransaction($validator); // does not need group validation.
app('log')->debug('Now done with validateOneTransaction');
// all journals must have a description
$this->validateDescriptions($validator); // does not need group validation.
// all transaction types must be equal:
$this->validateTransactionTypes($validator); // does not need group validation.
// validate foreign currency info
$this->validateForeignCurrencyInformation($validator); // does not need group validation.
// validate all account info
$this->validateAccountInformation($validator, $user, $userGroup);
// validate source/destination is equal, depending on the transaction journal type.
$this->validateEqualAccounts($validator);
// the group must have a description if > 1 journal.
$this->validateGroupDescription($validator);
}
);
if ($validator->fails()) {
Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray());
}
}
}

View File

@@ -1,371 +0,0 @@
<?php
/*
* UpdateRequest.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\V2\Request\Model\Transaction;
use Illuminate\Contracts\Validation\Validator;
use Override;
use FireflyIII\Api\V1\Requests\Models\AvailableBudget\Request;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsDateOrTime;
use FireflyIII\Rules\IsValidPositiveAmount;
use FireflyIII\Rules\IsValidZeroOrMoreAmount;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Validation\GroupValidation;
use FireflyIII\Validation\TransactionValidation;
use Illuminate\Support\Facades\Log;
/**
* Class UpdateRequest
*
* TODO it's the same as the v1
*/
class UpdateRequest extends Request
{
use ChecksLogin;
use ConvertsDataTypes;
use GroupValidation;
use TransactionValidation;
private array $arrayFields;
private array $booleanFields;
private array $dateFields;
private array $floatFields;
private array $integerFields;
private array $stringFields;
private array $textareaFields;
/**
* Get all data. Is pretty complex because of all the ??-statements.
*
* @throws FireflyException
*/
#[Override]
public function getAll(): array
{
Log::debug(sprintf('Now in %s', __METHOD__));
$this->integerFields = ['order', 'currency_id', 'foreign_currency_id', 'transaction_journal_id', 'source_id', 'destination_id', 'budget_id', 'category_id', 'bill_id', 'recurrence_id'];
$this->dateFields = ['date', 'interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];
$this->textareaFields = ['notes'];
// not really floats, for validation.
$this->floatFields = ['amount', 'foreign_amount'];
$this->stringFields = ['type', 'currency_code', 'foreign_currency_code', 'description', 'source_name', 'source_iban', 'source_number', 'source_bic', 'destination_name', 'destination_iban', 'destination_number', 'destination_bic', 'budget_name', 'category_name', 'bill_name', 'internal_reference', 'external_id', 'bunq_payment_id', 'sepa_cc', 'sepa_ct_op', 'sepa_ct_id', 'sepa_db', 'sepa_country', 'sepa_ep', 'sepa_ci', 'sepa_batch_id', 'external_url'];
$this->booleanFields = ['reconciled'];
$this->arrayFields = ['tags'];
$data = [];
if ($this->has('transactions')) {
$data['transactions'] = $this->getTransactionData();
}
if ($this->has('apply_rules')) {
$data['apply_rules'] = $this->boolean('apply_rules', true);
}
if ($this->has('fire_webhooks')) {
$data['fire_webhooks'] = $this->boolean('fire_webhooks', true);
}
if ($this->has('group_title')) {
$data['group_title'] = $this->convertString('group_title');
}
return $data;
}
/**
* Get transaction data.
*
* @throws FireflyException
*/
private function getTransactionData(): array
{
Log::debug(sprintf('Now in %s', __METHOD__));
$return = [];
/** @var null|array $transactions */
$transactions = $this->get('transactions');
if (!is_countable($transactions)) {
return $return;
}
/** @var null|array $transaction */
foreach ($transactions as $transaction) {
if (!is_array($transaction)) {
throw new FireflyException('Invalid data submitted: transaction is not array.');
}
// default response is to update nothing in the transaction:
$current = [];
$current = $this->getIntegerData($current, $transaction);
$current = $this->getStringData($current, $transaction);
$current = $this->getNlStringData($current, $transaction);
$current = $this->getDateData($current, $transaction);
$current = $this->getBooleanData($current, $transaction);
$current = $this->getArrayData($current, $transaction);
$current = $this->getFloatData($current, $transaction);
$return[] = $current;
}
return $return;
}
/**
* For each field, add it to the array if a reference is present in the request:
*
* @param array<string, string> $current
* @param array<string, mixed> $transaction
*/
private function getIntegerData(array $current, array $transaction): array
{
foreach ($this->integerFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->integerFromValue((string) $transaction[$fieldName]);
}
}
return $current;
}
/**
* @param array<string, string> $current
* @param array<string, mixed> $transaction
*/
private function getStringData(array $current, array $transaction): array
{
foreach ($this->stringFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->clearString((string) $transaction[$fieldName]);
}
}
return $current;
}
/**
* @param array<string, string> $current
* @param array<string, mixed> $transaction
*/
private function getNlStringData(array $current, array $transaction): array
{
foreach ($this->textareaFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->clearStringKeepNewlines((string) $transaction[$fieldName]); // keep newlines
}
}
return $current;
}
/**
* @param array<string, string> $current
* @param array<string, mixed> $transaction
*/
private function getDateData(array $current, array $transaction): array
{
foreach ($this->dateFields as $fieldName) {
Log::debug(sprintf('Now at date field %s', $fieldName));
if (array_key_exists($fieldName, $transaction)) {
Log::debug(sprintf('New value: "%s"', $transaction[$fieldName]));
$current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
}
}
return $current;
}
/**
* @param array<string, string> $current
* @param array<string, mixed> $transaction
*/
private function getBooleanData(array $current, array $transaction): array
{
foreach ($this->booleanFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->convertBoolean((string) $transaction[$fieldName]);
}
}
return $current;
}
/**
* @param array<string, string> $current
* @param array<string, mixed> $transaction
*/
private function getArrayData(array $current, array $transaction): array
{
foreach ($this->arrayFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->arrayFromValue($transaction[$fieldName]);
}
}
return $current;
}
/**
* @param array<string, string> $current
* @param array<string, mixed> $transaction
*/
private function getFloatData(array $current, array $transaction): array
{
foreach ($this->floatFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$value = $transaction[$fieldName];
if (is_float($value)) {
$current[$fieldName] = sprintf('%.12f', $value);
}
if (!is_float($value)) {
$current[$fieldName] = (string) $value;
}
}
}
return $current;
}
/**
* The rules that the incoming request must be matched against.
*/
#[Override]
public function rules(): array
{
Log::debug(sprintf('Now in %s', __METHOD__));
$validProtocols = config('firefly.valid_url_protocols');
return [
// basic fields for group:
'group_title' => 'min:1|max:1000|nullable',
'apply_rules' => [new IsBoolean()],
// transaction rules (in array for splits):
'transactions.*.type' => 'in:withdrawal,deposit,transfer,opening-balance,reconciliation',
'transactions.*.date' => [new IsDateOrTime()],
'transactions.*.order' => 'numeric|min:0',
// group id:
'transactions.*.transaction_journal_id' => ['nullable', 'numeric', new BelongsUser()],
// currency info
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
'transactions.*.currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
'transactions.*.foreign_currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
// amount
'transactions.*.amount' => ['nullable', new IsValidPositiveAmount()],
'transactions.*.foreign_amount' => ['nullable', new IsValidZeroOrMoreAmount()],
// description
'transactions.*.description' => 'nullable|min:1|max:1000',
// source of transaction
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()],
'transactions.*.source_name' => 'min:1|max:255|nullable',
// destination of transaction
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()],
'transactions.*.destination_name' => 'min:1|max:255|nullable',
// budget, category, bill and piggy
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser(), 'nullable'],
'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser(), 'nullable'],
'transactions.*.category_name' => 'min:1|max:255|nullable',
'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser()],
'transactions.*.bill_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
// other interesting fields
'transactions.*.reconciled' => [new IsBoolean()],
'transactions.*.notes' => 'min:1|max:32768|nullable',
'transactions.*.tags' => 'min:0|max:255|nullable',
'transactions.*.tags.*' => 'min:0|max:255',
// meta info fields
'transactions.*.internal_reference' => 'min:1|max:255|nullable',
'transactions.*.external_id' => 'min:1|max:255|nullable',
'transactions.*.recurrence_id' => 'min:1|max:255|nullable',
'transactions.*.bunq_payment_id' => 'min:1|max:255|nullable',
'transactions.*.external_url' => sprintf('min:1|max:255|nullable|url:%s', $validProtocols),
// SEPA fields:
'transactions.*.sepa_cc' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_op' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_id' => 'min:1|max:255|nullable',
'transactions.*.sepa_db' => 'min:1|max:255|nullable',
'transactions.*.sepa_country' => 'min:1|max:255|nullable',
'transactions.*.sepa_ep' => 'min:1|max:255|nullable',
'transactions.*.sepa_ci' => 'min:1|max:255|nullable',
'transactions.*.sepa_batch_id' => 'min:1|max:255|nullable',
// dates
'transactions.*.interest_date' => 'date|nullable',
'transactions.*.book_date' => 'date|nullable',
'transactions.*.process_date' => 'date|nullable',
'transactions.*.due_date' => 'date|nullable',
'transactions.*.payment_date' => 'date|nullable',
'transactions.*.invoice_date' => 'date|nullable',
];
}
/**
* Configure the validator instance.
*/
#[Override]
public function withValidator(Validator $validator): void
{
Log::debug('Now in withValidator');
/** @var TransactionGroup $transactionGroup */
$transactionGroup = $this->route()->parameter('userGroupTransaction');
$validator->after(
function (Validator $validator) use ($transactionGroup): void {
// if more than one, verify that there are journal ID's present.
$this->validateJournalIds($validator, $transactionGroup);
// all transaction types must be equal:
$this->validateTransactionTypesForUpdate($validator);
// user wants to update a reconciled transaction.
// source, destination, amount + foreign_amount cannot be changed
// and must be omitted from the request.
$this->preventUpdateReconciled($validator, $transactionGroup);
// validate source/destination is equal, depending on the transaction journal type.
$this->validateEqualAccountsForUpdate($validator, $transactionGroup);
// see method:
// $this->preventNoAccountInfo($validator, );
// validate that the currency fits the source and/or destination account.
// validate all account info
$this->validateAccountInformationUpdate($validator, $transactionGroup);
}
);
if ($validator->fails()) {
Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray());
}
}
}

View File

@@ -1,64 +0,0 @@
<?php
/*
* IndexRequest.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\V2\Request\Model\TransactionCurrency;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetFilterInstructions;
use FireflyIII\Support\Request\GetSortInstructions;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class IndexRequest
*
* Lots of code stolen from the SingleDateRequest.
*/
class IndexRequest extends FormRequest
{
use AccountFilter;
use ChecksLogin;
use ConvertsDataTypes;
use GetFilterInstructions;
use GetSortInstructions;
public function getAll(): array
{
return [
'enabled' => $this->convertBoolean($this->get('enabled')),
];
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'enabled' => 'nullable|boolean',
];
}
}

View File

@@ -1,66 +0,0 @@
<?php
/*
* StoreRequest.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\UserGroup;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class StoreRequest
*/
class StoreRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
protected array $acceptedRoles = [UserRoleEnum::OWNER, UserRoleEnum::FULL];
public function getAll(): array
{
return [
'title' => $this->convertString('title'),
];
}
public function rules(): array
{
$roles = [];
foreach (UserRoleEnum::cases() as $role) {
$roles[] = $role->value;
}
$string = implode(',', $roles);
return [
'title' => 'unique:user_groups,title|required|min:1|max:255',
'members' => 'required|min:1',
'members.*.user_email' => 'email|missing_with:members.*.user_id',
'members.*.user_id' => 'integer|exists:users,id|missing_with:members.*.user_email',
'members.*.roles' => 'required|array|min:1',
'members.*.roles.*' => sprintf('required|in:%s', $string),
];
}
}

View File

@@ -1,64 +0,0 @@
<?php
/*
* StoreRequest.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\UserGroup;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class StoreRequest
*/
class UpdateMembershipRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
protected array $acceptedRoles = [UserRoleEnum::OWNER, UserRoleEnum::FULL];
public function getAll(): array
{
return [
'id' => $this->convertInteger('id'),
'email' => $this->convertString('email'),
'roles' => $this->get('roles') ?? [],
];
}
public function rules(): array
{
$validRoles = [];
foreach (UserRoleEnum::cases() as $role) {
$validRoles[] = $role->value;
}
return [
'id' => 'exists:users,id|required_without:email',
'email' => 'exists:users,email|required_without:id',
'roles.*' => 'required|in:'.implode(',', $validRoles),
];
}
}

View File

@@ -1,60 +0,0 @@
<?php
/*
* StoreRequest.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\UserGroup;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\UserGroup;
use FireflyIII\Rules\IsDefaultUserGroupName;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class StoreRequest
*/
class UpdateRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
protected array $acceptedRoles = [UserRoleEnum::OWNER, UserRoleEnum::FULL];
public function getAll(): array
{
return [
'title' => $this->convertString('title'),
];
}
public function rules(): array
{
/** @var UserGroup $userGroup */
$userGroup = $this->route()->parameter('userGroup');
return [
'title' => ['required', 'min:1', 'max:255', sprintf('unique:user_groups,title,%d', $userGroup->id), new IsDefaultUserGroupName($userGroup)],
];
}
}

View File

@@ -1,71 +0,0 @@
<?php
/*
* AutoSum.php
* Copyright (c) 2022 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\V2\Response\Sum;
use Closure;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionCurrency;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
/**
* Class AutoSum
*
* @deprecated
*/
class AutoSum
{
/**
* @throws FireflyException
*/
public function autoSum(Collection $objects, Closure $getCurrency, Closure $getSum): array
{
$return = [];
/** @var Model $object */
foreach ($objects as $object) {
/** @var TransactionCurrency $currency */
$currency = $getCurrency($object);
/** @var string $amount */
$amount = $getSum($object);
$return[$currency->id] ??= [
'id' => (string) $currency->id,
'name' => $currency->name,
'symbol' => $currency->symbol,
'code' => $currency->code,
'decimal_places' => $currency->decimal_places,
'sum' => '0',
];
$return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], $amount);
}
var_dump(array_values($return));
throw new FireflyException('Not implemented');
}
}

View File

@@ -86,7 +86,7 @@ class CorrectsAmounts extends Command
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {
$repository->setUser($journal->user);
$native = Amount::getNativeCurrencyByUserGroup($journal->userGroup);
$primary = Amount::getPrimaryCurrencyByUserGroup($journal->userGroup);
/** @var null|Transaction $source */
$source = $journal->transactions()->where('amount', '<', 0)->first();
@@ -104,8 +104,8 @@ class CorrectsAmounts extends Command
if (null === $sourceAccount || null === $destAccount) {
continue;
}
$sourceCurrency = $repository->getAccountCurrency($sourceAccount) ?? $native;
$destCurrency = $repository->getAccountCurrency($destAccount) ?? $native;
$sourceCurrency = $repository->getAccountCurrency($sourceAccount) ?? $primary;
$destCurrency = $repository->getAccountCurrency($destAccount) ?? $primary;
if ($sourceCurrency->id === $destCurrency->id) {
Log::debug('Both accounts have the same currency. Removing foreign currency info.');

View File

@@ -63,7 +63,7 @@ class CorrectsCurrencies extends Command
$repos = app(CurrencyRepositoryInterface::class);
// first check if the user has any default currency (not necessarily the case, so can be forced).
$defaultCurrency = app('amount')->getNativeCurrencyByUserGroup($userGroup);
$defaultCurrency = app('amount')->getPrimaryCurrencyByUserGroup($userGroup);
Log::debug(sprintf('Now correcting currencies for user group #%d', $userGroup->id));
$found = [$defaultCurrency->id];

View File

@@ -75,7 +75,7 @@ class CorrectsDatabase extends Command
'correction:recalculates-liabilities',
'correction:preferences',
// 'correction:transaction-types', // resource heavy, disabled.
'correction:recalculate-native-amounts', // not necessary, disabled.
'correction:recalculate-pc-amounts', // not necessary, disabled.
'firefly-iii:report-integrity',
];
foreach ($commands as $command) {

View File

@@ -132,6 +132,6 @@ class CorrectsOpeningBalanceCurrencies extends Command
$repos = app(AccountRepositoryInterface::class);
$repos->setUser($account->user);
return $repos->getAccountCurrency($account) ?? app('amount')->getNativeCurrencyByUserGroup($account->userGroup);
return $repos->getAccountCurrency($account) ?? app('amount')->getPrimaryCurrencyByUserGroup($account->userGroup);
}
}

View File

@@ -2,7 +2,7 @@
/*
* CorrectsNativeAmounts.php
* CorrectsPrimaryCurrencyAmounts.php
* Copyright (c) 2025 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@@ -48,13 +48,13 @@ use Illuminate\Database\Query\Builder as DatabaseBuilder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class CorrectsNativeAmounts extends Command
class CorrectsPrimaryCurrencyAmounts extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Recalculate native amounts for all objects.';
protected $description = 'Recalculate primary currency amounts for all objects.';
protected $signature = 'correction:recalculate-native-amounts';
protected $signature = 'correction:recalculate-pc-amounts';
/**
* Execute the console command.
@@ -66,8 +66,8 @@ class CorrectsNativeAmounts extends Command
return 0;
}
Log::debug('Will update all native amounts. This may take some time.');
$this->friendlyWarning('Recalculating native amounts for all objects. This may take some time!');
Log::debug('Will update all primary currency amounts. This may take some time.');
$this->friendlyWarning('Recalculating primary currency amounts for all objects. This may take some time!');
/** @var UserGroupRepositoryInterface $repository */
$repository = app(UserGroupRepositoryInterface::class);
@@ -76,7 +76,7 @@ class CorrectsNativeAmounts extends Command
foreach ($repository->getAll() as $userGroup) {
$this->recalculateForGroup($userGroup);
}
$this->friendlyInfo('Recalculated all native amounts.');
$this->friendlyInfo('Recalculated all primary currency amounts.');
return 0;
}
@@ -88,7 +88,7 @@ class CorrectsNativeAmounts extends Command
// do a check with the group's currency so we can skip some stuff.
Preferences::mark();
$currency = app('amount')->getNativeCurrencyByUserGroup($userGroup);
$currency = app('amount')->getPrimaryCurrencyByUserGroup($userGroup);
$this->recalculatePiggyBanks($userGroup, $currency);
$this->recalculateBudgets($userGroup, $currency);

View File

@@ -84,6 +84,7 @@ class OutputsInstructions extends Command
$this->newLine();
$this->showLogo();
$this->newLine();
$this->newLine();
$this->showLine();
$this->boxed('');
@@ -141,6 +142,7 @@ class OutputsInstructions extends Command
$this->line(sprintf('<fg=%s> |_| |_|_| \___|_| |_|\__, | |_____|_____|_____| </>', $colors[5]));
$this->line(sprintf('<fg=%s> __/ | </>', $colors[6]));
$this->line(sprintf('<fg=%s> |___/ </>', $colors[7]));
$this->someQuote();
}
/**
@@ -233,4 +235,17 @@ class OutputsInstructions extends Command
$this->boxed('');
$this->showLine();
}
private function someQuote(): void
{
$lines = [
'Forgive yourself for not being at peace.',
'Doesn\'t look like anything to me.',
'Be proud of what you make.',
'Be there or forever wonder.',
'A year from now you will wish you had started today.',
];
$random = random_int(0, count($lines) - 1);
$this->line(sprintf(' "%s"', $lines[$random]));
}
}

View File

@@ -108,7 +108,7 @@ class UpgradesAccountCurrencies extends Command
$accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value]);
// get user's currency preference:
$defaultCurrency = app('amount')->getNativeCurrencyByUserGroup($user->userGroup);
$defaultCurrency = app('amount')->getPrimaryCurrencyByUserGroup($user->userGroup);
/** @var Account $account */
foreach ($accounts as $account) {

View File

@@ -66,7 +66,7 @@ class UpgradesBudgetLimits extends Command
/** @var null|User $user */
$user = $budget->user;
if (null !== $user) {
$currency = app('amount')->getNativeCurrencyByUserGroup($user->userGroup);
$currency = app('amount')->getPrimaryCurrencyByUserGroup($user->userGroup);
$budgetLimit->transaction_currency_id = $currency->id;
$budgetLimit->save();
$this->friendlyInfo(

Some files were not shown because too many files have changed in this diff Show More