Compare commits

...

102 Commits

Author SHA1 Message Date
github-actions[bot]
6946a815e2 Merge pull request #10143 from firefly-iii/release-1745034848
🤖 Automatically merge the PR into the develop branch.
2025-04-19 05:54:14 +02:00
JC5
4a84e94022 🤖 Auto commit for release 'develop' on 2025-04-19 2025-04-19 05:54:08 +02:00
James Cole
5ba5d1f90e Merge pull request #10142 from firefly-iii/add-expires
Add expiry details to tokens.
2025-04-19 05:49:09 +02:00
James Cole
beb2bbcdc9 Merge pull request #10141 from firefly-iii/fix-nullpointer
Fix nullpointer in bill chart controller.
2025-04-19 05:48:37 +02:00
James Cole
805fd5ae08 Add expiry details to tokens. 2025-04-19 05:48:11 +02:00
James Cole
96093e313a Fix nullpointer in bill chart controller. 2025-04-19 05:47:43 +02:00
James Cole
afe9e88f9a Merge pull request #10133 from firefly-iii/new-currencies
Add new currencies and update exchange rates.
2025-04-15 04:59:49 +02:00
James Cole
b43048c674 Add new currencies and update exchange rates. 2025-04-15 04:54:36 +02:00
github-actions[bot]
11c38a599b Merge pull request #10127 from firefly-iii/release-1744600947
🤖 Automatically merge the PR into the develop branch.
2025-04-14 05:22:37 +02:00
JC5
0ce245f480 🤖 Auto commit for release 'develop' on 2025-04-14 2025-04-14 05:22:27 +02:00
github-actions[bot]
aef15cf3d3 Merge pull request #10119 from firefly-iii/release-1744394417
🤖 Automatically merge the PR into the develop branch.
2025-04-11 20:00:28 +02:00
JC5
d1880de30e 🤖 Auto commit for release 'develop' on 2025-04-11 2025-04-11 20:00:17 +02:00
James Cole
9d900a69ed Merge pull request #10118 from firefly-iii/main
Merge security improvements.
2025-04-11 19:45:15 +02:00
James Cole
1653f77b15 Merge pull request #10117 from firefly-iii/fix-10114
Possible fix for #10114
2025-04-11 19:40:36 +02:00
James Cole
9418436d51 Possible fix for #10114 2025-04-11 19:38:48 +02:00
James Cole
1c9a6a194a Merge pull request #10115 from firefly-iii/dependabot/npm_and_yarn/npm_and_yarn-b7c6efa8f1 2025-04-11 18:59:39 +02:00
dependabot[bot]
11cfb5a962 Bump vite in the npm_and_yarn group across 1 directory
Bumps the npm_and_yarn group with 1 update in the / directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 6.2.5 to 6.2.6
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.2.6/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.2.6/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.2.6
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-11 15:37:30 +00:00
James Cole
7d21467447 Merge pull request #10110 from firefly-iii/add-ip
Add IP to failed login message.
2025-04-09 21:28:34 +02:00
James Cole
5ce9f32deb Add IP to failed login message. 2025-04-09 21:26:29 +02:00
James Cole
337440259f Merge pull request #10109 from firefly-iii/fix-9398
Fix #9398
2025-04-07 20:43:37 +02:00
James Cole
c483e0768f Fix #9398 2025-04-07 20:42:52 +02:00
James Cole
fd9b0d9417 Merge pull request #10108 from firefly-iii/fix-9858
Whoops
2025-04-07 19:48:52 +02:00
James Cole
c3165f4937 Whoops 2025-04-07 19:48:30 +02:00
James Cole
a5c9adc872 Merge pull request #10107 from firefly-iii/fix-9858
Fix #9858
2025-04-07 19:45:33 +02:00
James Cole
59cc007931 Fix #9858 2025-04-07 19:44:22 +02:00
github-actions[bot]
8b0b12b521 Merge pull request #10103 from firefly-iii/release-1743996054
🤖 Automatically merge the PR into the develop branch.
2025-04-07 05:21:01 +02:00
JC5
6ae1cfd82e 🤖 Auto commit for release 'develop' on 2025-04-07 2025-04-07 05:20:54 +02:00
github-actions[bot]
4d7eb27fd0 Merge pull request #10102 from firefly-iii/release-1743913710
🤖 Automatically merge the PR into the develop branch.
2025-04-06 06:28:37 +02:00
JC5
fe0b8d0128 🤖 Auto commit for release 'develop' on 2025-04-06 2025-04-06 06:28:30 +02:00
James Cole
04f0fcfbf7 Merge pull request #10101 from firefly-iii/fix-null-pointer
Fix nullpointer.
2025-04-06 06:24:02 +02:00
James Cole
7e182cf070 Fix nullpointer. 2025-04-06 06:22:32 +02:00
James Cole
ad78c302ef Merge branch 'main' into develop
# Conflicts:
#	package-lock.json
2025-04-06 06:22:04 +02:00
James Cole
36b4c69491 Merge pull request #10097 from firefly-iii/dependabot/npm_and_yarn/npm_and_yarn-2bd33993d4
Bump vite from 6.2.4 to 6.2.5 in the npm_and_yarn group across 1 directory
2025-04-05 07:23:09 +02:00
dependabot[bot]
30bd0711f4 Bump vite in the npm_and_yarn group across 1 directory
Bumps the npm_and_yarn group with 1 update in the / directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 6.2.4 to 6.2.5
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.2.5/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.2.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.2.5
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-04 15:59:25 +00:00
github-actions[bot]
d847827584 Merge pull request #10095 from firefly-iii/release-1743669036
🤖 Automatically merge the PR into the develop branch.
2025-04-03 10:30:45 +02:00
JC5
786c1fcd58 🤖 Auto commit for release 'develop' on 2025-04-03 2025-04-03 10:30:36 +02:00
James Cole
90e7f0c0f7 Merge pull request #10094 from firefly-iii/fix-more
Fix lint errors
2025-04-03 10:26:17 +02:00
Sander Dorigo
63f334abe5 Fix lint errors 2025-04-03 10:25:24 +02:00
James Cole
2466cd942f Update release.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2025-04-03 10:22:09 +02:00
James Cole
ea37db87f4 Merge pull request #10093 from firefly-iii/fix-php-error
Fix dumb error
2025-04-03 10:13:52 +02:00
Sander Dorigo
c168fb6960 Fix dumb error 2025-04-03 10:13:06 +02:00
github-actions[bot]
03fb707b93 Merge pull request #10092 from firefly-iii/release-1743665835
🤖 Automatically merge the PR into the develop branch.
2025-04-03 09:37:23 +02:00
JC5
db226c2584 🤖 Auto commit for release 'develop' on 2025-04-03 2025-04-03 09:37:15 +02:00
James Cole
1c6ec82c91 Merge pull request #10091 from firefly-iii/better-mute
Better mute
2025-04-03 09:33:26 +02:00
Sander Dorigo
40eb77ffde Better mute 2025-04-03 09:32:41 +02:00
github-actions[bot]
17ddb01cd1 Merge pull request #10089 from firefly-iii/release-1743601357
🤖 Automatically merge the PR into the develop branch.
2025-04-02 15:42:46 +02:00
JC5
ca56c7af70 🤖 Auto commit for release 'develop' on 2025-04-02 2025-04-02 15:42:37 +02:00
James Cole
55c428070f Merge pull request #10087 from firefly-iii/fix-10025
Fix #10025
2025-04-02 12:13:28 +02:00
Sander Dorigo
574eec1c08 Fix #10025 2025-04-02 12:12:18 +02:00
James Cole
15cde8173e Merge pull request #10081 from firefly-iii/debug-10068
Add debug for #10068
2025-04-01 11:29:23 +02:00
Sander Dorigo
ccb581b4ee Add debug for #10068 2025-04-01 11:28:12 +02:00
James Cole
c5f8db5b50 Merge pull request #10080 from firefly-iii/fix-10069-2
fix #10069
2025-04-01 10:54:54 +02:00
Sander Dorigo
611748fbaf fix #10069 2025-04-01 10:54:08 +02:00
James Cole
b57dfa9432 Merge pull request #10078 from firefly-iii/fix-10069
Fix #10069
2025-04-01 10:35:22 +02:00
Sander Dorigo
253982d579 Fix #10069 2025-04-01 10:33:58 +02:00
James Cole
94c7a19aa0 Merge pull request #10076 from firefly-iii/mute-notifications
Fix #10069
2025-04-01 07:27:31 +02:00
Sander Dorigo
e9b360a721 Fix #10069 2025-04-01 07:26:29 +02:00
github-actions[bot]
ebf7f5932a Merge pull request #10075 from firefly-iii/release-1743484026
🤖 Automatically merge the PR into the develop branch.
2025-04-01 07:07:14 +02:00
JC5
4427f2fb99 🤖 Auto commit for release 'develop' on 2025-04-01 2025-04-01 07:07:06 +02:00
James Cole
6626dfbac3 Merge pull request #10074 from firefly-iii/mute-notifications
Mute notifications for demo site.
2025-04-01 07:02:58 +02:00
Sander Dorigo
093a6387a2 Mute notifications for demo site. 2025-04-01 06:59:55 +02:00
James Cole
21ddde9e0d Merge pull request #10072 from firefly-iii/dependabot/npm_and_yarn/npm_and_yarn-8ec3883370 2025-03-31 21:07:21 +02:00
dependabot[bot]
44d4e4e6da Bump vite in the npm_and_yarn group across 1 directory
Bumps the npm_and_yarn group with 1 update in the / directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 6.2.3 to 6.2.4
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.2.4/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.2.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-31 18:43:22 +00:00
James Cole
e34e53eeb3 Merge pull request #10055 from firefly-iii/dependabot/composer/develop/guzzlehttp/guzzle-7.9.3
Bump guzzlehttp/guzzle from 7.9.2 to 7.9.3
2025-03-31 11:04:47 +02:00
James Cole
07fb45bb34 Merge pull request #10056 from firefly-iii/dependabot/composer/develop/phpstan/phpstan-2.1.11
Bump phpstan/phpstan from 2.1.10 to 2.1.11
2025-03-31 11:04:34 +02:00
mergify[bot]
d381669733 Merge branch 'develop' into dependabot/composer/develop/guzzlehttp/guzzle-7.9.3 2025-03-31 07:20:41 +00:00
mergify[bot]
fb9eb15ae1 Merge branch 'develop' into dependabot/composer/develop/phpstan/phpstan-2.1.11 2025-03-31 07:20:36 +00:00
github-actions[bot]
a2127c382b Merge pull request #10061 from firefly-iii/release-1743405544
🤖 Automatically merge the PR into the develop branch.
2025-03-31 09:19:58 +02:00
JC5
e10d39c093 🤖 Auto commit for release 'develop' on 2025-03-31 2025-03-31 09:19:04 +02:00
mergify[bot]
a933b49e7c Merge branch 'develop' into dependabot/composer/develop/guzzlehttp/guzzle-7.9.3 2025-03-31 07:15:55 +00:00
mergify[bot]
38bcd610df Merge branch 'develop' into dependabot/composer/develop/phpstan/phpstan-2.1.11 2025-03-31 07:15:49 +00:00
James Cole
5beb476a28 Merge pull request #10060 from firefly-iii/add-missing-files
ok final one
2025-03-31 09:15:44 +02:00
Sander Dorigo
3a43ce6546 ok final one 2025-03-31 09:15:03 +02:00
mergify[bot]
c11fddb097 Merge branch 'develop' into dependabot/composer/develop/guzzlehttp/guzzle-7.9.3 2025-03-31 07:13:06 +00:00
mergify[bot]
98f79cd9bf Merge branch 'develop' into dependabot/composer/develop/phpstan/phpstan-2.1.11 2025-03-31 07:13:03 +00:00
James Cole
a3d3fe758b Merge pull request #10059 from firefly-iii/add-missing-files
add missing files
2025-03-31 09:12:25 +02:00
Sander Dorigo
93587cf1b6 add missing files 2025-03-31 09:11:17 +02:00
mergify[bot]
361e95f102 Merge branch 'develop' into dependabot/composer/develop/guzzlehttp/guzzle-7.9.3 2025-03-31 07:07:16 +00:00
mergify[bot]
be212e7d1d Merge branch 'develop' into dependabot/composer/develop/phpstan/phpstan-2.1.11 2025-03-31 07:07:13 +00:00
James Cole
003a30727f Merge pull request #10058 from firefly-iii/add-missing-files
Add new files
2025-03-31 09:06:39 +02:00
Sander Dorigo
27b662e2dc Add new files 2025-03-31 09:05:58 +02:00
mergify[bot]
0b4d7ad95e Merge branch 'develop' into dependabot/composer/develop/guzzlehttp/guzzle-7.9.3 2025-03-31 07:03:39 +00:00
mergify[bot]
7acbfb230a Merge branch 'develop' into dependabot/composer/develop/phpstan/phpstan-2.1.11 2025-03-31 07:03:36 +00:00
James Cole
b974310798 Merge pull request #10057 from firefly-iii/add-missing-files
Add missing files
2025-03-31 09:02:58 +02:00
Sander Dorigo
e391725eed Add missing files 2025-03-31 09:01:29 +02:00
dependabot[bot]
f505580b33 Bump phpstan/phpstan from 2.1.10 to 2.1.11
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 2.1.10 to 2.1.11.
- [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.10...2.1.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-31 03:10:51 +00:00
dependabot[bot]
270f932a48 Bump guzzlehttp/guzzle from 7.9.2 to 7.9.3
Bumps [guzzlehttp/guzzle](https://github.com/guzzle/guzzle) from 7.9.2 to 7.9.3.
- [Release notes](https://github.com/guzzle/guzzle/releases)
- [Changelog](https://github.com/guzzle/guzzle/blob/7.9/CHANGELOG.md)
- [Commits](https://github.com/guzzle/guzzle/compare/7.9.2...7.9.3)

---
updated-dependencies:
- dependency-name: guzzlehttp/guzzle
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-31 03:10:43 +00:00
James Cole
b9afa908e3 Merge pull request #10045 from firefly-iii/v2-additions
Small additions
2025-03-29 07:58:56 +01:00
James Cole
6dcc78b9e5 Small additions 2025-03-29 07:58:45 +01:00
James Cole
7b0e7e8612 Merge pull request #10039 from ovv/ovv/cron-update-check
update check: consider cron succesfull when disabled or too frequent
2025-03-26 14:34:56 +01:00
=
1ece4abd9d update check: consider cron succesfull when disabled or too frequent
If the update check cron is disabled or run more often than once a week
consider the cron run succesfull.
2025-03-26 13:57:23 +01:00
James Cole
07c03b672b Merge pull request #10035 from firefly-iii/resurrect-v2
Resurrect v2
2025-03-25 17:31:50 +01:00
James Cole
27ea50ec16 Merge pull request #10034 from firefly-iii/main
Merge back into develop.
2025-03-25 17:29:52 +01:00
James Cole
e1195e6663 Fix JS views. 2025-03-25 17:28:12 +01:00
James Cole
faeb17f319 Recreate API endpoints. 2025-03-25 17:27:59 +01:00
James Cole
db91b1b127 Merge pull request #10033 from firefly-iii/dependabot/npm_and_yarn/npm_and_yarn-14f44f5325
Bump vite from 6.2.2 to 6.2.3 in the npm_and_yarn group across 1 directory
2025-03-25 16:35:57 +01:00
dependabot[bot]
b5b511c86b Bump vite in the npm_and_yarn group across 1 directory
Bumps the npm_and_yarn group with 1 update in the / directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 6.2.2 to 6.2.3
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.2.3/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.2.3/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-25 14:58:51 +00:00
James Cole
750019808c Finalise boxes. 2025-03-23 15:19:40 +01:00
James Cole
7f4510467f Convert subscription information to native. 2025-03-23 15:14:20 +01:00
James Cole
a46f8430df Account for renamed variable. 2025-03-23 15:04:38 +01:00
James Cole
5e1ecb2b11 Make sure the balance box converts to native. 2025-03-23 15:04:29 +01:00
James Cole
a3fcd636e7 Get v2 up and running (sort of) 2025-03-23 09:05:06 +01:00
117 changed files with 2462 additions and 997 deletions

View File

@@ -406,16 +406,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.73.1",
"version": "v3.75.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "ffcb8200a42045e65049af7910cfd022f631b064"
"reference": "399a128ff2fdaf4281e4e79b755693286cdf325c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/ffcb8200a42045e65049af7910cfd022f631b064",
"reference": "ffcb8200a42045e65049af7910cfd022f631b064",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/399a128ff2fdaf4281e4e79b755693286cdf325c",
"reference": "399a128ff2fdaf4281e4e79b755693286cdf325c",
"shasum": ""
},
"require": {
@@ -498,7 +498,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.73.1"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.75.0"
},
"funding": [
{
@@ -506,7 +506,7 @@
"type": "github"
}
],
"time": "2025-03-19T23:42:16+00:00"
"time": "2025-03-31T18:40:42+00:00"
},
{
"name": "psr/container",
@@ -1256,16 +1256,16 @@
},
{
"name": "symfony/console",
"version": "v7.2.1",
"version": "v7.2.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3"
"reference": "e51498ea18570c062e7df29d05a7003585b19b88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/fefcc18c0f5d0efe3ab3152f15857298868dc2c3",
"reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3",
"url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88",
"reference": "e51498ea18570c062e7df29d05a7003585b19b88",
"shasum": ""
},
"require": {
@@ -1329,7 +1329,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v7.2.1"
"source": "https://github.com/symfony/console/tree/v7.2.5"
},
"funding": [
{
@@ -1345,7 +1345,7 @@
"type": "tidelift"
}
],
"time": "2024-12-11T03:49:26+00:00"
"time": "2025-03-12T08:11:12+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -2243,16 +2243,16 @@
},
{
"name": "symfony/process",
"version": "v7.2.4",
"version": "v7.2.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf"
"reference": "87b7c93e57df9d8e39a093d32587702380ff045d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf",
"reference": "d8f411ff3c7ddc4ae9166fb388d1190a2df5b5cf",
"url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d",
"reference": "87b7c93e57df9d8e39a093d32587702380ff045d",
"shasum": ""
},
"require": {
@@ -2284,7 +2284,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v7.2.4"
"source": "https://github.com/symfony/process/tree/v7.2.5"
},
"funding": [
{
@@ -2300,7 +2300,7 @@
"type": "tidelift"
}
],
"time": "2025-02-05T08:33:46+00:00"
"time": "2025-03-13T12:21:46+00:00"
},
{
"name": "symfony/service-contracts",

View File

@@ -164,6 +164,13 @@ MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_SENDMAIL_COMMAND=
#
# If you use self-signed certificates for your STMP server, you can use the following settings.
#
MAIL_ALLOW_SELF_SIGNED=false
MAIL_VERIFY_PEER=true
MAIL_VERIFY_PEER_NAME=true
# Other mail drivers:
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
MAILGUN_DOMAIN=

View File

@@ -59,7 +59,28 @@ jobs:
git config user.email release@firefly-iii.org
git config advice.addIgnoredFile false
git config push.autoSetupRemote true
- name: crowdin action
- name: Lint PHP
run: |
php_lint_file()
{
local php_file="$1"
php -l "$php_file" &> /dev/null
if [ "$?" -ne 0 ]
then
echo -e "[FAIL] $php_file"
return 1
fi
}
export -f php_lint_file
find . -path ./vendor -prune -o -name '*.php' | parallel -j 4 php_lint_file {}
if [ "$?" -ne 0 ]
then
exit 1
fi
- name: Crowdin action
uses: crowdin/github-action@v2
with:
upload_sources: true

View File

@@ -4,6 +4,7 @@ Over time, many people have contributed to Firefly III. Their efforts are not al
Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution.
## 2025
- =
- Lompi
- Jose Diaz-Gonzalez
- SoftBrix

View File

@@ -27,13 +27,16 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Data\DateRequest;
use FireflyIII\Api\V1\Requests\Chart\ChartRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\Preference;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Chart\ChartData;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Api\ApiSupport;
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
@@ -43,8 +46,10 @@ use Illuminate\Http\JsonResponse;
class AccountController extends Controller
{
use ApiSupport;
use CollectsAccountsFromFilter;
private AccountRepositoryInterface $repository;
private ChartData $chartData;
/**
* AccountController constructor.
@@ -56,6 +61,7 @@ class AccountController extends Controller
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->chartData = new ChartData();
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setUser($user);
@@ -64,6 +70,29 @@ class AccountController extends Controller
);
}
/**
* TODO fix documentation
*
* @throws FireflyException
*/
public function dashboard(ChartRequest $request): JsonResponse
{
$queryParameters = $request->getParameters();
$accounts = $this->getAccountList($queryParameters);
// move date to end of day
$queryParameters['start']->startOfDay();
$queryParameters['end']->endOfDay();
// loop each account, and collect info:
/** @var Account $account */
foreach ($accounts as $account) {
$this->renderAccountData($queryParameters, $account);
}
return response()->json($this->chartData->render());
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/charts/getChartAccountOverview
@@ -133,4 +162,45 @@ class AccountController extends Controller
return response()->json($chartData);
}
/**
* @throws FireflyException
*/
private function renderAccountData(array $params, Account $account): void
{
$currency = $this->repository->getAccountCurrency($account);
if (null === $currency) {
$currency = $this->default;
}
$currentSet = [
'label' => $account->name,
// the currency that belongs to the account.
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
// the default currency of the user (could be the same!)
'date' => $params['start']->toAtomString(),
'start' => $params['start']->toAtomString(),
'end' => $params['end']->toAtomString(),
'period' => '1D',
'entries' => [],
];
$currentStart = clone $params['start'];
$range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative);
$previous = array_values($range)[0]['balance'];
while ($currentStart <= $params['end']) {
$format = $currentStart->format('Y-m-d');
$label = $currentStart->toAtomString();
$balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous;
$previous = $balance;
$currentStart->addDay();
$currentSet['entries'][$label] = $balance;
}
$this->chartData->add($currentSet);
}
}

View File

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

View File

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

View File

@@ -39,6 +39,8 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Report\Summarizer\TransactionSummarizer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
@@ -97,10 +99,9 @@ class BasicController extends Controller
$start = $dates['start'];
$end = $dates['end'];
$code = $request->get('currency_code');
// balance information:
$balanceData = $this->getBalanceInformation($start, $end);
$billData = $this->getBillInformation($start, $end);
$billData = $this->getSubscriptionInformation($start, $end);
$spentData = $this->getLeftToSpendInfo($start, $end);
$netWorthData = $this->getNetWorthInfo($end);
// $balanceData = [];
@@ -122,6 +123,7 @@ class BasicController extends Controller
private function getBalanceInformation(Carbon $start, Carbon $end): array
{
Log::debug('getBalanceInformation');
// some config settings
$convertToNative = Amount::convertToNative();
$default = Amount::getNativeCurrency();
@@ -130,47 +132,110 @@ class BasicController extends Controller
$expenses = [];
$sums = [];
$return = [];
$currencies = [
$default->id => $default,
];
// collect income of user using the new group collector.
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::DEPOSIT->value]);
$summarizer = new TransactionSummarizer();
$set = $collector->setRange($start, $end)->setTypes([TransactionTypeEnum::DEPOSIT->value])->getExtractedJournals();
$incomes = $summarizer->groupByCurrencyId($set, 'positive', false);
$set = $collector->getExtractedJournals();
/** @var array $journal */
foreach ($set as $journal) {
$currencyId = $convertToNative ? $default->id : (int) $journal['currency_id'];
$amount = Amount::getAmountFromJournal($journal);
$incomes[$currencyId] ??= '0';
$incomes[$currencyId] = bcadd(
$incomes[$currencyId],
bcmul($amount, '-1')
);
$sums[$currencyId] ??= '0';
$sums[$currencyId] = bcadd($sums[$currencyId], bcmul($amount, '-1'));
}
// collect expenses of user.
// collect expenses of user using the new group collector.
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
$set = $collector->getExtractedJournals();
$set = $collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->getExtractedJournals();
$expenses = $summarizer->groupByCurrencyId($set, 'negative', false);
/** @var array $journal */
foreach ($set as $journal) {
$currencyId = $convertToNative ? $default->id : (int) $journal['currency_id'];
$amount = Amount::getAmountFromJournal($journal);
$expenses[$currencyId] ??= '0';
$expenses[$currencyId] = bcadd($expenses[$currencyId], $amount);
$sums[$currencyId] ??= '0';
$sums[$currencyId] = bcadd($sums[$currencyId], $amount);
// if convert to native, do so right now.
if ($convertToNative) {
$newExpenses = [
$default->id => [
'currency_id' => $default->id,
'currency_code' => $default->code,
'currency_symbol' => $default->symbol,
'currency_decimal_places' => $default->decimal_places,
'sum' => '0',
],
];
$newIncomes = [
$default->id => [
'currency_id' => $default->id,
'currency_code' => $default->code,
'currency_symbol' => $default->symbol,
'currency_decimal_places' => $default->decimal_places,
'sum' => '0',
],
];
$sums = [
$default->id => [
'currency_id' => $default->id,
'currency_code' => $default->code,
'currency_symbol' => $default->symbol,
'currency_decimal_places' => $default->decimal_places,
'sum' => '0',
],
];
$converter = new ExchangeRateConverter();
// loop over income and expenses
foreach ([$expenses, $incomes] as $index => $array) {
// loop over either one.
foreach ($array as $entry) {
// if it is the native currency already.
if ($entry['currency_id'] === $default->id) {
$sums[$default->id]['sum'] = bcadd($entry['sum'], $sums[$default->id]['sum']);
// don't forget to add it to newExpenses and newIncome
if (0 === $index) {
$newExpenses[$default->id]['sum'] = bcadd($newExpenses[$default->id]['sum'], $entry['sum']);
}
if (1 === $index) {
$newIncomes[$default->id]['sum'] = bcadd($newIncomes[$default->id]['sum'], $entry['sum']);
}
continue;
}
$currencies[$entry['currency_id']] ??= $this->currencyRepos->find($entry['currency_id']);
$convertedSum = $converter->convert($currencies[$entry['currency_id']], $default, $start, $entry['sum']);
$sums[$default->id]['sum'] = bcadd($sums[$default->id]['sum'], $convertedSum);
if (0 === $index) {
$newExpenses[$default->id]['sum'] = bcadd($newExpenses[$default->id]['sum'], $convertedSum);
}
if (1 === $index) {
$newIncomes[$default->id]['sum'] = bcadd($newIncomes[$default->id]['sum'], $convertedSum);
}
}
}
$incomes = $newIncomes;
$expenses = $newExpenses;
}
if (!$convertToNative) {
foreach ([$expenses, $incomes] as $array) {
foreach ($array as $entry) {
$currencyId = $entry['currency_id'];
$sums[$currencyId] ??= [
'currency_id' => $entry['currency_id'],
'currency_code' => $entry['currency_code'],
'currency_symbol' => $entry['currency_symbol'],
'currency_decimal_places' => $entry['currency_decimal_places'],
'sum' => '0',
];
$sums[$currencyId]['sum'] = bcadd($sums[$currencyId]['sum'], $entry['sum']);
}
}
}
// format amounts:
$keys = array_keys($sums);
foreach ($keys as $currencyId) {
$currency = $this->currencyRepos->find($currencyId);
$currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId);
if (null === $currency) {
continue;
}
@@ -178,37 +243,37 @@ class BasicController extends Controller
$return[] = [
'key' => sprintf('balance-in-%s', $currency->code),
'title' => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]),
'monetary_value' => $sums[$currencyId] ?? '0',
'monetary_value' => $sums[$currencyId]['sum'] ?? '0',
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'value_parsed' => app('amount')->formatAnything($currency, $sums[$currencyId] ?? '0', false),
'value_parsed' => app('amount')->formatAnything($currency, $sums[$currencyId]['sum'] ?? '0', false),
'local_icon' => 'balance-scale',
'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false)
.' + '.app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false),
'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId]['sum'] ?? '0', false)
.' + '.app('amount')->formatAnything($currency, $incomes[$currencyId]['sum'] ?? '0', false),
];
$return[] = [
'key' => sprintf('spent-in-%s', $currency->code),
'title' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
'monetary_value' => $expenses[$currencyId] ?? '0',
'monetary_value' => $expenses[$currencyId]['sum'] ?? '0',
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'value_parsed' => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false),
'value_parsed' => app('amount')->formatAnything($currency, $expenses[$currencyId]['sum'] ?? '0', false),
'local_icon' => 'balance-scale',
'sub_title' => '',
];
$return[] = [
'key' => sprintf('earned-in-%s', $currency->code),
'title' => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]),
'monetary_value' => $incomes[$currencyId] ?? '0',
'monetary_value' => $incomes[$currencyId]['sum'] ?? '0',
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'value_parsed' => app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false),
'value_parsed' => app('amount')->formatAnything($currency, $incomes[$currencyId]['sum'] ?? '0', false),
'local_icon' => 'balance-scale',
'sub_title' => '',
];
@@ -227,7 +292,7 @@ class BasicController extends Controller
'value_parsed' => app('amount')->formatAnything($currency, '0', false),
'local_icon' => 'balance-scale',
'sub_title' => app('amount')->formatAnything($currency, '0', false)
.' + '.app('amount')->formatAnything($currency, '0', false),
.' + '.app('amount')->formatAnything($currency, '0', false),
];
$return[] = [
'key' => sprintf('spent-in-%s', $currency->code),
@@ -258,15 +323,72 @@ class BasicController extends Controller
return $return;
}
private function getBillInformation(Carbon $start, Carbon $end): array
private function getSubscriptionInformation(Carbon $start, Carbon $end): array
{
app('log')->debug(sprintf('Now in getBillInformation("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d-')));
Log::debug(sprintf('Now in getBillInformation("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d-')));
/*
* Since both this method and the chart use the exact same data, we can suffice
* with calling the one method in the bill repository that will get this amount.
*/
$paidAmount = $this->billRepository->sumPaidInRange($start, $end);
$unpaidAmount = $this->billRepository->sumUnpaidInRange($start, $end);
$currencies = [
$this->nativeCurrency->id => $this->nativeCurrency,
];
if ($this->convertToNative) {
$converter = new ExchangeRateConverter();
$newPaidAmount = [[
'id' => $this->nativeCurrency->id,
'name' => $this->nativeCurrency->name,
'symbol' => $this->nativeCurrency->symbol,
'code' => $this->nativeCurrency->code,
'decimal_places' => $this->nativeCurrency->decimal_places,
'sum' => '0',
]];
$newUnpaidAmount = [[
'id' => $this->nativeCurrency->id,
'name' => $this->nativeCurrency->name,
'symbol' => $this->nativeCurrency->symbol,
'code' => $this->nativeCurrency->code,
'decimal_places' => $this->nativeCurrency->decimal_places,
'sum' => '0',
]];
foreach ([$paidAmount, $unpaidAmount] as $index => $array) {
foreach ($array as $item) {
$currencyId = (int) $item['id'];
if (0 === $index) {
// paid amount
if ($currencyId === $this->nativeCurrency->id) {
$newPaidAmount[0]['sum'] = bcadd($newPaidAmount[0]['sum'], $item['sum']);
continue;
}
$currencies[$currencyId] ??= $this->currencyRepos->find($currencyId);
$convertedAmount = $converter->convert($currencies[$currencyId], $this->nativeCurrency, $start, $item['sum']);
$newPaidAmount[0]['sum'] = bcadd($newPaidAmount[0]['sum'], $convertedAmount);
continue;
}
// unpaid amount
if ($currencyId === $this->nativeCurrency->id) {
$newUnpaidAmount[0]['sum'] = bcadd($newUnpaidAmount[0]['sum'], $item['sum']);
continue;
}
$currencies[$currencyId] ??= $this->currencyRepos->find($currencyId);
$convertedAmount = $converter->convert($currencies[$currencyId], $this->nativeCurrency, $start, $item['sum']);
$newUnpaidAmount[0]['sum'] = bcadd($newUnpaidAmount[0]['sum'], $convertedAmount);
}
}
$paidAmount = $newPaidAmount;
$unpaidAmount = $newUnpaidAmount;
}
// var_dump($paidAmount);
// var_dump($unpaidAmount);
// exit;
$return = [];
@@ -307,7 +429,7 @@ class BasicController extends Controller
'sub_title' => '',
];
}
app('log')->debug(sprintf('Done with getBillInformation("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d-')));
Log::debug(sprintf('Done with getBillInformation("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d-')));
if (0 === count($return)) {
$currency = $this->nativeCurrency;
@@ -348,30 +470,60 @@ class BasicController extends Controller
*/
private function getLeftToSpendInfo(Carbon $start, Carbon $end): array
{
Log::debug(sprintf('Now in getLeftToSpendInfo("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
$return = [];
$today = today(config('app.timezone'));
$available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end);
$budgets = $this->budgetRepository->getActiveBudgets();
$spent = $this->opsRepository->sumExpenses($start, $end, null, $budgets);
$days = (int) $today->diffInDays($end, true) + 1;
Log::debug(sprintf('Now in getLeftToSpendInfo("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
$return = [];
$today = today(config('app.timezone'));
$available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end);
$budgets = $this->budgetRepository->getActiveBudgets();
$spent = $this->opsRepository->sumExpenses($start, $end, null, $budgets);
$days = (int) $today->diffInDays($end, true) + 1;
$currencies = [];
// first, create an entry for each entry in the "available" array.
/** @var array $availableBudget */
foreach ($available as $currencyId => $availableBudget) {
$currencies[$currencyId] ??= $this->currencyRepos->find($currencyId);
$return[$currencyId] = [
'key' => sprintf('left-to-spend-in-%s', $currencies[$currencyId]->code),
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $currencies[$currencyId]->symbol]),
'no_available_budgets' => false,
'monetary_value' => $availableBudget,
'currency_id' => (string) $currencies[$currencyId]->id,
'currency_code' => $currencies[$currencyId]->code,
'currency_symbol' => $currencies[$currencyId]->symbol,
'currency_decimal_places' => $currencies[$currencyId]->decimal_places,
'value_parsed' => app('amount')->formatFlat($currencies[$currencyId]->symbol, $currencies[$currencyId]->decimal_places, $availableBudget, false),
'local_icon' => 'money',
'sub_title' => app('amount')->formatFlat(
$currencies[$currencyId]->symbol,
$currencies[$currencyId]->decimal_places,
$availableBudget,
false
),
];
}
foreach ($spent as $row) {
// either an amount was budgeted or 0 is available.
$currencyId = $row['currency_id'];
$amount = (string) ($available[$currencyId] ?? '0');
$spentInCurrency = $row['sum'];
$leftToSpend = bcadd($amount, $spentInCurrency);
$perDay = '0';
$currencyId = (int) $row['currency_id'];
$amount = (string) ($available[$currencyId] ?? '0');
if (0 === bccomp($amount, '0')) {
// #9858 skip over currencies with no available budget.
continue;
}
$spentInCurrency = $row['sum'];
$leftToSpend = bcadd($amount, $spentInCurrency);
$perDay = '0';
if (0 !== $days && bccomp($leftToSpend, '0') > -1) {
$perDay = bcdiv($leftToSpend, (string) $days);
}
Log::debug(sprintf('Spent %s %s', $row['currency_code'], $row['sum']));
$return[] = [
$return[$currencyId] = [
'key' => sprintf('left-to-spend-in-%s', $row['currency_code']),
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $row['currency_symbol']]),
'no_available_budgets' => false,
'monetary_value' => $leftToSpend,
'currency_id' => (string) $row['currency_id'],
'currency_code' => $row['currency_code'],
@@ -388,11 +540,12 @@ class BasicController extends Controller
];
}
if (0 === count($return)) {
$currency = $this->nativeCurrency;
$return[] = [
$currency = $this->nativeCurrency;
$return[$currency->id] = [
'key' => sprintf('left-to-spend-in-%s', $currency->code),
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $currency->symbol]),
'monetary_value' => '0',
'no_available_budgets' => true,
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
@@ -408,7 +561,7 @@ class BasicController extends Controller
];
}
return $return;
return array_values($return);
}
private function getNetWorthInfo(Carbon $end): array

View File

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

View File

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

View File

@@ -0,0 +1,59 @@
<?php
/*
* DateRequest.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Generic;
use 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:1900-01-01|before:2099-12-31',
];
}
}

View File

@@ -179,7 +179,7 @@ class BillController extends Controller
}
$amount = bcmul($journal['amount'], '-1');
if ($this->convertToNative && $currencyId !== $journal['currency_id']) {
$amount = bcmul($journal['native_amount'], '-1');
$amount = bcmul($journal['native_amount'] ?? '0', '-1');
}
if ($this->convertToNative && $currencyId === $journal['foreign_currency_id']) {
$amount = bcmul($journal['foreign_amount'], '-1');

View File

@@ -32,6 +32,7 @@ use FireflyIII\Support\Export\ExportDataGenerator;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Response as LaravelResponse;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
/**
@@ -71,6 +72,7 @@ class IndexController extends Controller
return redirect(route('export.index'));
}
Log::debug('Will export from the UI.');
/** @var ExportDataGenerator $generator */
$generator = app(ExportDataGenerator::class);
@@ -83,6 +85,7 @@ class IndexController extends Controller
$firstDate->subYear();
$journal = $this->journalRepository->firstNull();
if (null !== $journal) {
Log::debug('First journal is NULL, using today() - 1 year.');
$firstDate = clone $journal->date;
}
$generator->setStart($firstDate);

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Notifications\Admin;
use FireflyIII\Notifications\Notifiables\OwnerNotifiable;
use FireflyIII\Notifications\ReturnsAvailableChannels;
use FireflyIII\Notifications\ReturnsSettings;
use FireflyIII\Support\Facades\FireflyConfig;
use FireflyIII\Support\Facades\Steam;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
@@ -79,9 +80,10 @@ class UnknownUserLoginAttempt extends Notification
{
$settings = ReturnsSettings::getSettings('ntfy', 'owner', null);
$message = new Message();
$ip = Request::ip();
$message->topic($settings['ntfy_topic']);
$message->title((string) trans('email.unknown_user_subject'));
$message->body((string) trans('email.unknown_user_message', ['address' => $this->address]));
$message->body((string) trans('email.unknown_user_message', ['address' => $this->address, 'ip' => $ip]));
return $message;
}
@@ -91,7 +93,9 @@ class UnknownUserLoginAttempt extends Notification
*/
public function toPushover(OwnerNotifiable $notifiable): PushoverMessage
{
return PushoverMessage::create((string) trans('email.unknown_user_message', ['address' => $this->address]))
$ip = Request::ip();
return PushoverMessage::create((string) trans('email.unknown_user_message', ['address' => $this->address, 'ip' => $ip]))
->title((string) trans('email.unknown_user_subject'))
;
}
@@ -101,8 +105,10 @@ class UnknownUserLoginAttempt extends Notification
*/
public function toSlack(OwnerNotifiable $notifiable): SlackMessage
{
$ip = Request::ip();
return new SlackMessage()->content(
(string) trans('email.unknown_user_body', ['address' => $this->address])
(string) trans('email.unknown_user_body', ['address' => $this->address, 'ip' => $ip])
);
}
@@ -111,6 +117,12 @@ class UnknownUserLoginAttempt extends Notification
*/
public function via(OwnerNotifiable $notifiable): array
{
return ReturnsAvailableChannels::returnChannels('owner');
$channels = ReturnsAvailableChannels::returnChannels('owner');
$isDemoSite = FireflyConfig::get('is_demo_site', false)->data;
if (true === $isDemoSite) {
return array_diff($channels, ['mail']);
}
return $channels;
}
}

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Notifications\Security;
use FireflyIII\Notifications\ReturnsAvailableChannels;
use FireflyIII\Notifications\ReturnsSettings;
use FireflyIII\Support\Facades\FireflyConfig;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
@@ -103,6 +104,12 @@ class UserFailedLoginAttempt extends Notification
*/
public function via(User $notifiable): array
{
return ReturnsAvailableChannels::returnChannels('user', $notifiable);
$channels = ReturnsAvailableChannels::returnChannels('user', $notifiable);
$isDemoSite = FireflyConfig::get('is_demo_site', false)->data;
if (true === $isDemoSite) {
return array_diff($channels, ['mail']);
}
return $channels;
}
}

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Notifications\Test;
use FireflyIII\Notifications\Notifiables\OwnerNotifiable;
use FireflyIII\Support\Facades\FireflyConfig;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
@@ -63,6 +64,11 @@ class OwnerTestNotificationEmail extends Notification
*/
public function via(OwnerNotifiable $notifiable): array
{
$isDemoSite = FireflyConfig::get('is_demo_site', false)->data;
if (true === $isDemoSite) {
return [];
}
return ['mail'];
}
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Notifications\Test;
use FireflyIII\Support\Facades\FireflyConfig;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
@@ -60,6 +61,11 @@ class UserTestNotificationEmail extends Notification
*/
public function via(User $notifiable): array
{
$isDemoSite = FireflyConfig::get('is_demo_site', false)->data;
if (true === $isDemoSite) {
return [];
}
return ['mail'];
}
}

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Notifications\User;
use FireflyIII\Notifications\ReturnsAvailableChannels;
use FireflyIII\Notifications\ReturnsSettings;
use FireflyIII\Support\Facades\FireflyConfig;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
@@ -101,6 +102,12 @@ class NewAccessToken extends Notification
*/
public function via(User $notifiable): array
{
return ReturnsAvailableChannels::returnChannels('user', $notifiable);
$channels = ReturnsAvailableChannels::returnChannels('user', $notifiable);
$isDemoSite = FireflyConfig::get('is_demo_site', false)->data;
if (true === $isDemoSite) {
return array_diff($channels, ['mail']);
}
return $channels;
}
}

View File

@@ -676,7 +676,7 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac
'foreign_currencies.code as foreign_currency_code',
'foreign_currencies.name as foreign_currency_name',
'foreign_currencies.symbol as foreign_currency_symbol',
'foreign_currencies.decimal_places as foreign_decimal_places',
'foreign_currencies.decimal_places as foreign_currency_decimal_places',
// fields
'transaction_journals.date', 'transaction_types.type', 'transaction_journals.transaction_currency_id', 'transactions.amount'])

View File

@@ -138,7 +138,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface, U
->where('end_date', $end->format('Y-m-d'))->get()
;
Log::debug(sprintf('Found %d available budgets', $availableBudgets->count()));
Log::debug(sprintf('Found %d available budgets (already converted)', $availableBudgets->count()));
// use native amount if necessary?
$convertToNative = Amount::convertToNative($this->user);
@@ -149,8 +149,9 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface, U
$currencyId = $convertToNative && $availableBudget->transaction_currency_id !== $default->id ? $default->id : $availableBudget->transaction_currency_id;
$field = $convertToNative && $availableBudget->transaction_currency_id !== $default->id ? 'native_amount' : 'amount';
$return[$currencyId] ??= '0';
$return[$currencyId] = bcadd($return[$currencyId], $availableBudget->{$field});
Log::debug(sprintf('Add #%d %s (%s) for a total of %s', $currencyId, $availableBudget->{$field}, $field, $return[$currencyId]));
$amount = '' === (string) $availableBudget->{$field} ? '0' : (string) $availableBudget->{$field};
$return[$currencyId] = bcadd($return[$currencyId], $amount);
Log::debug(sprintf('Add #%d %s (%s) for a total of %s', $currencyId, $amount, $field, $return[$currencyId]));
}
return $return;

View File

@@ -247,6 +247,6 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
}
$summarizer = new TransactionSummarizer($this->user);
return $summarizer->groupByCurrencyId($journals);
return $summarizer->groupByCurrencyId($journals, 'negative', false);
}
}

View File

@@ -55,6 +55,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
$collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
if (null !== $accounts && $accounts->count() > 0) {
$collector->setAccounts($accounts);
$collector->excludeDestinationAccounts($accounts); // to exclude withdrawals to liabilities.
}
if (null !== $categories && $categories->count() > 0) {
$collector->setCategories($categories);
@@ -132,6 +133,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
$collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionTypeEnum::DEPOSIT->value]);
if (null !== $accounts && $accounts->count() > 0) {
$collector->setAccounts($accounts);
$collector->excludeSourceAccounts($accounts); // to prevent income from liabilities.
}
if (null !== $categories && $categories->count() > 0) {
$collector->setCategories($categories);

View File

@@ -46,7 +46,7 @@ class ChartData
if (array_key_exists('native_currency_id', $data)) {
$data['native_currency_id'] = (string) $data['native_currency_id'];
}
$required = ['start', 'date', 'end', 'entries', 'native_entries'];
$required = ['start', 'date', 'end', 'entries'];
foreach ($required as $field) {
if (!array_key_exists($field, $data)) {
throw new FireflyException(sprintf('Data-set is missing the "%s"-variable.', $field));

View File

@@ -45,8 +45,8 @@ class UpdateCheckCronjob extends AbstractCronjob
Log::debug('Update check is not enabled.');
// get stuff from job:
$this->jobFired = false;
$this->jobErrored = true;
$this->jobSucceeded = false;
$this->jobErrored = false;
$this->jobSucceeded = true;
$this->message = 'The update check is not enabled.';
return;
@@ -61,8 +61,8 @@ class UpdateCheckCronjob extends AbstractCronjob
if ($diff < 604800 && false === $this->force) {
// get stuff from job:
$this->jobFired = false;
$this->jobErrored = true;
$this->jobSucceeded = false;
$this->jobErrored = false;
$this->jobSucceeded = true;
$this->message = sprintf('Checked for updates less than a week ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data));
return;

View File

@@ -731,6 +731,7 @@ class ExportDataGenerator
*/
private function exportTransactions(): string
{
Log::debug('Will now export transactions.');
// TODO better place for keys?
$header = ['user_id', 'group_id', 'journal_id', 'created_at', 'updated_at', 'group_title', 'type', 'currency_code', 'amount', 'foreign_currency_code', 'foreign_amount', 'native_currency_code', 'native_amount', 'native_foreign_amount', 'description', 'date', 'source_name', 'source_iban', 'source_type', 'destination_name', 'destination_iban', 'destination_type', 'reconciled', 'category', 'budget', 'bill', 'tags', 'notes'];

View File

@@ -49,7 +49,7 @@ class TransactionSummarizer
$this->convertToNative = Amount::convertToNative($user);
}
public function groupByCurrencyId(array $journals, string $method = 'negative'): array
public function groupByCurrencyId(array $journals, string $method = 'negative', bool $includeForeign = true): array
{
Log::debug(sprintf('Now in groupByCurrencyId(array, "%s")', $method));
$array = [];
@@ -94,10 +94,10 @@ class TransactionSummarizer
}
}
if (!$this->convertToNative) {
Log::debug(sprintf('Journal #%d also includes foreign amount (foreign is %s)', $journal['transaction_journal_id'], $journal['foreign_currency_code']));
// use foreign amount?
$foreignCurrencyId = (int) $journal['foreign_currency_id'];
if (0 !== $foreignCurrencyId) {
Log::debug(sprintf('Journal #%d also includes foreign amount (foreign is "%s")', $journal['transaction_journal_id'], $journal['foreign_currency_code']));
$foreignCurrencyName = $journal['foreign_currency_name'];
$foreignCurrencySymbol = $journal['foreign_currency_symbol'];
$foreignCurrencyCode = $journal['foreign_currency_code'];
@@ -124,7 +124,7 @@ class TransactionSummarizer
}
// then process foreign amount, if it exists.
if (0 !== $foreignCurrencyId) {
if (0 !== $foreignCurrencyId && true === $includeForeign) {
$amount = (string) ($journal['foreign_amount'] ?? '0');
$array[$foreignCurrencyId] ??= [
'sum' => '0',

View File

@@ -84,7 +84,7 @@
"bacon/bacon-qr-code": "^2",
"diglactic/laravel-breadcrumbs": "^10",
"gdbots/query-parser": "^3.0",
"guzzlehttp/guzzle": "^7.8",
"guzzlehttp/guzzle": "^7.9",
"jc5/google2fa-laravel": "^2.0",
"jc5/recovery": "^2",
"laravel-notification-channels/pushover": "^4.0",

413
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -28,48 +28,53 @@ return [
'download_enabled' => env('ENABLE_EXTERNAL_RATES', false),
// if currencies are added, default rates must be added as well!
// last exchange rate update: 2024-12-30
// source: https://www.xe.com/currencyconverter/
'date' => '2024-12-30',
'date' => '2025-04-15',
// all rates are from EUR to $currency:
'rates' => [
// europa
'EUR' => 1,
'HUF' => 410.79798,
'GBP' => 0.82858703,
'UAH' => 43.485934,
'PLN' => 4.2708542,
'TRY' => 36.804124,
'GBP' => 0.86003261,
'UAH' => 46.867455,
'PLN' => 4.2802098,
'TRY' => 43.180054,
'DKK' => 7.4591,
'RON' => 4.9768699,
'RON' => 7.4648336,
// Americas
'USD' => 1.0430046,
'BRL' => 6.4639113,
'CAD' => 1.5006908,
'MXN' => 21.249542,
'USD' => 1.1349044,
'BRL' => 6.6458518,
'CAD' => 1.575105,
'MXN' => 22.805278,
// Oceania currencies
'IDR' => 16860.057,
'AUD' => 1.6705648,
'NZD' => 1.8436945,
'IDR' => 19070.382,
'AUD' => 1.787202,
'NZD' => 1.9191078,
// africa
'EGP' => 53.038174,
'MAD' => 10.521629,
'ZAR' => 19.460263,
'EGP' => 57.874172,
'MAD' => 10.549438,
'ZAR' => 21.444356,
// asia
'JPY' => 164.74767,
'RMB' => 7.6138994,
'CNY' => 7.6138994,
'RUB' => 108.56771,
'INR' => 89.157391,
'JPY' => 162.47195,
'RMB' => 8.2849977,
'CNY' => 8.2849977,
'RUB' => 93.34423,
'INR' => 97.572815,
// int
'ILS' => 3.8428028,
'CHF' => 0.94044969,
'ILS' => 4.1801786,
'CHF' => 0.92683126,
'HRK' => 7.5345, // replaced by EUR
'ISK' => 145.10532,
'NOK' => 11.980824,
'SEK' => 11.08809,
'HKD' => 8.8046322,
'CZK' => 25.092213,
],
];

View File

@@ -78,7 +78,7 @@ return [
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2025-03-24',
'version' => 'develop/2025-04-19',
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 25,
@@ -184,6 +184,7 @@ return [
'currencyPreference' => 'EUR',
'language' => 'en_US',
'locale' => 'equal',
'convertToNative' => false,
],
'default_currency' => 'EUR',
'default_language' => envNonEmpty('DEFAULT_LANGUAGE', 'en_US'),

View File

@@ -37,14 +37,19 @@ return [
'mailers' => [
'smtp' => [
'transport' => 'smtp',
'host' => envNonEmpty('MAIL_HOST', 'smtp.mailtrap.io'),
'port' => (int) env('MAIL_PORT', 2525),
'encryption' => envNonEmpty('MAIL_ENCRYPTION', 'tls'),
'username' => envNonEmpty('MAIL_USERNAME', 'user@example.com'),
'password' => envNonEmpty('MAIL_PASSWORD', 'password'),
'timeout' => null,
'verify_peer' => null !== env('MAIL_ENCRYPTION'),
'transport' => 'smtp',
'host' => envNonEmpty('MAIL_HOST', 'smtp.mailtrap.io'),
'port' => (int) env('MAIL_PORT', 2525),
'encryption' => envNonEmpty('MAIL_ENCRYPTION', 'tls'),
'username' => envNonEmpty('MAIL_USERNAME', 'user@example.com'),
'password' => envNonEmpty('MAIL_PASSWORD', 'password'),
'timeout' => null,
'scheme' => env('MAIL_SCHEME'),
'url' => env('MAIL_URL'),
'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST)),
'verify_peer' => env('MAIL_VERIFY_PEER', true),
'allow_self_signed' => env('MAIL_ALLOW_SELF_SIGNED', false),
'verify_peer_name' => env('MAIL_VERIFY_PEER_NAME', true),
],
'mailersend' => [
'transport' => 'mailersend',

View File

@@ -139,6 +139,7 @@ return [
'firefly' => [
'administrations_page_title',
'administrations_index_menu',
'expires_at',
'temp_administrations_introduction',
'administration_currency_form_help',
'administrations_page_edit_sub_title_js',

View File

@@ -69,10 +69,14 @@ class TransactionCurrencySeeder extends Seeder
$currencies[] = ['code' => 'RUB', 'name' => 'Russian ruble', 'symbol' => '₽', 'decimal_places' => 2];
$currencies[] = ['code' => 'INR', 'name' => 'Indian rupee', 'symbol' => '₹', 'decimal_places' => 2];
// PLEASE ADD NEW CURRENCIES BELOW THIS LINE
// ALL NEW CURRENCIES BELOW THIS LINE
$currencies[] = ['code' => 'ILS', 'name' => 'Israeli new shekel', 'symbol' => '₪', 'decimal_places' => 2];
$currencies[] = ['code' => 'CHF', 'name' => 'Swiss franc', 'symbol' => 'CHF', 'decimal_places' => 2];
$currencies[] = ['code' => 'HRK', 'name' => 'Croatian kuna', 'symbol' => 'kn', 'decimal_places' => 2];
$currencies[] = ['code' => 'HKD', 'name' => 'Hong Kong dollar', 'symbol' => 'HK$', 'decimal_places' => 2];
$currencies[] = ['code' => 'CHF', 'name' => 'Swiss franc', 'symbol' => 'CHF', 'decimal_places' => 2];
$currencies[] = ['code' => 'NOK', 'name' => 'Norwegian krone', 'symbol' => 'kr.', 'decimal_places' => 2];
$currencies[] = ['code' => 'CZK', 'name' => 'Czech koruna', 'symbol' => 'Kč', 'decimal_places' => 2];
foreach ($currencies as $currency) {
if (null === TransactionCurrency::where('code', $currency['code'])->first()) {

753
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -80,11 +80,18 @@ function drawChart() {
// left to spend
if (key.substring(0, 17) === 'left-to-spend-in-') {
left_to_spend_top.push(data[key].value_parsed);
left_to_spend_bottom.push(data[key].sub_title);
if (parseFloat(data[key].monetary_value) > 0) {
if(true === data[key].no_available_budgets) {
left_to_spend_top.push('---');
left_to_spend_bottom.push('---');
keepGreen = true;
}
if(false === data[key].no_available_budgets) {
left_to_spend_top.push(data[key].value_parsed);
left_to_spend_bottom.push(data[key].sub_title);
if (parseFloat(data[key].monetary_value) > 0) {
keepGreen = true;
}
}
}
// net worth

View File

@@ -47,6 +47,7 @@
<thead>
<tr>
<th scope="col">{{ $t('firefly.name') }}</th>
<th scope="col">{{ $t('firefly.expires_at') }}</th>
<th scope="col"></th>
</tr>
</thead>
@@ -57,6 +58,10 @@
<td style="vertical-align: middle;">
{{ token.name }}
</td>
<!-- expires at -->
<td style="vertical-align: middle;">
{{ new Date(token.expires_at).toLocaleString() }}
</td>
<!-- Delete Button -->
<td style="vertical-align: middle;">
@@ -232,7 +237,7 @@ export default {
},
/**
* Get all of the available scopes.
* Get all the available scopes.
*/
getScopes() {
axios.get('./oauth/scopes')

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",
@@ -103,7 +104,7 @@
"profile_oauth_confidential": "Soukrom\u00e1 aplikace",
"profile_oauth_confidential_help": "Po\u017eadovat aby se klienti autorizovali. Soukrom\u00e9 aplikace mohou bezpe\u010dn\u011b pracovat s p\u0159\u00edstupov\u00fdmi \u00fadaji bez toho aby je zve\u0159ejnily. Ve\u0159ejn\u00e9 aplikace, nativn\u00ed nebo JavaScriptov\u00e9 SPA, toho schopn\u00e9 nejsou.",
"multi_account_warning_unknown": "Depending on the type of transaction you create, the source and\/or destination account of subsequent splits may be overruled by whatever is defined in the first split of the transaction.",
"multi_account_warning_withdrawal": "Zdrojov\u00fd \u00fa\u010del v\u0161ech n\u00e1sleduj\u00edc\u00edch rozd\u011blen\u00ed je ovl\u00e1dan\u00fd zdrojov\u00fdm \u00fa\u010dtem prvn\u00edho rozd\u011blen\u00ed transakce.",
"multi_account_warning_withdrawal": "Zdrojov\u00fd \u00fa\u010det cel\u00e9 transakce je ovl\u00e1dan\u00fd prvn\u00edm rozd\u011blen\u00edm.",
"multi_account_warning_deposit": "C\u00edlov\u00fd \u00fa\u010del v\u0161ech n\u00e1sleduj\u00edc\u00edch rozd\u011blen\u00ed je ovl\u00e1dan\u00fd c\u00edlov\u00fdm \u00fa\u010dtem prvn\u00edho rozd\u011blen\u00ed transakce.",
"multi_account_warning_transfer": "Zdrojov\u00fd i c\u00edlov\u00fd \u00fa\u010det v\u0161ech n\u00e1sleduj\u00edc\u00edch rozd\u011blen\u00ed jsou ovl\u00e1d\u00e1ny zdrojov\u00fdm a c\u00edlov\u00fdm \u00fa\u010dtem prvn\u00edho rozd\u011blen\u00ed transakce.",
"webhook_trigger_STORE_TRANSACTION": "Po vytvo\u0159en\u00ed transakce",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Finanzverwaltungen",
"administrations_index_menu": "Finanzverwaltung",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III wird bald die M\u00f6glichkeit erhalten, mehrere Finanzverwaltungen zu verwalten. Im Moment verf\u00fcgen Sie nur \u00fcber eine. Sie k\u00f6nnen den Titel dieser Verwaltung und ihre eigene W\u00e4hrung festlegen. Dies ersetzt die bisherige Einstellung, bei der Sie Ihre \u201eStandardw\u00e4hrung\u201c festlegen konnten. Diese Einstellung ist jetzt an die Finanzverwaltung gebunden und kann f\u00fcr jede Verwaltung unterschiedlich sein.",
"administration_currency_form_help": "Es kann l\u00e4nger dauern, bis die Seite geladen ist, wenn Sie die Landesw\u00e4hrung \u00e4ndern, da die Buchungen m\u00f6glicherweise in Ihre (neue) Landesw\u00e4hrung umgerechnet werden m\u00fcssen.",
"administrations_page_edit_sub_title_js": "Finanzverwaltung \u201e{title}\u201c bearbeiten",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",
@@ -46,7 +47,7 @@
"tags": "Etiquetas",
"no_budget": "(sin presupuesto)",
"no_bill": "(no subscription)",
"category": "Categoria",
"category": "Categor\u00eda",
"attachments": "Archivos adjuntos",
"notes": "Notas",
"external_url": "URL externa",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Administrations financi\u00e8res",
"administrations_index_menu": "Administrations financi\u00e8res",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III aura bient\u00f4t la possibilit\u00e9 de g\u00e9rer plusieurs administrations financi\u00e8res. Pour le moment, vous n'en avez qu'une. Vous pouvez d\u00e9finir le titre de cette administration et de sa devise locale. Cela remplace le param\u00e8tre pr\u00e9c\u00e9dent o\u00f9 vous d\u00e9finissiez votre \"devise par d\u00e9faut\". Ce param\u00e8tre est d\u00e9sormais li\u00e9 \u00e0 l'administration financi\u00e8re et peut \u00eatre diff\u00e9rent par administration.",
"administration_currency_form_help": "La page peut mettre longtemps \u00e0 charger si vous modifiez la devise locale, car des op\u00e9rations peuvent n\u00e9cessiter une conversion vers votre (nouvelle) devise locale.",
"administrations_page_edit_sub_title_js": "Modifier l'administration financi\u00e8re \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Amministrazioni finanziarie",
"administrations_index_menu": "Amministrazioni finanziarie",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III avr\u00e0 presto la possibilit\u00e0 di gestire pi\u00f9 amministrazioni finanziarie. In questo momento, hai solo il titolo. Puoi impostare il titolo di questa amministrazione e la sua valuta nativa. Questo sostituisce l'impostazione precedente, in cui si impostava la \"valuta predefinita\". Questa situazione \u00e8 ora legata all'amministrazione finanziaria e pu\u00f2 essere diversa per amministrazione.",
"administration_currency_form_help": "Se modifichi la valuta nativa, il caricamento della pagina potrebbe richiedere molto tempo, poich\u00e9 potrebbe essere necessario convertire la transazione nella (nuova) valuta nativa.",
"administrations_page_edit_sub_title_js": "Modifica amministrazione finanziaria \"{title}\"",
@@ -30,7 +31,7 @@
"apply_rules_checkbox": "Applica le regole",
"fire_webhooks_checkbox": "Esegui webhook",
"no_budget_pointer": "Sembra che tu non abbia ancora dei budget. Dovresti crearne alcuni nella pagina dei <a href=\"budgets\">budget<\/a>. I budget possono aiutarti a tenere traccia delle spese.",
"no_bill_pointer": "Sembra che tu non abbia ancora un abbonamento. Dovresti crearne alcuni sulla pagina <a href=\"subscriptions\">abbonamento<\/a>. Gli abbonamenti possono aiutarti a tenere traccia delle spese.",
"no_bill_pointer": "Sembra che tu non abbia ancora un pagamento ricorrente. Dovresti crearne alcuni sulla pagina <a href=\"subscriptions\">pagamenti ricorrenti<\/a>. I pagamenti ricorrenti possono aiutarti a tenere traccia delle spese.",
"source_account": "Conto di origine",
"hidden_fields_preferences": "Puoi abilitare maggiori opzioni per le transazioni nelle tue <a href=\"preferences\">impostazioni<\/a>.",
"destination_account": "Conto destinazione",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",
@@ -153,7 +154,7 @@
"url": "URL",
"active": "\ud65c\uc131",
"interest_date": "\uc774\uc790 \ub0a0\uc9dc",
"administration_currency": "Native currency",
"administration_currency": "\uc790\uad6d \ud1b5\ud654",
"title": "\uc81c\ubaa9",
"date": "\ub0a0\uc9dc",
"book_date": "\uc608\uc57d\uc77c",
@@ -173,7 +174,7 @@
"list": {
"title": "\uc81c\ubaa9",
"active": "\ud65c\uc131 \uc0c1\ud0dc\uc785\ub2c8\uae4c?",
"native_currency": "Native currency",
"native_currency": "\uc790\uad6d \ud1b5\ud654",
"trigger": "\ud2b8\ub9ac\uac70",
"response": "\uc751\ub2f5",
"delivery": "\uc804\ub2ec",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Grootboeken",
"administrations_index_menu": "Grootboeken",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III krijgt binnenkort het vermogen om meerdere grootboeken te beheren. Op dit moment kan dat nog niet. Je kan de titel van dit grootboek instellen en de basisvaluta. Dit vervangt de voorgaande manier waarop je je \"standaardvaluta\" zou instellen. Deze instelling is nu gekoppeld aan dit grootboek, en kan per grootboek verschillend zijn.",
"administration_currency_form_help": "Het wijzigen van deze instelling betekent dat heel veel transacties omgerekend moeten worden naar je nieuwe basisvaluta en dat kan lang duren.",
"administrations_page_edit_sub_title_js": "Wijzig grootboek \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Ustawienia finansowe",
"administrations_index_menu": "Ustawienia finansowe",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III wkr\u00f3tce uzyska mo\u017cliwo\u015b\u0107 zarz\u0105dzania wieloma ustawieniami finansowymi. W tej chwili jest tylko jedno domy\u015blne ustawienie. Mo\u017cesz ustawi\u0107 jego tytu\u0142 i natywn\u0105 walut\u0119. To zast\u0119puje poprzednie ustawienia, w kt\u00f3rym mo\u017cna by\u0142o ustawi\u0107 \"domy\u015bln\u0105 walut\u0119\". Jest ona obecnie powi\u0105zana z wybranym ustawieniem finansowym i mo\u017ce by\u0107 zmienione w tej zak\u0142adce.",
"administration_currency_form_help": "Wczytywanie strony mo\u017ce zaj\u0105\u0107 du\u017co czasu, je\u015bli zmienisz natywn\u0105 walut\u0119, poniewa\u017c transakcja mo\u017ce wymaga\u0107 przewalutowania na (now\u0105) natywn\u0105 walut\u0119.",
"administrations_page_edit_sub_title_js": "Edytuj ustawienia finansowe \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "\u0424\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u044b\u0435 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u044b",
"administrations_index_menu": "\u0424\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u044b\u0435 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u044b",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III \u0432\u0441\u043a\u043e\u0440\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0444\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u044b\u043c\u0438 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\u043c\u0438. \u0421\u0435\u0439\u0447\u0430\u0441 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0434\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0439 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u0435\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0432\u0430\u043b\u044e\u0442\u0443. \u042d\u0442\u043e \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 \"\u0432\u0430\u043b\u044e\u0442\u0443 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e\". \u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u044d\u0442\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0432\u044f\u0437\u0430\u043d\u0430 \u0441 \u0444\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u043e\u0439 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u043e\u0439 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430.",
"administration_currency_form_help": "\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043d\u044f\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0435\u0441\u043b\u0438 \u0432\u044b \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0432\u0430\u043b\u044e\u0442\u0443, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0430 \u0432 \u043d\u043e\u0432\u0443\u044e \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0432\u0430\u043b\u044e\u0442\u0443.",
"administrations_page_edit_sub_title_js": "\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0444\u0438\u043d\u0430\u043d\u0441\u0430\u043c\u0438 \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Finan\u010dne administracije",
"administrations_index_menu": "Finan\u010dne administracije",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III bo kmalu dobil mo\u017enost upravljanja ve\u010d finan\u010dnih administracij. Trenutno imate samo eno. Nastavite lahko naziv te administracije in njeno doma\u010do valuto. To nadome\u0161\u010da prej\u0161njo nastavitev, kjer bi nastavili svojo \"privzeto valuto\". Ta nastavitev je zdaj vezana na finan\u010dno administracijo in se lahko razlikuje glede na administracijo.",
"administration_currency_form_help": "\u010ce spremenite doma\u010do valuto, lahko traja dolgo \u010dasa, da se stran nalo\u017ei, ker bo transakcijo morda treba pretvoriti v va\u0161o (novo) doma\u010do valuto.",
"administrations_page_edit_sub_title_js": "Uredi finan\u010dno administracijo \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "\u0424\u0456\u043d\u0430\u043d\u0441\u043e\u0432\u0456 \u0430\u0434\u043c\u0456\u043d\u0456\u0441\u0442\u0440\u0430\u0446\u0456\u0457",
"administrations_index_menu": "\u0424\u0456\u043d\u0430\u043d\u0441\u043e\u0432\u0456 \u0430\u0434\u043c\u0456\u043d\u0456\u0441\u0442\u0440\u0430\u0446\u0456\u0457",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "Financial administrations",
"administrations_index_menu": "Financial administrations",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",

View File

@@ -2,9 +2,10 @@
"firefly": {
"administrations_page_title": "\u8d22\u52a1\u7ba1\u7406",
"administrations_index_menu": "\u8d22\u52a1\u7ba1\u7406",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III \u4e0d\u4e45\u5c06\u80fd\u591f\u7ba1\u7406\u591a\u4e2a\u8d22\u52a1\u7ba1\u7406\u3002 \u73b0\u5728\uff0c\u4f60\u53ea\u80fd\u6709\u4e00\u4e2a\u8d22\u52a1\u7ba1\u7406\u3002\u4f60\u53ef\u4ee5\u8bbe\u7f6e\u8fd9\u4e2a\u8d22\u52a1\u7ba1\u7406\u7684\u6807\u9898\u53ca\u5176\u5f53\u5730\u8d27\u5e01\u3002 \u8fd9\u5c06\u53d6\u4ee3\u60a8\u5148\u524d\u8bbe\u7f6e\u7684\u201c\u9ed8\u8ba4\u8d27\u5e01\u201d\u3002 \u8fd9\u79cd\u8bbe\u7f6e\u73b0\u5728\u4e0e\u8d22\u52a1\u7ba1\u7406\u6302\u94a9\uff0c\u6bcf\u4e2a\u7ba1\u7406\u53ef\u4ee5\u6709\u4e0d\u540c\u7684\u8bbe\u7f6e\u3002",
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",
"administration_currency_form_help": "\u5982\u679c\u60a8\u66f4\u6539\u672c\u5730\u8d27\u5e01\uff0c\u9875\u9762\u52a0\u8f7d\u53ef\u80fd\u9700\u8981\u5f88\u957f\u65f6\u95f4\uff0c\u56e0\u4e3a\u4ea4\u6613\u53ef\u80fd\u9700\u8981\u8f6c\u6362\u4e3a\u60a8\u7684(\u65b0)\u672c\u5730\u8d27\u5e01\u3002",
"administrations_page_edit_sub_title_js": "\u7f16\u8f91\u8d22\u52a1\u7ba1\u7406{title}",
"table": "\u8868\u683c",
"welcome_back": "\u4eca\u5929\u7406\u8d22\u4e86\u5417\uff1f",
"flash_error": "\u9519\u8bef\uff01",
@@ -140,12 +141,12 @@
"visit_webhook_url": "\u8bbf\u95ee webhook URL",
"reset_webhook_secret": "\u91cd\u7f6e webhook \u5bc6\u94a5",
"header_exchange_rates": "\u6c47\u7387",
"exchange_rates_intro": "Firefly III supports downloading and using exchange rates. Read more about this in <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">the documentation<\/a>.",
"exchange_rates_from_to": "Between {from} and {to} (and the other way around)",
"exchange_rates_intro_rates": "Firefly III uses the following exchange rates. The inverse is automatically calculated when it is not provided. If no exchange rate exists for the date of the transaction, Firefly III will go back in time to find one. If none are present, the rate \"1\" will be used.",
"exchange_rates_intro": "Frefly III \u652f\u6301\u4e0b\u8f7d\u548c\u4f7f\u7528\u6c47\u7387\u3002\u8bf7\u5728 <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">\u8fd9\u4efd\u6587\u6863<\/a>\u4e2d\u9605\u8bfb\u66f4\u591a\u3002",
"exchange_rates_from_to": "\u4ece {from} \u5230 {to} \u7684\u6c47\u7387\uff08\u4ee5\u53ca\u53cd\u5411\uff09",
"exchange_rates_intro_rates": "Firefly III \u91c7\u7528\u4ee5\u4e0b\u6c47\u7387\u3002\u5982\u679c\u6ca1\u6709\u63d0\u4f9b\u53cd\u5411\u6c47\u7387\u5219\u81ea\u52a8\u8ba1\u7b97\u3002 \u5982\u679c\u4ea4\u6613\u65e5\u671f\u4e0d\u5b58\u5728\u6c47\u7387\uff0cFifrefly III \u5c06\u5bfb\u627e\u524d\u4e00\u4e2a\u53ef\u7528\u65e5\u671f\u7684\u6c47\u7387\u3002 \u5982\u679c\u6ca1\u6709\uff0c\u5c06\u6309\u6c47\u7387\u4e3a 1 \u8fdb\u884c\u8ba1\u7b97\u3002",
"header_exchange_rates_rates": "\u6c47\u7387",
"header_exchange_rates_table": "Table with exchange rates",
"help_rate_form": "On this day, how many {to} will you get for one {from}?",
"header_exchange_rates_table": "\u6c47\u7387\u8868",
"help_rate_form": "\u5728\u8fd9\u4e00\u5929\uff0c\u4f60\u80fd\u4ece\u6bcf 1 \u4e2a\u5355\u4f4d\u7684 {from} \u83b7\u5f97\u591a\u5c11 {to}\uff1f",
"add_new_rate": "\u6dfb\u52a0\u65b0\u6c47\u7387",
"save_new_rate": "\u4fdd\u5b58\u65b0\u6c47\u7387"
},
@@ -168,7 +169,7 @@
"webhook_delivery": "\u53d1\u9001\u683c\u5f0f",
"from_currency_to_currency": "{from}&rarr;{to}",
"to_currency_from_currency": "{to}&rarr;{from}",
"rate": "\u8bc4\u7ea7"
"rate": "\u6c47\u7387"
},
"list": {
"title": "\u6807\u9898",

View File

@@ -2,6 +2,7 @@
"firefly": {
"administrations_page_title": "\u591a\u500b\u8ca1\u52d9\u7ba1\u7406",
"administrations_index_menu": "\u591a\u500b\u8ca1\u52d9\u7ba1\u7406",
"expires_at": "Expires at",
"temp_administrations_introduction": "Firefly III \u5373\u5c07\u652f\u63f4\u540c\u6642\u7ba1\u7406\u591a\u500b\u8ca1\u52d9\u7ba1\u7406\u3002\u76ee\u524d\u60a8\u53ea\u6709\u4e00\u500b\u3002\u60a8\u53ef\u5728\u6b64\u8a2d\u5b9a\u5176\u6a19\u984c\u8207\u672c\u5e63\uff0c\u9019\u53d6\u4ee3\u4e86\u5148\u524d\u7684\u300c\u9810\u8a2d\u8ca8\u5e63\u300d\u8a2d\u5b9a\u3002\u6b64\u8a2d\u5b9a\u73fe\u5728\u7d81\u5b9a\u65bc\u8a72\u8ca1\u52d9\u7ba1\u7406\uff0c\u4e26\u53ef\u56e0\u4e0d\u540c\u8ca1\u52d9\u7ba1\u7406\u800c\u7570\u3002",
"administration_currency_form_help": "\u5982\u679c\u60a8\u66f4\u6539\u4e86\u672c\u5e63\uff0c\u53ef\u80fd\u9700\u8981\u4e00\u6bb5\u6642\u9593\u624d\u80fd\u8f09\u5165\u9801\u9762\uff0c\u56e0\u70ba\u4ea4\u6613\u53ef\u80fd\u9700\u8981\u8f49\u63db\u70ba\uff08\u65b0\uff09\u672c\u5e63\u3002",
"administrations_page_edit_sub_title_js": "\u7de8\u8f2f\u8ca1\u52d9\u7ba1\u7406\u300c{title}\u300d",

View File

@@ -8,26 +8,22 @@
"postinstall": "patch-package --error-on-fail"
},
"devDependencies": {
"axios": "^1.8.2",
"laravel-vite-plugin": "^1.0.5",
"patch-package": "^8.0.0",
"sass": "^1.78.0",
"axios": "^1",
"laravel-vite-plugin": "^1",
"patch-package": "^8",
"sass": "^1",
"vite": "^6",
"vite-plugin-manifest-sri": "^0.2.0"
},
"dependencies": {
"@ag-grid-community/client-side-row-model": "^32.0.2",
"@ag-grid-community/core": "^32.0.2",
"@ag-grid-community/infinite-row-model": "^32.0.2",
"@ag-grid-community/styles": "^33.0.2",
"@fortawesome/fontawesome-free": "^6.4.0",
"@popperjs/core": "^2.11.8",
"admin-lte": "^4.0.0-alpha3",
"admin-lte": "^4.0.0-beta3",
"alpinejs": "^3.13.7",
"bootstrap": "^5.3.0",
"bootstrap5-autocomplete": "^1.1.22",
"bootstrap5-tags": "^1.7",
"chart.js": "^4.4.0",
"bootstrap": "^5",
"bootstrap5-autocomplete": "^1",
"bootstrap5-tags": "^1",
"chart.js": "^4",
"chartjs-adapter-date-fns": "^3.0.0",
"chartjs-chart-sankey": "^0.14.0",
"date-fns": "^4.0.0",

View File

@@ -0,0 +1,36 @@
/*
* overview.js
* 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/>.
*/
import {api} from "../../../../boot/axios";
import {format} from "date-fns";
export default class Dashboard {
dashboard(start, end) {
let startStr = format(start, 'y-MM-dd');
let endStr = format(end, 'y-MM-dd');
return api.get('/api/v1/chart/account/dashboard', {params: {fix: true, start: startStr, end: endStr}});
}
expense(start, end) {
let startStr = format(start, 'y-MM-dd');
let endStr = format(end, 'y-MM-dd');
return api.get('/api/v1/chart/account/expense-dashboard', {params: {start: startStr, end: endStr}});
}
}

View File

@@ -0,0 +1,30 @@
/*
* overview.js
* 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/>.
*/
import {api} from "../../../../boot/axios";
import {format} from "date-fns";
export default class Dashboard {
dashboard(start, end) {
let startStr = format(start, 'y-MM-dd');
let endStr = format(end, 'y-MM-dd');
return api.get('/api/v1/chart/budget/dashboard', {params: {start: startStr, end: endStr}});
}
}

View File

@@ -0,0 +1,30 @@
/*
* overview.js
* 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/>.
*/
import {api} from "../../../../boot/axios";
import {format} from "date-fns";
export default class Dashboard {
dashboard(start, end) {
let startStr = format(start, 'y-MM-dd');
let endStr = format(end, 'y-MM-dd');
return api.get('/api/v1/chart/category/dashboard', {params: {start: startStr, end: endStr}});
}
}

View File

@@ -18,7 +18,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {api} from "../../../boot/axios";
import {api} from "../../../../boot/axios";
import format from "date-fns/format";
export default class Get {
@@ -37,6 +37,18 @@ export default class Get {
return api.get('/api/v1/accounts/' + identifier, {params: params});
}
/**
*
* @param identifier
* @param params
* @returns {Promise<AxiosResponse<any>>}
*/
show(identifier, params) {
return api.get('/api/v1/accounts/' + identifier, {params: params});
}
/**
*
* @param identifier

View File

@@ -0,0 +1,36 @@
/*
* list.js
* 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/>.
*/
import {api} from "../../../../boot/axios";
import format from "date-fns/format";
export default class Put {
/**
*
* @param identifier
* @param params
* @returns {Promise<AxiosResponse<any>>}
*/
put(identifier, params) {
return api.put('/api/v2/accounts/' + identifier, params);
}
}

View File

@@ -18,7 +18,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {api} from "../../../boot/axios";
import {api} from "../../../../boot/axios";
export default class Post {
post(fileName, attachableType, attachableId) {

View File

@@ -0,0 +1,35 @@
/*
* list.js
* 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/>.
*/
import {api} from "../../../../boot/axios";
import format from "date-fns/format";
export default class Get {
/**
*
* @param params
* @returns {Promise<AxiosResponse<any>>}
*/
list(params) {
return api.get('/api/v2/budgets', {params: params});
}
}

View File

@@ -0,0 +1,35 @@
/*
* list.js
* 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/>.
*/
import {api} from "../../../../boot/axios";
import format from "date-fns/format";
export default class Get {
/**
*
* @param params
* @returns {Promise<AxiosResponse<any>>}
*/
list(params) {
return api.get('/api/v2/currencies', {params: params});
}
}

View File

@@ -0,0 +1,35 @@
/*
* get.js
* 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/>.
*/
import {api} from "../../../../boot/axios";
export default class Get {
/**
*
* @param params
* @returns {Promise<AxiosResponse<any>>}
*/
list(params) {
return api.get('/api/v1/piggy-banks', {params: params});
}
}

View File

@@ -0,0 +1,42 @@
/*
* get.js
* 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/>.
*/
import {api} from "../../../../boot/axios";
export default class Get {
/**
*
* @param params
* @returns {Promise<AxiosResponse<any>>}
*/
list(params) {
return api.get('/api/v1/subscriptions', {params: params});
}
paid(params) {
return api.get('/api/v1/subscriptions/sum/paid', {params: params});
}
unpaid(params) {
return api.get('/api/v1/subscriptions/sum/unpaid', {params: params});
}
}

View File

@@ -0,0 +1,37 @@
/*
* get.js
* 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/>.
*/
import {api} from "../../../../boot/axios";
export default class Get {
/**
*
* @param params
* @returns {Promise<AxiosResponse<any>>}
*/
list(params) {
return api.get('/api/v1/transactions', {params: params});
}
show(id, params){
return api.get('/api/v1/transactions/' + id, {params: params});
}
}

View File

@@ -0,0 +1,28 @@
/*
* post.js
* 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/>.
*/
import {api} from "../../../../boot/axios";
export default class Post {
post(submission) {
let url = '/api/v1/transactions';
return api.post(url, submission);
}
}

View File

@@ -0,0 +1,28 @@
/*
* post.js
* 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/>.
*/
import {api} from "../../../../boot/axios";
export default class Put {
put(submission, params) {
let url = '/api/v1/transactions/' + parseInt(params.id);
return api.put(url, submission);
}
}

View File

@@ -0,0 +1,45 @@
/*
* list.js
* 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/>.
*/
import {api} from "../../../../boot/axios";
import format from "date-fns/format";
export default class Get {
/**
*
* @param identifier
* @param params
* @returns {Promise<AxiosResponse<any>>}
*/
show(identifier, params) {
return api.get('/api/v2/user-groups/' + identifier, {params: params});
}
/**
*
* @param params
* @returns {Promise<AxiosResponse<any>>}
*/
index(params) {
return api.get('/api/v2/user-groups', {params: params});
}
}

View File

@@ -0,0 +1,33 @@
/*
* post.js
* 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/.
*/
import {api} from "../../../../boot/axios";
export default class Post {
post(submission) {
let url = './api/v2/user-groups';
return api.post(url, submission);
}
use(groupId) {
let url = './api/v2/user-groups/' + groupId + '/use';
return api.post(url, {});
}
}

View File

@@ -0,0 +1,28 @@
/*
* post.js
* 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/>.
*/
import {api} from "../../../../boot/axios";
export default class Put {
put(submission, params) {
let url = '/api/v2/user-groups/' + parseInt(params.id);
return api.put(url, submission);
}
}

View File

@@ -25,7 +25,7 @@ export default class Dashboard {
dashboard(start, end) {
let startStr = format(start, 'y-MM-dd');
let endStr = format(end, 'y-MM-dd');
return api.get('/api/v2/chart/account/dashboard', {params: {filter: {start: startStr, end: endStr}}});
return api.get('/api/v2/chart/account/dashboard', {params: {start: startStr, end: endStr}});
}
expense(start, end) {

View File

@@ -24,8 +24,8 @@ import i18next from "i18next";
import {format} from "date-fns";
import formatMoney from "../../util/format-money.js";
import Get from "../../api/v2/model/account/get.js";
import Put from "../../api/v2/model/account/put.js";
import Get from "../../api/v1/model/account/get.js";
import Put from "../../api/v1/model/account/put.js";
import AccountRenderer from "../../support/renderers/AccountRenderer.js";
import {showInternalsButton} from "../../support/page-settings/show-internals-button.js";
import {showWizardButton} from "../../support/page-settings/show-wizard-button.js";

View File

@@ -20,7 +20,7 @@
import '../../boot/bootstrap.js';
import dates from "../shared/dates.js";
import Post from "../../api/v2/model/user-group/post.js";
import Post from "../../api/v1/model/user-group/post.js";
import i18next from "i18next";

View File

@@ -20,10 +20,10 @@
import '../../boot/bootstrap.js';
import dates from "../shared/dates.js";
import Post from "../../api/v2/model/user-group/post.js";
import Post from "../../api/v1/model/user-group/post.js";
import i18next from "i18next";
import Get from "../../api/v2/model/user-group/get.js";
import Put from "../../api/v2/model/user-group/put.js";
import Get from "../../api/v1/model/user-group/get.js";
import Put from "../../api/v1/model/user-group/put.js";
let administrations = function () {

View File

@@ -23,11 +23,9 @@ import dates from "../shared/dates.js";
import i18next from "i18next";
import {format} from "date-fns";
import '@ag-grid-community/styles/ag-grid.css';
import '@ag-grid-community/styles/ag-theme-alpine.css';
import '../../css/grid-ff3-theme.css';
import Get from "../../api/v2/model/user-group/get.js";
import Post from "../../api/v2/model/user-group/post.js";
import Get from "../../api/v1/model/user-group/get.js";
import Post from "../../api/v1/model/user-group/post.js";
let index = function () {
return {

View File

@@ -20,9 +20,9 @@
import {getVariable} from "../../store/get-variable.js";
import {setVariable} from "../../store/set-variable.js";
import Dashboard from "../../api/v2/chart/account/dashboard.js";
import Dashboard from "../../api/v1/chart/account/dashboard.js";
import formatMoney from "../../util/format-money.js";
import Get from "../../api/v2/model/account/get.js";
import Get from "../../api/v1/model/account/get.js";
import {Chart} from 'chart.js';
import {getDefaultChartSettings} from "../../support/default-chart-settings.js";
import {getCacheKey} from "../../support/get-cache-key.js";
@@ -39,12 +39,12 @@ export default () => ({
loading: false,
loadingAccounts: false,
accountList: [],
autoConversion: false,
autoConversionAvailable: false,
convertToNative: false,
convertToNativeAvailable: false,
chartOptions: null,
switchAutoConversion() {
this.autoConversion = !this.autoConversion;
setVariable('autoConversion', this.autoConversion);
switchConvertToNative() {
this.convertToNative = !this.convertToNative;
setVariable('convertToNative', this.convertToNative);
},
localCacheKey(type) {
return 'ds_accounts_' + type;
@@ -90,18 +90,18 @@ export default () => ({
dataset.label = current.label;
// use the "native" currency code and use the "native_entries" as array
if (this.autoConversion) {
currencies.push(current.native_currency_code);
dataset.currency_code = current.native_currency_code;
collection = Object.values(current.native_entries);
yAxis = 'y' + current.native_currency_code;
}
if (!this.autoConversion) {
// if (this.convertToNative) {
// currencies.push(current.native_currency_code);
// dataset.currency_code = current.native_currency_code;
// collection = Object.values(current.native_entries);
// yAxis = 'y' + current.native_currency_code;
// }
// if (!this.convertToNative) {
yAxis = 'y' + current.currency_code;
dataset.currency_code = current.currency_code;
currencies.push(current.currency_code);
collection = Object.values(current.entries);
}
// }
dataset.yAxisID = yAxis;
dataset.data = collection;
@@ -217,12 +217,12 @@ export default () => ({
for (let iii = 0; iii < current.attributes.transactions.length; iii++) {
let currentTransaction = current.attributes.transactions[iii];
//console.log(currentTransaction);
let nativeAmountRaw = 'withdrawal' === currentTransaction.type ? parseFloat(currentTransaction.native_amount) * -1 : parseFloat(currentTransaction.native_amount);
//let nativeAmountRaw = 'withdrawal' === currentTransaction.type ? parseFloat(currentTransaction.native_amount) * -1 : parseFloat(currentTransaction.native_amount);
let amountRaw = 'withdrawal' === currentTransaction.type ? parseFloat(currentTransaction.amount) * -1 : parseFloat(currentTransaction.amount);
// if transfer and source is this account, multiply again
if('transfer' === currentTransaction.type && parseInt(currentTransaction.source_id) === accountId) { //
nativeAmountRaw = nativeAmountRaw * -1;
// nativeAmountRaw = nativeAmountRaw * -1;
amountRaw = amountRaw * -1;
}
@@ -232,8 +232,8 @@ export default () => ({
type: currentTransaction.type,
amount_raw: amountRaw,
amount: formatMoney(amountRaw, currentTransaction.currency_code),
native_amount_raw: nativeAmountRaw,
native_amount: formatMoney(nativeAmountRaw, currentTransaction.native_currency_code),
// native_amount_raw: nativeAmountRaw,
// native_amount: formatMoney(nativeAmountRaw, currentTransaction.native_currency_code),
});
}
groups.push(group);
@@ -244,7 +244,7 @@ export default () => ({
order: parent.attributes.order,
id: parent.id,
balance: parent.attributes.balance,
native_balance: parent.attributes.native_balance,
//native_balance: parent.attributes.native_balance,
groups: groups,
});
// console.log(parent.attributes);
@@ -266,12 +266,12 @@ export default () => ({
init() {
// console.log('accounts init');
Promise.all([getVariable('viewRange', '1M'), getVariable('autoConversion', false), getVariable('language', 'en_US'),
Promise.all([getVariable('viewRange', '1M'), getVariable('convertToNative', false), getVariable('language', 'en_US'),
getConfiguration('cer.enabled', false)
]).then((values) => {
//console.log('accounts after promises');
this.autoConversion = values[1] && values[3];
this.autoConversionAvailable = values[3];
this.convertToNative = values[1] && values[3];
this.convertToNativeAvailable = values[3];
afterPromises = true;
// main dashboard chart:
@@ -289,11 +289,11 @@ export default () => ({
this.loadChart();
this.loadAccounts();
});
window.store.observe('autoConversion', () => {
window.store.observe('convertToNative', () => {
if (!afterPromises) {
return;
}
// console.log('accounts observe autoconversion');
// console.log('accounts observe convertToNative');
this.loadChart();
this.loadAccounts();
});

View File

@@ -18,7 +18,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Summary from "../../api/v2/summary/index.js";
import Summary from "../../api/v1/summary/index.js";
import {format} from "date-fns";
import {getVariable} from "../../store/get-variable.js";
import formatMoney from "../../util/format-money.js";
@@ -31,7 +31,7 @@ export default () => ({
billBox: {paid: [], unpaid: []},
leftBox: {left: [], perDay: []},
netBox: {net: []},
autoConversion: false,
convertToNative: false,
loading: false,
boxData: null,
boxOptions: null,
@@ -42,8 +42,9 @@ export default () => ({
const boxesCacheKey = getCacheKey('ds_boxes_data', {start: start, end: end});
cleanupCache();
const cacheValid = window.store.get('cacheValid');
//const cacheValid = window.store.get('cacheValid');
let cachedData = window.store.get(boxesCacheKey);
const cacheValid = false; // force refresh
if (cacheValid && typeof cachedData !== 'undefined') {
this.boxData = cachedData;
@@ -75,114 +76,56 @@ export default () => ({
continue;
}
let key = current.key;
// native (auto conversion):
if (this.autoConversion) {
if (key.startsWith('balance-in-native')) {
this.balanceBox.amounts.push(formatMoney(current.value, current.currency_code));
// prep subtitles (for later)
if (!subtitles.hasOwnProperty(current.currency_code)) {
subtitles[current.currency_code] = '';
}
continue;
}
// spent info is used in subtitle:
if (key.startsWith('spent-in-native')) {
// prep subtitles (for later)
if (!subtitles.hasOwnProperty(current.currency_code)) {
subtitles[current.currency_code] = '';
}
// append the amount spent.
subtitles[current.currency_code] =
subtitles[current.currency_code] +
formatMoney(current.value, current.currency_code);
continue;
}
// earned info is used in subtitle:
if (key.startsWith('earned-in-native')) {
// prep subtitles (for later)
if (!subtitles.hasOwnProperty(current.currency_code)) {
subtitles[current.currency_code] = '';
}
// prepend the amount earned.
subtitles[current.currency_code] =
formatMoney(current.value, current.currency_code) + ' + ' +
subtitles[current.currency_code];
continue;
}
if (key.startsWith('bills-unpaid-in-native')) {
this.billBox.unpaid.push(formatMoney(current.value, current.currency_code));
continue;
}
if (key.startsWith('bills-paid-in-native')) {
this.billBox.paid.push(formatMoney(current.value, current.currency_code));
continue;
}
if (key.startsWith('left-to-spend-in-native')) {
this.leftBox.left.push(formatMoney(current.value, current.currency_code));
continue;
}
if (key.startsWith('left-per-day-to-spend-in-native')) { // per day
this.leftBox.perDay.push(formatMoney(current.value, current.currency_code));
continue;
}
if (key.startsWith('net-worth-in-native')) {
this.netBox.net.push(formatMoney(current.value, current.currency_code));
continue;
}
console.log('NOT NATIVE');
if (key.startsWith('balance-in-')) {
this.balanceBox.amounts.push(formatMoney(current.monetary_value, current.currency_code));
continue;
}
// not native
if (!this.autoConversion && !key.endsWith('native')) {
if (key.startsWith('balance-in-')) {
this.balanceBox.amounts.push(formatMoney(current.value, current.currency_code));
continue;
// spent info is used in subtitle:
if (key.startsWith('spent-in-')) {
// prep subtitles (for later)
if (!subtitles.hasOwnProperty(current.currency_code)) {
subtitles[current.currency_code] = '';
}
// spent info is used in subtitle:
if (key.startsWith('spent-in-')) {
// prep subtitles (for later)
if (!subtitles.hasOwnProperty(current.currency_code)) {
subtitles[current.currency_code] = '';
}
// append the amount spent.
subtitles[current.currency_code] =
subtitles[current.currency_code] +
formatMoney(current.value, current.currency_code);
continue;
}
// earned info is used in subtitle:
if (key.startsWith('earned-in-')) {
// prep subtitles (for later)
if (!subtitles.hasOwnProperty(current.currency_code)) {
subtitles[current.currency_code] = '';
}
// prepend the amount earned.
subtitles[current.currency_code] =
formatMoney(current.value, current.currency_code) + ' + ' +
subtitles[current.currency_code];
continue;
// append the amount spent.
subtitles[current.currency_code] =
subtitles[current.currency_code] +
formatMoney(current.monetary_value, current.currency_code);
continue;
}
// earned info is used in subtitle:
if (key.startsWith('earned-in-')) {
// prep subtitles (for later)
if (!subtitles.hasOwnProperty(current.currency_code)) {
subtitles[current.currency_code] = '';
}
// prepend the amount earned.
subtitles[current.currency_code] =
formatMoney(current.monetary_value, current.currency_code) + ' + ' +
subtitles[current.currency_code];
continue;
}
if (key.startsWith('bills-unpaid-in-')) {
this.billBox.unpaid.push(formatMoney(current.value, current.currency_code));
continue;
}
if (key.startsWith('bills-paid-in-')) {
this.billBox.paid.push(formatMoney(current.value, current.currency_code));
continue;
}
if (key.startsWith('left-to-spend-in-')) {
this.leftBox.left.push(formatMoney(current.value, current.currency_code));
continue;
}
if (key.startsWith('left-per-day-to-spend-in-')) {
this.leftBox.perDay.push(formatMoney(current.value, current.currency_code));
continue;
}
if (key.startsWith('net-worth-in-')) {
this.netBox.net.push(formatMoney(current.value, current.currency_code));
if (key.startsWith('bills-unpaid-in-')) {
this.billBox.unpaid.push(formatMoney(current.monetary_value, current.currency_code));
continue;
}
if (key.startsWith('bills-paid-in-')) {
this.billBox.paid.push(formatMoney(current.monetary_value, current.currency_code));
continue;
}
if (key.startsWith('left-to-spend-in-')) {
this.leftBox.left.push(formatMoney(current.monetary_value, current.currency_code));
continue;
}
if (key.startsWith('left-per-day-to-spend-in-')) {
this.leftBox.perDay.push(formatMoney(current.monetary_value, current.currency_code));
continue;
}
if (key.startsWith('net-worth-in-')) {
this.netBox.net.push(formatMoney(current.monetary_value, current.currency_code));
}
}
}
}
@@ -210,10 +153,10 @@ export default () => ({
init() {
// console.log('boxes init');
// TODO can be replaced by "getVariables"
Promise.all([getVariable('viewRange'), getVariable('autoConversion', false)]).then((values) => {
Promise.all([getVariable('viewRange'), getVariable('convertToNative', false)]).then((values) => {
// console.log('boxes after promises');
afterPromises = true;
this.autoConversion = values[1];
this.convertToNative = values[1];
this.loadBoxes();
});
window.store.observe('end', () => {
@@ -224,12 +167,12 @@ export default () => ({
this.boxData = null;
this.loadBoxes();
});
window.store.observe('autoConversion', (newValue) => {
window.store.observe('convertToNative', (newValue) => {
if (!afterPromises) {
return;
}
// console.log('boxes observe autoConversion');
this.autoConversion = newValue;
// console.log('boxes observe convertToNative');
this.convertToNative = newValue;
this.loadBoxes();
});
},

View File

@@ -18,7 +18,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {getVariable} from "../../store/get-variable.js";
import Dashboard from "../../api/v2/chart/budget/dashboard.js";
import Dashboard from "../../api/v1/chart/budget/dashboard.js";
import {getDefaultChartSettings} from "../../support/default-chart-settings.js";
import formatMoney from "../../util/format-money.js";
import {Chart} from 'chart.js';
@@ -34,7 +34,7 @@ let afterPromises = false;
export default () => ({
loading: false,
autoConversion: false,
convertToNative: false,
loadChart() {
if (true === this.loading) {
return;
@@ -134,7 +134,7 @@ export default () => ({
// // convert to EUR yes no?
let label = current.label + ' (' + current.currency_code + ')';
options.data.labels.push(label);
if (this.autoConversion) {
if (this.convertToNative) {
currencies.push(current.native_currency_code);
// series 0: spent
options.data.datasets[0].data.push(parseFloat(current.native_entries.spent) * -1);
@@ -143,7 +143,7 @@ export default () => ({
// series 2: overspent
options.data.datasets[2].data.push(parseFloat(current.native_entries.overspent));
}
if (!this.autoConversion) {
if (!this.convertToNative) {
currencies.push(current.currency_code);
// series 0: spent
options.data.datasets[0].data.push(parseFloat(current.entries.spent) * -1);
@@ -172,8 +172,8 @@ export default () => ({
init() {
Promise.all([getVariable('autoConversion', false)]).then((values) => {
this.autoConversion = values[0];
Promise.all([getVariable('convertToNative', false)]).then((values) => {
this.convertToNative = values[0];
afterPromises = true;
if (false === this.loading) {
this.loadChart();
@@ -189,12 +189,12 @@ export default () => ({
this.loadChart();
}
});
window.store.observe('autoConversion', (newValue) => {
window.store.observe('convertToNative', (newValue) => {
if (!afterPromises) {
return;
}
// console.log('boxes observe autoConversion');
this.autoConversion = newValue;
// console.log('boxes observe convertToNative');
this.convertToNative = newValue;
if (false === this.loading) {
this.loadChart();
}

View File

@@ -18,7 +18,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {getVariable} from "../../store/get-variable.js";
import Dashboard from "../../api/v2/chart/category/dashboard.js";
import Dashboard from "../../api/v1/chart/category/dashboard.js";
import {getDefaultChartSettings} from "../../support/default-chart-settings.js";
import {Chart} from "chart.js";
import formatMoney from "../../util/format-money.js";
@@ -32,7 +32,7 @@ let afterPromises = false;
export default () => ({
loading: false,
autoConversion: false,
convertToNative: false,
generateOptions(data) {
currencies = [];
let options = getDefaultChartSettings('column');
@@ -44,7 +44,7 @@ export default () => ({
let current = data[i];
let code = current.currency_code;
// only use native code when doing auto conversion.
if (this.autoConversion) {
if (this.convertToNative) {
code = current.native_currency_code;
}
@@ -65,7 +65,7 @@ export default () => ({
let yAxis = 'y';
let current = data[i];
let code = current.currency_code;
if (this.autoConversion) {
if (this.convertToNative) {
code = current.native_currency_code;
}
@@ -77,7 +77,7 @@ export default () => ({
// this series' currency matches this column's currency.
amount = parseFloat(current.amount);
yAxis = 'y' + current.currency_code;
if (this.autoConversion) {
if (this.convertToNative) {
amount = parseFloat(current.native_amount);
yAxis = 'y' + current.native_currency_code;
}
@@ -183,8 +183,8 @@ export default () => ({
},
init() {
// console.log('categories init');
Promise.all([getVariable('autoConversion', false),]).then((values) => {
this.autoConversion = values[0];
Promise.all([getVariable('convertToNative', false),]).then((values) => {
this.convertToNative = values[0];
afterPromises = true;
this.loadChart();
});
@@ -195,11 +195,11 @@ export default () => ({
this.chartData = null;
this.loadChart();
});
window.store.observe('autoConversion', (newValue) => {
window.store.observe('convertToNative', (newValue) => {
if (!afterPromises) {
return;
}
this.autoConversion = newValue;
this.convertToNative = newValue;
this.loadChart();
});
},

View File

@@ -18,7 +18,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {getVariable} from "../../store/get-variable.js";
import Get from "../../api/v2/model/piggy-bank/get.js";
import Get from "../../api/v1/model/piggy-bank/get.js";
import {getCacheKey} from "../../support/get-cache-key.js";
import {format} from "date-fns";
import i18next from "i18next";
@@ -29,7 +29,7 @@ const PIGGY_CACHE_KEY = 'ds_pg_data';
export default () => ({
loading: false,
autoConversion: false,
convertToNative: false,
sankeyGrouping: 'account',
piggies: [],
getFreshData() {
@@ -96,14 +96,14 @@ export default () => ({
id: current.id,
name: current.attributes.name,
percentage: parseInt(current.attributes.percentage),
amount: this.autoConversion ? current.attributes.native_current_amount : current.attributes.current_amount,
amount: this.convertToNative ? current.attributes.native_current_amount : current.attributes.current_amount,
// left to save
left_to_save: this.autoConversion ? current.attributes.native_left_to_save : current.attributes.left_to_save,
left_to_save: this.convertToNative ? current.attributes.native_left_to_save : current.attributes.left_to_save,
// target amount
target_amount: this.autoConversion ? current.attributes.native_target_amount : current.attributes.target_amount,
target_amount: this.convertToNative ? current.attributes.native_target_amount : current.attributes.target_amount,
// save per month
save_per_month: this.autoConversion ? current.attributes.native_save_per_month : current.attributes.save_per_month,
currency_code: this.autoConversion ? current.attributes.native_currency_code : current.attributes.currency_code,
save_per_month: this.convertToNative ? current.attributes.native_save_per_month : current.attributes.save_per_month,
currency_code: this.convertToNative ? current.attributes.native_currency_code : current.attributes.currency_code,
};
dataSet[groupName].piggies.push(piggy);
@@ -129,10 +129,10 @@ export default () => ({
init() {
// console.log('piggies init');
apiData = [];
Promise.all([getVariable('autoConversion', false)]).then((values) => {
Promise.all([getVariable('convertToNative', false)]).then((values) => {
afterPromises = true;
this.autoConversion = values[0];
this.convertToNative = values[0];
this.loadPiggyBanks();
});
@@ -144,12 +144,12 @@ export default () => ({
apiData = [];
this.loadPiggyBanks();
});
window.store.observe('autoConversion', (newValue) => {
window.store.observe('convertToNative', (newValue) => {
if (!afterPromises) {
return;
}
// console.log('piggies observe autoConversion');
this.autoConversion = newValue;
// console.log('piggies observe convertToNative');
this.convertToNative = newValue;
this.loadPiggyBanks();
});
},

View File

@@ -18,7 +18,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {getVariable} from "../../store/get-variable.js";
import Get from "../../api/v2/model/transaction/get.js";
import Get from "../../api/v1/model/transaction/get.js";
import {getDefaultChartSettings} from "../../support/default-chart-settings.js";
import {Chart} from 'chart.js';
import {Flow, SankeyController} from 'chartjs-chart-sankey';
@@ -33,7 +33,7 @@ let currencies = [];
let afterPromises = false;
let chart = null;
let transactions = [];
let autoConversion = false;
let convertToNative = false;
let translations = {
category: null,
unknown_category: null,
@@ -83,37 +83,37 @@ function getObjectName(type, name, direction, code) {
// category 4x
if ('category' === type && null !== name && 'in' === direction) {
return translations.category + ' "' + name + '" (' + translations.in + (autoConversion ? ', ' + code + ')' : ')');
return translations.category + ' "' + name + '" (' + translations.in + (convertToNative ? ', ' + code + ')' : ')');
}
if ('category' === type && null === name && 'in' === direction) {
return translations.unknown_category + ' (' + translations.in + (autoConversion ? ', ' + code + ')' : ')');
return translations.unknown_category + ' (' + translations.in + (convertToNative ? ', ' + code + ')' : ')');
}
if ('category' === type && null !== name && 'out' === direction) {
return translations.category + ' "' + name + '" (' + translations.out + (autoConversion ? ', ' + code + ')' : ')');
return translations.category + ' "' + name + '" (' + translations.out + (convertToNative ? ', ' + code + ')' : ')');
}
if ('category' === type && null === name && 'out' === direction) {
return translations.unknown_category + ' (' + translations.out + (autoConversion ? ', ' + code + ')' : ')');
return translations.unknown_category + ' (' + translations.out + (convertToNative ? ', ' + code + ')' : ')');
}
// account 4x
if ('account' === type && null === name && 'in' === direction) {
return translations.unknown_source + (autoConversion ? ' (' + code + ')' : '');
return translations.unknown_source + (convertToNative ? ' (' + code + ')' : '');
}
if ('account' === type && null !== name && 'in' === direction) {
return translations.revenue_account + '"' + name + '"' + (autoConversion ? ' (' + code + ')' : '');
return translations.revenue_account + '"' + name + '"' + (convertToNative ? ' (' + code + ')' : '');
}
if ('account' === type && null === name && 'out' === direction) {
return translations.unknown_dest + (autoConversion ? ' (' + code + ')' : '');
return translations.unknown_dest + (convertToNative ? ' (' + code + ')' : '');
}
if ('account' === type && null !== name && 'out' === direction) {
return translations.expense_account + ' "' + name + '"' + (autoConversion ? ' (' + code + ')' : '');
return translations.expense_account + ' "' + name + '"' + (convertToNative ? ' (' + code + ')' : '');
}
// budget 2x
if ('budget' === type && null !== name) {
return translations.budget + ' "' + name + '"' + (autoConversion ? ' (' + code + ')' : '');
return translations.budget + ' "' + name + '"' + (convertToNative ? ' (' + code + ')' : '');
}
if ('budget' === type && null === name) {
return translations.unknown_budget + (autoConversion ? ' (' + code + ')' : '');
return translations.unknown_budget + (convertToNative ? ' (' + code + ')' : '');
}
console.error('Cannot handle: type:"' + type + '", dir: "' + direction + '"');
}
@@ -121,25 +121,25 @@ function getObjectName(type, name, direction, code) {
function getLabelName(type, name, code) {
// category
if ('category' === type && null !== name) {
return translations.category + ' "' + name + '"' + (autoConversion ? ' (' + code + ')' : '');
return translations.category + ' "' + name + '"' + (convertToNative ? ' (' + code + ')' : '');
}
if ('category' === type && null === name) {
return translations.unknown_category + (autoConversion ? ' (' + code + ')' : '');
return translations.unknown_category + (convertToNative ? ' (' + code + ')' : '');
}
// account
if ('account' === type && null === name) {
return translations.unknown_account + (autoConversion ? ' (' + code + ')' : '');
return translations.unknown_account + (convertToNative ? ' (' + code + ')' : '');
}
if ('account' === type && null !== name) {
return name + (autoConversion ? ' (' + code + ')' : '');
return name + (convertToNative ? ' (' + code + ')' : '');
}
// budget 2x
if ('budget' === type && null !== name) {
return translations.budget + ' "' + name + '"' + (autoConversion ? ' (' + code + ')' : '');
return translations.budget + ' "' + name + '"' + (convertToNative ? ' (' + code + ')' : '');
}
if ('budget' === type && null === name) {
return translations.unknown_budget + (autoConversion ? ' (' + code + ')' : '');
return translations.unknown_budget + (convertToNative ? ' (' + code + ')' : '');
}
console.error('Cannot handle: type:"' + type + '"');
}
@@ -147,7 +147,7 @@ function getLabelName(type, name, code) {
export default () => ({
loading: false,
autoConversion: false,
convertToNative: false,
generateOptions() {
let options = getDefaultChartSettings('sankey');
@@ -164,8 +164,8 @@ export default () => ({
if (group.attributes.transactions.hasOwnProperty(ii)) {
// properties of the transaction, used in the generation of the chart:
let transaction = group.attributes.transactions[ii];
let currencyCode = this.autoConversion ? transaction.native_currency_code : transaction.currency_code;
let amount = this.autoConversion ? parseFloat(transaction.native_amount) : parseFloat(transaction.amount);
let currencyCode = this.convertToNative ? transaction.native_currency_code : transaction.currency_code;
let amount = this.convertToNative ? parseFloat(transaction.native_amount) : parseFloat(transaction.amount);
let flowKey;
/*
@@ -194,7 +194,7 @@ export default () => ({
if (!amounts.hasOwnProperty(flowKey)) {
amounts[flowKey] = {
from: category,
to: translations.all_money + (this.autoConversion ? ' (' + currencyCode + ')' : ''),
to: translations.all_money + (this.convertToNative ? ' (' + currencyCode + ')' : ''),
amount: 0
};
}
@@ -214,7 +214,7 @@ export default () => ({
if (!amounts.hasOwnProperty(flowKey)) {
amounts[flowKey] = {
from: translations.all_money + (this.autoConversion ? ' (' + currencyCode + ')' : ''),
from: translations.all_money + (this.convertToNative ? ' (' + currencyCode + ')' : ''),
to: budget,
amount: 0
};
@@ -348,9 +348,9 @@ export default () => ({
init() {
// console.log('sankey init');
transactions = [];
Promise.all([getVariable('autoConversion', false)]).then((values) => {
this.autoConversion = values[0];
autoConversion = values[0];
Promise.all([getVariable('convertToNative', false)]).then((values) => {
this.convertToNative = values[0];
convertToNative = values[0];
// some translations:
translations.all_money = i18next.t('firefly.all_money');
translations.category = i18next.t('firefly.category');
@@ -378,12 +378,12 @@ export default () => ({
this.transactions = [];
this.loadChart();
});
window.store.observe('autoConversion', (newValue) => {
window.store.observe('convertToNative', (newValue) => {
if (!afterPromises) {
return;
}
// console.log('sankey observe autoConversion');
this.autoConversion = newValue;
// console.log('sankey observe convertToNative');
this.convertToNative = newValue;
this.loadChart();
});
},

View File

@@ -18,7 +18,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {getVariable} from "../../store/get-variable.js";
import Get from "../../api/v2/model/subscription/get.js";
import Get from "../../api/v1/model/subscription/get.js";
import {format} from "date-fns";
import {getCacheKey} from "../../support/get-cache-key.js";
import {Chart} from "chart.js";
@@ -66,10 +66,10 @@ function downloadSubscriptions(params) {
currency_code: current.attributes.currency_code,
// native amount
native_amount_min: current.attributes.native_amount_min,
native_amount_max: current.attributes.native_amount_max,
native_amount: (parseFloat(current.attributes.native_amount_max) + parseFloat(current.attributes.native_amount_min)) / 2,
native_currency_code: current.attributes.native_currency_code,
// native_amount_min: current.attributes.native_amount_min,
// native_amount_max: current.attributes.native_amount_max,
// native_amount: (parseFloat(current.attributes.native_amount_max) + parseFloat(current.attributes.native_amount_min)) / 2,
// native_currency_code: current.attributes.native_currency_code,
// paid transactions:
transactions: [],
@@ -79,8 +79,7 @@ function downloadSubscriptions(params) {
paid: current.attributes.paid_dates.length > 0,
};
// set variables
bill.expected_amount = params.autoConversion ? formatMoney(bill.native_amount, bill.native_currency_code) :
formatMoney(bill.amount, bill.currency_code);
bill.expected_amount = formatMoney(bill.amount, bill.currency_code);
bill.expected_times = i18next.t('firefly.subscr_expected_x_times', {
times: current.attributes.pay_dates.length,
amount: bill.expected_amount
@@ -92,22 +91,25 @@ function downloadSubscriptions(params) {
const currentPayment = current.attributes.paid_dates[iii];
let percentage = 100;
// math: -100+(paid/expected)*100
if (params.autoConversion) {
if (params.convertToNative) {
percentage = Math.round(-100 + ((parseFloat(currentPayment.native_amount) * -1) / parseFloat(bill.native_amount)) * 100);
}
if (!params.autoConversion) {
if (!params.convertToNative) {
percentage = Math.round(-100 + ((parseFloat(currentPayment.amount) * -1) / parseFloat(bill.amount)) * 100);
}
// TODO fix me
currentPayment.currency_code = 'EUR';
console.log('Currency code: "'+currentPayment+'"');
console.log(currentPayment);
let currentTransaction = {
amount: params.autoConversion ? formatMoney(currentPayment.native_amount, currentPayment.native_currency_code) : formatMoney(currentPayment.amount, currentPayment.currency_code),
amount: formatMoney(currentPayment.amount, currentPayment.currency_code),
percentage: percentage,
date: format(new Date(currentPayment.date), 'PP'),
foreign_amount: null,
};
if (null !== currentPayment.foreign_currency_code) {
currentTransaction.foreign_amount = params.autoConversion ? currentPayment.foreign_native_amount : currentPayment.foreign_amount;
currentTransaction.foreign_currency_code = params.autoConversion ? currentPayment.native_currency_code : currentPayment.foreign_currency_code;
currentTransaction.foreign_amount = currentPayment.foreign_amount;
currentTransaction.foreign_currency_code = currentPayment.foreign_currency_code;
}
bill.transactions.push(currentTransaction);
@@ -119,7 +121,7 @@ function downloadSubscriptions(params) {
// bill is unpaid, count the "pay_dates" and multiply with the "amount".
// since bill is unpaid, this can only be in currency amount and native currency amount.
const totalAmount = current.attributes.pay_dates.length * bill.amount;
const totalNativeAmount = current.attributes.pay_dates.length * bill.native_amount;
// const totalNativeAmount = current.attributes.pay_dates.length * bill.native_amount;
// for bill's currency
if (!subscriptionData[objectGroupId].payment_info.hasOwnProperty(bill.currency_code)) {
subscriptionData[objectGroupId].payment_info[bill.currency_code] = {
@@ -128,11 +130,11 @@ function downloadSubscriptions(params) {
unpaid: 0,
native_currency_code: bill.native_currency_code,
native_paid: 0,
native_unpaid: 0,
//native_unpaid: 0,
};
}
subscriptionData[objectGroupId].payment_info[bill.currency_code].unpaid += totalAmount;
subscriptionData[objectGroupId].payment_info[bill.currency_code].native_unpaid += totalNativeAmount;
//subscriptionData[objectGroupId].payment_info[bill.currency_code].native_unpaid += totalNativeAmount;
}
if (current.attributes.paid_dates.length > 0) {
@@ -149,15 +151,15 @@ function downloadSubscriptions(params) {
currency_code: bill.currency_code,
paid: 0,
unpaid: 0,
native_currency_code: bill.native_currency_code,
native_paid: 0,
native_unpaid: 0,
// native_currency_code: bill.native_currency_code,
// native_paid: 0,
//native_unpaid: 0,
};
}
const amount = parseFloat(currentJournal.amount) * -1;
const nativeAmount = parseFloat(currentJournal.native_amount) * -1;
// const nativeAmount = parseFloat(currentJournal.native_amount) * -1;
subscriptionData[objectGroupId].payment_info[currentJournal.currency_code].paid += amount;
subscriptionData[objectGroupId].payment_info[currentJournal.currency_code].native_paid += nativeAmount;
// subscriptionData[objectGroupId].payment_info[currentJournal.currency_code].native_paid += nativeAmount;
}
}
}
@@ -178,7 +180,7 @@ function downloadSubscriptions(params) {
export default () => ({
loading: false,
autoConversion: false,
convertToNative: false,
subscriptions: [],
startSubscriptions() {
this.loading = true;
@@ -198,7 +200,7 @@ export default () => ({
let params = {
start: format(start, 'y-MM-dd'),
end: format(end, 'y-MM-dd'),
autoConversion: this.autoConversion,
// convertToNative: this.convertToNative,
page: 1
};
downloadSubscriptions(params).then(() => {
@@ -226,9 +228,9 @@ export default () => ({
drawPieChart(groupId, groupTitle, data) {
let id = '#pie_' + groupId + '_' + data.currency_code;
//console.log(data);
const unpaidAmount = this.autoConversion ? data.native_unpaid : data.unpaid;
const paidAmount = this.autoConversion ? data.native_paid : data.paid;
const currencyCode = this.autoConversion ? data.native_currency_code : data.currency_code;
const unpaidAmount = data.unpaid;
const paidAmount = data.paid;
const currencyCode = data.currency_code;
const chartData = {
labels: [
i18next.t('firefly.paid'),
@@ -267,8 +269,8 @@ export default () => ({
},
init() {
Promise.all([getVariable('autoConversion', false)]).then((values) => {
this.autoConversion = values[0];
Promise.all([getVariable('convertToNative', false)]).then((values) => {
this.convertToNative = values[0];
afterPromises = true;
if (false === this.loading) {
@@ -285,11 +287,11 @@ export default () => ({
this.startSubscriptions();
}
});
window.store.observe('autoConversion', (newValue) => {
window.store.observe('convertToNative', (newValue) => {
if (!afterPromises) {
return;
}
this.autoConversion = newValue;
this.convertToNative = newValue;
if (false === this.loading) {
this.startSubscriptions();
}

View File

@@ -23,7 +23,7 @@ import dates from '../../pages/shared/dates.js';
import {createEmptySplit, defaultErrorSet} from "./shared/create-empty-split.js";
import {parseFromEntries} from "./shared/parse-from-entries.js";
import formatMoney from "../../util/format-money.js";
import Post from "../../api/v2/model/transaction/post.js";
import Post from "../../api/v1/model/transaction/post.js";
import {loadCurrencies} from "./shared/load-currencies.js";
import {loadBudgets} from "./shared/load-budgets.js";
import {loadPiggyBanks} from "./shared/load-piggy-banks.js";

View File

@@ -21,7 +21,7 @@
import '../../boot/bootstrap.js';
import dates from '../../pages/shared/dates.js';
import formatMoney from "../../util/format-money.js";
import Get from "../../api/v2/model/transaction/get.js";
import Get from "../../api/v1/model/transaction/get.js";
import {parseDownloadedSplits} from "./shared/parse-downloaded-splits.js";
import {addAutocomplete, getUrls} from "./shared/add-autocomplete.js";
import {
@@ -40,7 +40,7 @@ import Tags from "bootstrap5-tags";
import i18next from "i18next";
import {defaultErrorSet} from "./shared/create-empty-split.js";
import {parseFromEntries} from "./shared/parse-from-entries.js";
import Put from "../../api/v2/model/transaction/put.js";
import Put from "../../api/v1/model/transaction/put.js";
import {processAttachments} from "./shared/process-attachments.js";
import {spliceErrorsIntoTransactions} from "./shared/splice-errors-into-transactions.js";

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