Compare commits

..

76 Commits

Author SHA1 Message Date
James Cole
a59d7ccdc2 Merge branch 'release/v6.0.21' 2023-09-01 05:33:50 +02:00
James Cole
2c1ca428db Update meta files for new release. 2023-09-01 05:33:02 +02:00
James Cole
224970f3bd New version 2023-09-01 05:16:58 +02:00
James Cole
742d934ddb Catch missing key. 2023-09-01 04:42:49 +02:00
James Cole
1699513023 Fix test 2023-08-31 19:18:16 +02:00
James Cole
488a8a7e86 Fix test 2023-08-31 19:13:06 +02:00
James Cole
dd571d6221 Fix test 2023-08-31 19:02:38 +02:00
James Cole
4cc5128b4c Use relative urls see what breaks. 2023-08-31 18:45:11 +02:00
James Cole
2636a6557a Less notice events. 2023-08-30 18:03:47 +02:00
James Cole
0bf97ccf22 Expand logging 2023-08-30 15:57:59 +02:00
James Cole
592fc71b4e Change some logging settings. 2023-08-30 15:38:15 +02:00
James Cole
0e7712d3b8 Add more tracing 2023-08-30 11:58:44 +02:00
James Cole
80f21d2a4f Fix test 2023-08-30 07:06:43 +02:00
James Cole
5513ec068e Fix test 2023-08-30 06:53:46 +02:00
James Cole
14a46a6197 Add more info to error message. 2023-08-30 06:40:12 +02:00
James Cole
b93ee5efd8 Sort accounts properly 2023-08-29 18:28:29 +02:00
James Cole
cdd4dc6065 Rebuild frontend 2023-08-29 07:34:41 +02:00
James Cole
0d8b2ae799 Fix https://github.com/firefly-iii/firefly-iii/issues/7910 2023-08-29 05:47:13 +02:00
James Cole
77dc79b638 Merge pull request #7898 from firefly-iii/dependabot/composer/develop/phpstan/phpstan-1.10.32 2023-08-28 05:51:54 +02:00
dependabot[bot]
f48723db40 chore(deps-dev): bump phpstan/phpstan from 1.10.29 to 1.10.32
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.29 to 1.10.32.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.29...1.10.32)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-28 03:50:38 +00:00
James Cole
ebf91078c5 Merge pull request #7899 from firefly-iii/dependabot/composer/develop/guzzlehttp/guzzle-7.8.0 2023-08-28 05:50:17 +02:00
James Cole
90d0d85dd6 Merge pull request #7900 from firefly-iii/dependabot/composer/develop/laravel/framework-10.20.0 2023-08-28 05:50:06 +02:00
James Cole
0c5b4f7f64 Merge pull request #7901 from firefly-iii/dependabot/composer/develop/laravel/sanctum-3.2.6 2023-08-28 05:49:57 +02:00
James Cole
9c4bb08ed1 Merge pull request #7902 from firefly-iii/dependabot/composer/develop/spatie/laravel-ignition-2.3.0 2023-08-28 05:49:46 +02:00
James Cole
1d3bbde4b0 Merge pull request #7903 from firefly-iii/dependabot/npm_and_yarn/develop/axios-1.5.0 2023-08-28 05:49:36 +02:00
James Cole
b6faee033d Merge pull request #7904 from firefly-iii/dependabot/npm_and_yarn/develop/alpinejs-3.13.0 2023-08-28 05:49:27 +02:00
James Cole
05e0f88d11 Merge pull request #7905 from firefly-iii/dependabot/npm_and_yarn/develop/chart.js-4.4.0 2023-08-28 05:49:17 +02:00
dependabot[bot]
ae9a151140 chore(deps): bump chart.js from 4.3.3 to 4.4.0
Bumps [chart.js](https://github.com/chartjs/Chart.js) from 4.3.3 to 4.4.0.
- [Release notes](https://github.com/chartjs/Chart.js/releases)
- [Commits](https://github.com/chartjs/Chart.js/compare/v4.3.3...v4.4.0)

---
updated-dependencies:
- dependency-name: chart.js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-28 03:25:21 +00:00
dependabot[bot]
da633e3c62 chore(deps): bump alpinejs from 3.12.3 to 3.13.0
Bumps [alpinejs](https://github.com/alpinejs/alpine/tree/HEAD/packages/alpinejs) from 3.12.3 to 3.13.0.
- [Release notes](https://github.com/alpinejs/alpine/releases)
- [Commits](https://github.com/alpinejs/alpine/commits/v3.13.0/packages/alpinejs)

---
updated-dependencies:
- dependency-name: alpinejs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-28 03:25:10 +00:00
dependabot[bot]
8cb384d3cf chore(deps-dev): bump axios from 1.4.0 to 1.5.0
Bumps [axios](https://github.com/axios/axios) from 1.4.0 to 1.5.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.4.0...v1.5.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-28 03:24:59 +00:00
dependabot[bot]
de2a34c3ec chore(deps): bump spatie/laravel-ignition from 2.2.0 to 2.3.0
Bumps [spatie/laravel-ignition](https://github.com/spatie/laravel-ignition) from 2.2.0 to 2.3.0.
- [Release notes](https://github.com/spatie/laravel-ignition/releases)
- [Changelog](https://github.com/spatie/laravel-ignition/blob/main/CHANGELOG.md)
- [Commits](https://github.com/spatie/laravel-ignition/compare/2.2.0...2.3.0)

---
updated-dependencies:
- dependency-name: spatie/laravel-ignition
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-28 03:06:43 +00:00
dependabot[bot]
b7c65446a8 chore(deps): bump laravel/sanctum from 3.2.5 to 3.2.6
Bumps [laravel/sanctum](https://github.com/laravel/sanctum) from 3.2.5 to 3.2.6.
- [Release notes](https://github.com/laravel/sanctum/releases)
- [Changelog](https://github.com/laravel/sanctum/blob/3.x/CHANGELOG.md)
- [Commits](https://github.com/laravel/sanctum/compare/v3.2.5...v3.2.6)

---
updated-dependencies:
- dependency-name: laravel/sanctum
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-28 03:06:31 +00:00
dependabot[bot]
bc648b187c chore(deps): bump laravel/framework from 10.19.0 to 10.20.0
Bumps [laravel/framework](https://github.com/laravel/framework) from 10.19.0 to 10.20.0.
- [Release notes](https://github.com/laravel/framework/releases)
- [Changelog](https://github.com/laravel/framework/blob/10.x/CHANGELOG.md)
- [Commits](https://github.com/laravel/framework/compare/v10.19.0...v10.20.0)

---
updated-dependencies:
- dependency-name: laravel/framework
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-28 03:06:19 +00:00
dependabot[bot]
4de0828b5d chore(deps): bump guzzlehttp/guzzle from 7.7.0 to 7.8.0
Bumps [guzzlehttp/guzzle](https://github.com/guzzle/guzzle) from 7.7.0 to 7.8.0.
- [Release notes](https://github.com/guzzle/guzzle/releases)
- [Changelog](https://github.com/guzzle/guzzle/blob/7.8/CHANGELOG.md)
- [Commits](https://github.com/guzzle/guzzle/compare/7.7.0...7.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-28 03:06:01 +00:00
James Cole
b2364d26ec Various color fixes. 2023-08-27 18:45:06 +02:00
James Cole
83d94cb792 Expand cache 2023-08-27 07:45:09 +02:00
James Cole
66cc3f48bc Mild code cleanup. 2023-08-26 18:42:18 +02:00
James Cole
63297c43b7 Possible fix for https://github.com/firefly-iii/firefly-iii/issues/7891 2023-08-26 18:40:23 +02:00
James Cole
5b0637558f Better error for invalid date 2023-08-24 05:53:17 +02:00
James Cole
e9a8e104be Change URLs to relative URLs 2023-08-24 05:47:28 +02:00
James Cole
0f524e7800 Add relative route 2023-08-23 07:05:41 +02:00
James Cole
969e0bccc9 Remove slash 2023-08-23 07:04:47 +02:00
James Cole
ba3e026927 Add base href 2023-08-23 07:02:30 +02:00
James Cole
0c6868d477 Add relative paths to JS 2023-08-23 07:00:09 +02:00
James Cole
7f70cf47ec Fix https://github.com/firefly-iii/firefly-iii/issues/7883 2023-08-22 16:08:19 +02:00
James Cole
fa4492287d Rebuild frontend 2023-08-22 08:28:52 +02:00
James Cole
60809c688e Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2023-08-22 08:25:16 +02:00
James Cole
2404f5299c New code for transaction processing and frontend 2023-08-22 08:25:06 +02:00
James Cole
21a394eaf5 Merge pull request #7873 from firefly-iii/dependabot/composer/develop/doctrine/dbal-3.6.6
chore(deps): bump doctrine/dbal from 3.6.5 to 3.6.6
2023-08-21 05:41:31 +02:00
dependabot[bot]
419d7846c9 chore(deps): bump doctrine/dbal from 3.6.5 to 3.6.6
Bumps [doctrine/dbal](https://github.com/doctrine/dbal) from 3.6.5 to 3.6.6.
- [Release notes](https://github.com/doctrine/dbal/releases)
- [Commits](https://github.com/doctrine/dbal/compare/3.6.5...3.6.6)

---
updated-dependencies:
- dependency-name: doctrine/dbal
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-21 03:38:59 +00:00
James Cole
0827accc39 Merge pull request #7872 from firefly-iii/dependabot/npm_and_yarn/develop/sass-1.66.1 2023-08-21 05:38:48 +02:00
James Cole
2e53f7d0b7 Merge pull request #7874 from firefly-iii/dependabot/composer/develop/predis/predis-2.2.1 2023-08-21 05:38:27 +02:00
James Cole
bdfcf8ec95 Merge pull request #7875 from firefly-iii/dependabot/composer/develop/laravel/framework-10.19.0 2023-08-21 05:38:18 +02:00
James Cole
6a20170e00 Merge pull request #7876 from firefly-iii/dependabot/composer/develop/phpstan/phpstan-1.10.29 2023-08-21 05:38:00 +02:00
James Cole
0c974f1ff7 Merge pull request #7877 from firefly-iii/dependabot/composer/develop/ergebnis/phpstan-rules-2.1.0 2023-08-21 05:37:48 +02:00
dependabot[bot]
9c098d45c5 chore(deps-dev): bump ergebnis/phpstan-rules from 2.0.0 to 2.1.0
Bumps [ergebnis/phpstan-rules](https://github.com/ergebnis/phpstan-rules) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/ergebnis/phpstan-rules/releases)
- [Changelog](https://github.com/ergebnis/phpstan-rules/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ergebnis/phpstan-rules/compare/2.0.0...2.1.0)

---
updated-dependencies:
- dependency-name: ergebnis/phpstan-rules
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-21 03:25:35 +00:00
dependabot[bot]
cfdf9aa8dc chore(deps-dev): bump phpstan/phpstan from 1.10.28 to 1.10.29
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.28 to 1.10.29.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.28...1.10.29)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-21 03:25:31 +00:00
dependabot[bot]
2ea74542e6 chore(deps): bump laravel/framework from 10.18.0 to 10.19.0
Bumps [laravel/framework](https://github.com/laravel/framework) from 10.18.0 to 10.19.0.
- [Release notes](https://github.com/laravel/framework/releases)
- [Changelog](https://github.com/laravel/framework/blob/10.x/CHANGELOG.md)
- [Commits](https://github.com/laravel/framework/compare/v10.18.0...v10.19.0)

---
updated-dependencies:
- dependency-name: laravel/framework
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-21 03:25:26 +00:00
dependabot[bot]
7fcaa2b5fb chore(deps): bump predis/predis from 2.2.0 to 2.2.1
Bumps [predis/predis](https://github.com/predis/predis) from 2.2.0 to 2.2.1.
- [Release notes](https://github.com/predis/predis/releases)
- [Changelog](https://github.com/predis/predis/blob/v2.x/CHANGELOG.md)
- [Commits](https://github.com/predis/predis/compare/v2.2.0...v2.2.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-21 03:25:12 +00:00
dependabot[bot]
e9e905e495 chore(deps-dev): bump sass from 1.65.1 to 1.66.1
Bumps [sass](https://github.com/sass/dart-sass) from 1.65.1 to 1.66.1.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.65.1...1.66.1)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-21 03:12:29 +00:00
James Cole
f67ff98d78 More exact search for available budgets. #7853 2023-08-15 18:37:47 +02:00
James Cole
e3c4dde4ff Add cleanup method for issue #7853 and some more debug info. 2023-08-15 17:57:02 +02:00
James Cole
9787561000 Potential solution for #7853 2023-08-15 17:19:50 +02:00
James Cole
cd041b4c75 Add debug info for #7853 2023-08-15 16:22:54 +02:00
James Cole
60ee70c926 Check for rule triggers in #7853 2023-08-15 16:17:54 +02:00
James Cole
00de78b6f1 Also support Discord. 2023-08-15 13:52:30 +02:00
James Cole
33a841b831 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2023-08-15 13:51:51 +02:00
James Cole
df66dcf102 Various UI fixes 2023-08-15 13:51:38 +02:00
James Cole
086a7a0b1e Merge pull request #7848 from firefly-iii/dependabot/npm_and_yarn/develop/laravel-vite-plugin-0.8.0 2023-08-14 06:58:21 +02:00
dependabot[bot]
ec0ba3d212 chore(deps-dev): bump laravel-vite-plugin from 0.7.8 to 0.8.0
Bumps [laravel-vite-plugin](https://github.com/laravel/vite-plugin) from 0.7.8 to 0.8.0.
- [Release notes](https://github.com/laravel/vite-plugin/releases)
- [Changelog](https://github.com/laravel/vite-plugin/blob/main/CHANGELOG.md)
- [Commits](https://github.com/laravel/vite-plugin/compare/v0.7.8...v0.8.0)

---
updated-dependencies:
- dependency-name: laravel-vite-plugin
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-14 03:58:10 +00:00
James Cole
b0ab06b7eb Add rule error reporting to all rules. 2023-08-13 15:01:12 +02:00
James Cole
965acd6d45 Finetune index. 2023-08-13 14:30:16 +02:00
James Cole
4d156870ef Add nonce to scripts 2023-08-13 07:30:19 +02:00
James Cole
499720df46 Fix math issue in summary controller. 2023-08-13 07:24:51 +02:00
James Cole
610bc108e7 Add some slack notifications and a todo to fix the rest 2023-08-12 20:57:51 +02:00
James Cole
53f1b0218c Merge tag 'v6.0.20' into develop
v6.0.20
2023-08-12 19:56:11 +02:00
237 changed files with 7343 additions and 3957 deletions

View File

@@ -79,16 +79,16 @@
},
{
"name": "composer/semver",
"version": "3.3.2",
"version": "3.4.0",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9"
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9",
"reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9",
"url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32",
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32",
"shasum": ""
},
"require": {
@@ -138,9 +138,9 @@
"versioning"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.3.2"
"source": "https://github.com/composer/semver/tree/3.4.0"
},
"funding": [
{
@@ -156,7 +156,7 @@
"type": "tidelift"
}
],
"time": "2022-04-01T19:23:25+00:00"
"time": "2023-08-31T09:50:34+00:00"
},
{
"name": "composer/xdebug-handler",
@@ -224,178 +224,23 @@
],
"time": "2022-02-25T21:32:43+00:00"
},
{
"name": "doctrine/annotations",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
"reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f",
"reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f",
"shasum": ""
},
"require": {
"doctrine/lexer": "^2 || ^3",
"ext-tokenizer": "*",
"php": "^7.2 || ^8.0",
"psr/cache": "^1 || ^2 || ^3"
},
"require-dev": {
"doctrine/cache": "^2.0",
"doctrine/coding-standard": "^10",
"phpstan/phpstan": "^1.8.0",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"symfony/cache": "^5.4 || ^6",
"vimeo/psalm": "^4.10"
},
"suggest": {
"php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Docblock Annotations Parser",
"homepage": "https://www.doctrine-project.org/projects/annotations.html",
"keywords": [
"annotations",
"docblock",
"parser"
],
"support": {
"issues": "https://github.com/doctrine/annotations/issues",
"source": "https://github.com/doctrine/annotations/tree/2.0.1"
},
"time": "2023-02-02T22:02:53+00:00"
},
{
"name": "doctrine/lexer",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/lexer.git",
"reference": "84a527db05647743d50373e0ec53a152f2cde568"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/84a527db05647743d50373e0ec53a152f2cde568",
"reference": "84a527db05647743d50373e0ec53a152f2cde568",
"shasum": ""
},
"require": {
"php": "^8.1"
},
"require-dev": {
"doctrine/coding-standard": "^10",
"phpstan/phpstan": "^1.9",
"phpunit/phpunit": "^9.5",
"psalm/plugin-phpunit": "^0.18.3",
"vimeo/psalm": "^5.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Common\\Lexer\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
"homepage": "https://www.doctrine-project.org/projects/lexer.html",
"keywords": [
"annotations",
"docblock",
"lexer",
"parser",
"php"
],
"support": {
"issues": "https://github.com/doctrine/lexer/issues",
"source": "https://github.com/doctrine/lexer/tree/3.0.0"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer",
"type": "tidelift"
}
],
"time": "2022-12-15T16:57:16+00:00"
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.22.0",
"version": "v3.25.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "92b019f6c8d79aa26349d0db7671d37440dc0ff3"
"reference": "9025b7d2b6e1d90a63d0ac0905018ce5d03ec88d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/92b019f6c8d79aa26349d0db7671d37440dc0ff3",
"reference": "92b019f6c8d79aa26349d0db7671d37440dc0ff3",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/9025b7d2b6e1d90a63d0ac0905018ce5d03ec88d",
"reference": "9025b7d2b6e1d90a63d0ac0905018ce5d03ec88d",
"shasum": ""
},
"require": {
"composer/semver": "^3.3",
"composer/xdebug-handler": "^3.0.3",
"doctrine/annotations": "^2",
"doctrine/lexer": "^2 || ^3",
"ext-json": "*",
"ext-tokenizer": "*",
"php": "^7.4 || ^8.0",
@@ -464,7 +309,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.22.0"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.25.0"
},
"funding": [
{
@@ -472,56 +317,7 @@
"type": "github"
}
],
"time": "2023-07-16T23:08:06+00:00"
},
{
"name": "psr/cache",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/cache.git",
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
"reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Cache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for caching libraries",
"keywords": [
"cache",
"psr",
"psr-6"
],
"support": {
"source": "https://github.com/php-fig/cache/tree/3.0.0"
},
"time": "2021-02-03T23:26:27+00:00"
"time": "2023-08-31T21:27:18+00:00"
},
{
"name": "psr/container",
@@ -745,16 +541,16 @@
},
{
"name": "symfony/console",
"version": "v6.3.2",
"version": "v6.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898"
"reference": "eca495f2ee845130855ddf1cf18460c38966c8b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/aa5d64ad3f63f2e48964fc81ee45cb318a723898",
"reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898",
"url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6",
"reference": "eca495f2ee845130855ddf1cf18460c38966c8b6",
"shasum": ""
},
"require": {
@@ -815,7 +611,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v6.3.2"
"source": "https://github.com/symfony/console/tree/v6.3.4"
},
"funding": [
{
@@ -831,7 +627,7 @@
"type": "tidelift"
}
],
"time": "2023-07-19T20:17:28+00:00"
"time": "2023-08-16T10:10:12+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -1252,16 +1048,16 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"shasum": ""
},
"require": {
@@ -1276,7 +1072,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -1314,7 +1110,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
},
"funding": [
{
@@ -1330,20 +1126,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
"reference": "875e90aeea2777b6f135677f618529449334a612"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612",
"reference": "875e90aeea2777b6f135677f618529449334a612",
"shasum": ""
},
"require": {
@@ -1355,7 +1151,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -1395,7 +1191,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0"
},
"funding": [
{
@@ -1411,20 +1207,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"shasum": ""
},
"require": {
@@ -1436,7 +1232,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -1479,7 +1275,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0"
},
"funding": [
{
@@ -1495,20 +1291,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
"reference": "42292d99c55abe617799667f454222c54c60e229"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
"reference": "42292d99c55abe617799667f454222c54c60e229",
"shasum": ""
},
"require": {
@@ -1523,7 +1319,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -1562,7 +1358,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
},
"funding": [
{
@@ -1578,20 +1374,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-07-28T09:04:16+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"shasum": ""
},
"require": {
@@ -1600,7 +1396,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -1645,7 +1441,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0"
},
"funding": [
{
@@ -1661,20 +1457,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-php81",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a"
"reference": "7581cd600fa9fd681b797d00b02f068e2f13263b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a",
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b",
"reference": "7581cd600fa9fd681b797d00b02f068e2f13263b",
"shasum": ""
},
"require": {
@@ -1683,7 +1479,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -1724,7 +1520,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0"
},
"funding": [
{
@@ -1740,20 +1536,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/process",
"version": "v6.3.2",
"version": "v6.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d"
"reference": "0b5c29118f2e980d455d2e34a5659f4579847c54"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d",
"reference": "c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d",
"url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54",
"reference": "0b5c29118f2e980d455d2e34a5659f4579847c54",
"shasum": ""
},
"require": {
@@ -1785,7 +1581,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v6.3.2"
"source": "https://github.com/symfony/process/tree/v6.3.4"
},
"funding": [
{
@@ -1801,7 +1597,7 @@
"type": "tidelift"
}
],
"time": "2023-07-12T16:00:22+00:00"
"time": "2023-08-07T10:39:22+00:00"
},
{
"name": "symfony/service-contracts",

View File

@@ -45,12 +45,6 @@ TRUSTED_PROXIES=
# Default setting 'stack' will log to 'daily' and to 'stdout' at the same time.
LOG_CHANNEL=stack
#
# Used when logging to papertrail:
#
PAPERTRAIL_HOST=
PAPERTRAIL_PORT=
# Log level. You can set this from least severe to most severe:
# debug, info, notice, warning, error, critical, alert, emergency
# If you set it to debug your logs will grow large, and fast. If you set it to emergency probably
@@ -58,8 +52,30 @@ PAPERTRAIL_PORT=
APP_LOG_LEVEL=notice
# Audit log level.
# Set this to "emergency" if you dont want to store audit logs, leave on info otherwise.
AUDIT_LOG_LEVEL=info
# The audit log is used to log notable Firefly III events on a separate channel.
# These log entries may contain sensitive financial information.
# The audit log is disabled by default.
#
# To enable it, set AUDIT_LOG_LEVEL to "info"
# To disable it, set AUDIT_LOG_LEVEL to "emergency"
AUDIT_LOG_LEVEL=emergency
#
# If you want, you can redirect the audit logs to another channel.
# Set 'audit_stdout', 'audit_syslog', 'audit_errorlog' to log to the system itself.
# Use audit_daily to log to a rotating file.
# Use audit_papertrail to log to papertrail.
#
# If you do this, the audit logs may be mixed with normal logs because the settings for these channels
# are often the same as the settings for the normal logs.
AUDIT_LOG_CHANNEL=
#
# Used when logging to papertrail:
# Also used when audit logs log to papertrail:
#
PAPERTRAIL_HOST=
PAPERTRAIL_PORT=
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
# For other database types, please see the FAQ: https://docs.firefly-iii.org/firefly-iii/faq/self-hosted/#i-want-to-use-sqlite

View File

@@ -102,6 +102,7 @@ abstract class Controller extends BaseController
} catch (BadRequestException $e) {
Log::error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $field));
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
$value = null;
}
$obj = null;
@@ -130,6 +131,7 @@ abstract class Controller extends BaseController
} catch (BadRequestException $e) {
Log::error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $integer));
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
$value = null;
}
if (null !== $value) {
@@ -154,6 +156,7 @@ abstract class Controller extends BaseController
} catch (BadRequestException $e) {
Log::error('Request field "sort" contains a non-scalar value. Value set to NULL.');
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
$param = '';
}
if ('' === $param) {

View File

@@ -99,6 +99,7 @@ class Controller extends BaseController
} catch (BadRequestException $e) {
Log::error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $field));
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
}
if (null !== $date) {
try {

View File

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

View File

@@ -105,10 +105,6 @@ class BasicController extends Controller
$end = $this->parameters->get('end');
// balance information:
$balanceData = [];
$billData = [];
$spentData = [];
$netWorthData = [];
$balanceData = $this->getBalanceInformation($start, $end);
$billData = $this->getBillInformation($start, $end);
$spentData = $this->getLeftToSpendInfo($start, $end);
@@ -127,9 +123,15 @@ class BasicController extends Controller
private function getBalanceInformation(Carbon $start, Carbon $end): array
{
// prep some arrays:
$incomes = [];
$expenses = [];
$sums = [];
$incomes = [
'native' => '0',
];
$expenses = [
'native' => '0',
];
$sums = [
'native' => '0',
];
$return = [];
$currencies = [];
$converter = new ExchangeRateConverter();
@@ -354,6 +356,7 @@ class BasicController extends Controller
*/
private function getLeftToSpendInfo(Carbon $start, Carbon $end): array
{
app('log')->debug('Now in getLeftToSpendInfo');
$return = [];
$today = today(config('app.timezone'));
$available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end);
@@ -367,7 +370,7 @@ class BasicController extends Controller
$nativeLeft = [
'key' => 'left-to-spend-in-native',
'value' => '0',
'currency_id' => (int)$default->id,
'currency_id' => (string)$default->id,
'currency_code' => $default->code,
'currency_symbol' => $default->symbol,
'currency_decimal_places' => (int)$default->decimal_places,
@@ -375,7 +378,7 @@ class BasicController extends Controller
$nativePerDay = [
'key' => 'left-per-day-to-spend-in-native',
'value' => '0',
'currency_id' => (int)$default->id,
'currency_id' => (string)$default->id,
'currency_code' => $default->code,
'currency_symbol' => $default->symbol,
'currency_decimal_places' => (int)$default->decimal_places,
@@ -386,17 +389,20 @@ class BasicController extends Controller
* @var array $row
*/
foreach ($spent as $currencyId => $row) {
app('log')->debug(sprintf('Processing spent array in currency #%d', $currencyId));
$currencyId = (int)$currencyId;
$spent = '0';
$spentNative = '0';
// get the sum from the array of transactions (double loop but who cares)
/** @var array $budget */
foreach ($row['budgets'] as $budget) {
app('log')->debug(sprintf('Processing expenses in budget "%s".', $budget['name']));
/** @var array $journal */
foreach ($budget['transaction_journals'] as $journal) {
$journalCurrencyId = $journal['currency_id'];
$currency = $currencies[$journalCurrencyId] ?? $this->currencyRepos->find($journalCurrencyId);
$currencies[$currencyId] = $currency;
$amount = bcmul($journal['amount'], '-1');
$amount = app('steam')->negative($journal['amount']);
$amountNative = $converter->convert($default, $currency, $start, $amount);
if ((int)$journal['foreign_currency_id'] === (int)$default->id) {
$amountNative = $journal['foreign_amount'];
@@ -404,15 +410,18 @@ class BasicController extends Controller
$spent = bcadd($spent, $amount);
$spentNative = bcadd($spentNative, $amountNative);
}
app('log')->debug(sprintf('Total spent in budget "%s" is %s', $budget['name'], $spent));
}
// either an amount was budgeted or 0 is available.
$currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId);
$currencies[$currencyId] = $currency;
$amount = $available[$currencyId]['amount'] ?? '0';
$amountNative = $converter->convert($default, $currency, $start, $amount);
$amountNative = $available[$currencyId]['native_amount'] ?? '0';
$left = bcadd($amount, $spent);
$leftNative = bcadd($amountNative, $spentNative);
app('log')->debug(sprintf('Available amount is %s', $amount));
app('log')->debug(sprintf('Amount left is %s', $left));
// how much left per day?
$days = $today->diffInDays($end) + 1;
@@ -429,10 +438,10 @@ class BasicController extends Controller
$return[] = [
'key' => sprintf('left-to-spend-in-%s', $row['currency_code']),
'value' => $left,
'currency_id' => $row['currency_id'],
'currency_id' => (string)$row['currency_id'],
'currency_code' => $row['currency_code'],
'currency_symbol' => $row['currency_symbol'],
'currency_decimal_places' => $row['currency_decimal_places'],
'currency_decimal_places' => (int)$row['currency_decimal_places'],
];
// left (native)
$nativeLeft['value'] = $leftNative;
@@ -441,10 +450,10 @@ class BasicController extends Controller
$return[] = [
'key' => sprintf('left-per-day-to-spend-in-%s', $row['currency_code']),
'value' => $perDay,
'currency_id' => $row['currency_id'],
'currency_id' => (string)$row['currency_id'],
'currency_code' => $row['currency_code'],
'currency_symbol' => $row['currency_symbol'],
'currency_decimal_places' => $row['currency_decimal_places'],
'currency_decimal_places' => (int)$row['currency_decimal_places'],
];
// left per day (native)

View File

@@ -42,7 +42,7 @@ class BalanceChartRequest extends FormRequest
{
return [
'accounts' => $this->getAccountList(),
'period' => $this->string('period'),
'period' => $this->convertString('period'),
];
}

View File

@@ -34,6 +34,7 @@ use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Models\RuleTrigger;
use Illuminate\Console\Command;
use ValueError;
/**
* Class ReportSkeleton
@@ -247,7 +248,16 @@ class CorrectAmounts extends Command
/** @var RuleTrigger $item */
foreach ($set as $item) {
// basic check:
if (-1 === bccomp((string)$item->trigger_value, '0')) {
$check = 0;
try {
$check = bccomp((string)$item->trigger_value, '0');
} catch (ValueError $e) {
$this->friendlyError(sprintf('Rule #%d contained invalid %s-trigger "%s". The trigger has been removed, and the rule is disabled.', $item->rule_id, $item->trigger_type, $item->trigger_value));
$item->rule->active = false;
$item->rule->save();
$item->forceDelete();
}
if (-1 === $check) {
$fixed++;
$item->trigger_value = app('steam')->positive((string)$item->trigger_value);
$item->save();

View File

@@ -82,6 +82,7 @@ class DeleteEmptyJournals extends Command
TransactionJournal::find((int)$row->transaction_journal_id)->delete();
} catch (QueryException $e) {
Log::info(sprintf('Could not delete journal: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
}
@@ -113,6 +114,7 @@ class DeleteEmptyJournals extends Command
TransactionJournal::find($entry->id)->delete();
} catch (QueryException $e) {
Log::info(sprintf('Could not delete entry: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
}

View File

@@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
/*
* RuleActionFailedOnArray.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/>.
*/
namespace FireflyIII\Events\Model\Rule;
use FireflyIII\Models\RuleAction;
use Illuminate\Queue\SerializesModels;
/**
* Class RuleActionFailedOnArray
*/
class RuleActionFailedOnArray
{
use SerializesModels;
public string $error;
public array $journal;
public RuleAction $ruleAction;
/**
* @param RuleAction $ruleAction
* @param array $journal
* @param string $error
*/
public function __construct(RuleAction $ruleAction, array $journal, string $error)
{
app('log')->debug('Created new RuleActionFailedOnArray');
$this->ruleAction = $ruleAction;
$this->journal = $journal;
$this->error = $error;
}
}

View File

@@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
/*
* RuleActionFailedOnArray.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/>.
*/
namespace FireflyIII\Events\Model\Rule;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Queue\SerializesModels;
/**
* Class RuleActionFailedOnObject
*/
class RuleActionFailedOnObject
{
use SerializesModels;
public string $error;
public TransactionJournal $journal;
public RuleAction $ruleAction;
/**
* @param RuleAction $ruleAction
* @param TransactionJournal $journal
* @param string $error
*/
public function __construct(RuleAction $ruleAction, TransactionJournal $journal, string $error)
{
app('log')->debug('Created new RuleActionFailedOnObject');
$this->ruleAction = $ruleAction;
$this->journal = $journal;
$this->error = $error;
}
}

View File

@@ -218,6 +218,7 @@ class AccountFactory
}
// create account!
$account = Account::create($databaseData);
Log::channel('audit')->info(sprintf('Account #%d ("%s") has been created.', $account->id, $account->name));
// update meta data:
$data = $this->cleanMetaDataArray($account, $data);
@@ -228,6 +229,7 @@ class AccountFactory
$this->storeOpeningBalance($account, $data);
} catch (FireflyException $e) {
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
}
// create credit liability data (only liabilities)
@@ -235,6 +237,7 @@ class AccountFactory
$this->storeCreditLiability($account, $data);
} catch (FireflyException $e) {
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
}
// create notes

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Factory;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountMeta;
use Illuminate\Support\Facades\Log;
/**
* Class AccountMetaFactory

View File

@@ -77,6 +77,7 @@ class CategoryFactory
);
} catch (QueryException $e) {
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
throw new FireflyException('400003: Could not store new category.', 0, $e);
}
}

View File

@@ -130,6 +130,7 @@ class RecurrenceFactory
$this->createTransactions($recurrence, $data['transactions'] ?? []);
} catch (FireflyException $e) {
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
$recurrence->forceDelete();
$message = sprintf('Could not create recurring transaction: %s', $e->getMessage());
$this->errors->add('store', $message);

View File

@@ -69,6 +69,7 @@ class TransactionCurrencyFactory
} catch (QueryException $e) {
$result = null;
Log::error(sprintf('Could not create new currency: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
throw new FireflyException('400004: Could not store new currency.', 0, $e);
}

View File

@@ -110,7 +110,7 @@ class TransactionFactory
Log::error(sprintf('Could not create transaction: %s', $e->getMessage()), $data);
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
throw new FireflyException('Query exception when creating transaction.', 0, $e);
throw new FireflyException(sprintf('Query exception when creating transaction: %s', $e->getMessage()), 0, $e);
}
if (null === $result) {
throw new FireflyException('Transaction is NULL.');

View File

@@ -75,6 +75,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render reports.account.report: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = sprintf('Could not render report view: %s', $e->getMessage());
throw new FireflyException($result, 0, $e);
}

View File

@@ -77,6 +77,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render reports.category.month: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = sprintf('Could not render report view: %s', $e->getMessage());
throw new FireflyException($result, 0, $e);
}

View File

@@ -59,6 +59,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
return view('reports.default.month', compact('accountIds', 'reportType'))->with('start', $this->start)->with('end', $this->end)->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render reports.default.month: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = 'Could not render report view.';
throw new FireflyException($result, 0, $e);
}

View File

@@ -63,6 +63,7 @@ class MultiYearReportGenerator implements ReportGeneratorInterface
)->with('start', $this->start)->with('end', $this->end)->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render reports.default.multi-year: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = sprintf('Could not render report view: %s', $e->getMessage());
throw new FireflyException($result, 0, $e);
}

View File

@@ -63,6 +63,7 @@ class YearReportGenerator implements ReportGeneratorInterface
)->with('start', $this->start)->with('end', $this->end)->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render reports.account.report: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = 'Could not render report view.';
throw new FireflyException($result, 0, $e);
}

View File

@@ -71,6 +71,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
)->with('start', $this->start)->with('end', $this->end)->with('tags', $this->tags)->with('accounts', $this->accounts)->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render reports.tag.month: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = sprintf('Could not render report view: %s', $e->getMessage());
throw new FireflyException($result, 0, $e);
}

View File

@@ -174,6 +174,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
Log::error(
sprintf('The transformer could not include the requested transaction group for webhook #%d: %s', $webhook->id, $e->getMessage())
);
Log::error($e->getTraceAsString());
return;
}

View File

@@ -166,7 +166,7 @@ class BudgetLimitHandler
$availableBudget->end_date->format('Y-m-d')
)
);
// have to recalc everything just in case.
// have to recalculate everything just in case.
$set = $repository->getAllBudgetLimitsByCurrency($availableBudget->transactionCurrency, $availableBudget->start_date, $availableBudget->end_date);
Log::debug(sprintf('Found %d interesting budget limit(s).', $set->count()));
/** @var BudgetLimit $budgetLimit */
@@ -186,15 +186,18 @@ class BudgetLimitHandler
precision : Precision::DAY(),
boundaries: Boundaries::EXCLUDE_NONE()
);
// if both equal eachother, amount from this BL must be added to the AB
// if both equal each other, amount from this BL must be added to the AB
if ($limitPeriod->equals($abPeriod)) {
app('log')->debug('This budget limit is equal to the available budget period.');
$newAmount = bcadd($newAmount, $budgetLimit->amount);
}
// if budget limit period inside AB period, can be added in full.
// if budget limit period is inside AB period, it can be added in full.
if (!$limitPeriod->equals($abPeriod) && $abPeriod->contains($limitPeriod)) {
app('log')->debug('This budget limit is smaller than the available budget period.');
$newAmount = bcadd($newAmount, $budgetLimit->amount);
}
if (!$limitPeriod->equals($abPeriod) && $abPeriod->overlapsWith($limitPeriod)) {
if (!$limitPeriod->equals($abPeriod) && !$abPeriod->contains($limitPeriod) && $abPeriod->overlapsWith($limitPeriod)) {
app('log')->debug('This budget limit is something else entirely!');
$overlap = $abPeriod->overlap($limitPeriod);
if (null !== $overlap) {
$length = $overlap->length();
@@ -209,7 +212,7 @@ class BudgetLimitHandler
return;
}
Log::debug(sprintf('Concluded new amount for this AB must be %s', $newAmount));
$availableBudget->amount = $newAmount;
$availableBudget->amount = app('steam')->bcround($newAmount, $availableBudget->transactionCurrency->decimal_places);
$availableBudget->save();
}

View File

@@ -0,0 +1,95 @@
<?php
declare(strict_types=1);
/*
* RuleHandler.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/>.
*/
namespace FireflyIII\Handlers\Events\Model;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject;
use FireflyIII\Notifications\User\RuleActionFailed;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Support\Facades\Notification;
/**
* Class RuleHandler
*/
class RuleHandler
{
/**
* @param RuleActionFailedOnArray $event
*
* @return void
*/
public function ruleActionFailedOnArray(RuleActionFailedOnArray $event): void
{
$ruleAction = $event->ruleAction;
$rule = $ruleAction->rule;
$preference = Preferences::getForUser($rule->user, 'notification_rule_action_failures', true)->data;
if (false === $preference) {
return;
}
app('log')->debug('Now in ruleActionFailedOnArray');
$journal = $event->journal;
$error = $event->error;
$user = $ruleAction->rule->user;
$mainMessage = trans('rules.main_message', ['rule' => $rule->title, 'action' => $ruleAction->action_type, 'group' => $journal['transaction_group_id'], 'error' => $error]);
$groupTitle = $journal['description'] ?? '';
$groupLink = route('transactions.show', [$journal['transaction_group_id']]);
$ruleTitle = $rule->title;
$ruleLink = route('rules.edit', [$rule->id]);
$params = [$mainMessage, $groupTitle, $groupLink, $ruleTitle, $ruleLink];
Notification::send($user, new RuleActionFailed($params));
}
/**
* @param RuleActionFailedOnObject $event
*
* @return void
*/
public function ruleActionFailedOnObject(RuleActionFailedOnObject $event): void
{
$ruleAction = $event->ruleAction;
$rule = $ruleAction->rule;
$preference = Preferences::getForUser($rule->user, 'notification_rule_action_failures', true)->data;
if (false === $preference) {
return;
}
app('log')->debug('Now in ruleActionFailedOnObject');
$journal = $event->journal;
$error = $event->error;
$user = $ruleAction->rule->user;
$mainMessage = trans('rules.main_message', ['rule' => $rule->title, 'action' => $ruleAction->action_type, 'group' => $journal->transaction_group_id, 'error' => $error]);
$groupTitle = $journal->description ?? '';
$groupLink = route('transactions.show', [$journal->transaction_group_id]);
$ruleTitle = $rule->title;
$ruleLink = route('rules.edit', [$rule->id]);
$params = [$mainMessage, $groupTitle, $groupLink, $ruleTitle, $ruleLink];
Notification::send($user, new RuleActionFailed($params));
}
}

View File

@@ -275,6 +275,7 @@ class UserEventHandler
Mail::to($newEmail)->send(new ConfirmEmailChangeMail($newEmail, $oldEmail, $url));
} catch (Exception $e) { // intentional generic exception
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
throw new FireflyException($e->getMessage(), 0, $e);
}
}
@@ -299,6 +300,7 @@ class UserEventHandler
Mail::to($oldEmail)->send(new UndoEmailChangeMail($newEmail, $oldEmail, $url));
} catch (Exception $e) { // intentional generic exception
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
throw new FireflyException($e->getMessage(), 0, $e);
}
}
@@ -342,6 +344,7 @@ class UserEventHandler
Mail::to($invitee)->send(new InvitationMail($invitee, $admin, $url));
} catch (Exception $e) { // intentional generic exception
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
throw new FireflyException($e->getMessage(), 0, $e);
}
}

View File

@@ -57,7 +57,7 @@ class VersionCheckEventHandler
$permission = app('fireflyconfig')->get('permission_update_check', -1);
$value = (int)$permission->data;
if (1 !== $value) {
Log::info('Update check is not enabled.');
Log::debug('Update check is not enabled.');
$this->warnToCheckForUpdates($event);
return;

View File

@@ -871,7 +871,7 @@ class GroupCollector implements GroupCollectorInterface
public function setLimit(int $limit): GroupCollectorInterface
{
$this->limit = $limit;
app('log')->debug(sprintf('GroupCollector: The limit is now %d', $limit));
//app('log')->debug(sprintf('GroupCollector: The limit is now %d', $limit));
return $this;
}
@@ -976,7 +976,7 @@ class GroupCollector implements GroupCollectorInterface
{
$page = 0 === $page ? 1 : $page;
$this->page = $page;
app('log')->debug(sprintf('GroupCollector: page is now %d', $page));
//app('log')->debug(sprintf('GroupCollector: page is now %d', $page));
return $this;
}

View File

@@ -27,6 +27,7 @@ use FireflyIII\Events\AdminRequestedTestMessage;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Middleware\IsDemoUser;
use FireflyIII\Support\Facades\FireflyConfig;
use FireflyIII\Support\Notifications\UrlValidator;
use FireflyIII\User;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
@@ -99,7 +100,7 @@ class HomeController extends Controller
if ('' === $url) {
FireflyConfig::delete('slack_webhook_url');
}
if (str_starts_with($url, 'https://hooks.slack.com/services/')) {
if (UrlValidator::isValidWebhookURL($url)) {
FireflyConfig::set('slack_webhook_url', $url);
}

View File

@@ -146,7 +146,7 @@ class IndexController extends Controller
private function getSums(array $bills): array
{
$sums = [];
$range = app('navigation')->getViewRange(false);
$range = app('navigation')->getViewRange(true);
/** @var array $group */
foreach ($bills as $groupOrder => $group) {
@@ -177,7 +177,6 @@ class IndexController extends Controller
$sums[$groupOrder][$currencyId]['per_period'] = bcadd($sums[$groupOrder][$currencyId]['per_period'], $this->amountPerPeriod($bill, $range));
}
}
return $sums;
}

View File

@@ -101,6 +101,7 @@ class IndexController extends Controller
*/
public function index(Request $request, Carbon $start = null, Carbon $end = null)
{
$this->abRepository->cleanup();
Log::debug(sprintf('Start of IndexController::index("%s", "%s")', $start?->format('Y-m-d'), $end?->format('Y-m-d')));
// collect some basic vars:
@@ -337,6 +338,7 @@ class IndexController extends Controller
*/
public function reorder(Request $request, BudgetRepositoryInterface $repository): JsonResponse
{
$this->abRepository->cleanup();
$budgetIds = $request->get('budgetIds');
foreach ($budgetIds as $index => $budgetId) {

View File

@@ -138,6 +138,9 @@ class HomeController extends Controller
$accounts = $repository->getAccountsById($frontPage->data);
$today = today(config('app.timezone'));
// sort frontpage accounts by order
$accounts = $accounts->sortBy('order');
Log::debug('Frontpage accounts are ', $frontPage->data);
/** @var BillRepositoryInterface $billRepository */

View File

@@ -55,10 +55,12 @@ class BoxController extends Controller
*/
public function available(): JsonResponse
{
app('log')->debug('Now in available()');
/** @var OperationsRepositoryInterface $opsRepository */
$opsRepository = app(OperationsRepositoryInterface::class);
/** @var AvailableBudgetRepositoryInterface $abRepository */
$abRepository = app(AvailableBudgetRepositoryInterface::class);
$abRepository->cleanup();
/** @var Carbon $start */
$start = session('start', today(config('app.timezone'))->startOfMonth());
/** @var Carbon $end */
@@ -73,40 +75,57 @@ class BoxController extends Controller
$cache->addProperty($today);
$cache->addProperty('box-available');
if ($cache->has()) {
return response()->json($cache->get());
//return response()->json($cache->get());
}
$leftPerDayAmount = '0';
$leftToSpendAmount = '0';
$currency = app('amount')->getDefaultCurrency();
$availableBudgets = $abRepository->getAvailableBudgetsByDate($start, $end);
$currency = app('amount')->getDefaultCurrency();
app('log')->debug(sprintf('Default currency is %s', $currency->code));
$availableBudgets = $abRepository->getAvailableBudgetsByExactDate($start, $end);
app('log')->debug(sprintf('Found %d available budget(s)', $availableBudgets->count()));
$availableBudgets = $availableBudgets->filter(
static function (AvailableBudget $availableBudget) use ($currency) {
if ($availableBudget->transaction_currency_id === $currency->id) {
app('log')->debug(sprintf(
'Will include AB #%d: from %s-%s amount %s',
$availableBudget->id,
$availableBudget->start_date->format('Y-m-d'),
$availableBudget->end_date->format('Y-m-d'),
$availableBudget->amount
));
return $availableBudget;
}
return null;
}
);
app('log')->debug(sprintf('Filtered back to %d available budgets', $availableBudgets->count()));
// spent in this period, in budgets, for default currency.
// also calculate spent per day.
$spent = $opsRepository->sumExpenses($start, $end, null, null, $currency);
$spentAmount = $spent[(int)$currency->id]['sum'] ?? '0';
app('log')->debug(sprintf('Spent for default currency for all budgets in this period: %s', $spentAmount));
$days = $today->between($start, $end) ? $today->diffInDays($start) + 1 : $end->diffInDays($start) + 1;
$days = $today->between($start, $end) ? $today->diffInDays($start) + 1 : $end->diffInDays($start) + 1;
app('log')->debug(sprintf('Number of days left: %d', $days));
$spentPerDay = bcdiv($spentAmount, (string)$days);
app('log')->debug(sprintf('Available to spend per day: %s', $spentPerDay));
if ($availableBudgets->count() > 0) {
$display = 0; // assume user overspent
$boxTitle = (string)trans('firefly.overspent');
$totalAvailableSum = (string)$availableBudgets->sum('amount');
app('log')->debug(sprintf('Total available sum is %s', $totalAvailableSum));
// calculate with available budget.
$leftToSpendAmount = bcadd($totalAvailableSum, $spentAmount);
app('log')->debug(sprintf('So left to spend is %s', $leftToSpendAmount));
if (1 === bccomp($leftToSpendAmount, '0')) {
app('log')->debug(sprintf('Left to spend is positive!'));
$boxTitle = (string)trans('firefly.left_to_spend');
$days = $today->diffInDays($end) + 1;
$display = 1; // not overspent
$leftPerDayAmount = bcdiv($leftToSpendAmount, (string)$days);
app('log')->debug(sprintf('Left to spend per day is %s', $leftPerDayAmount));
}
}
@@ -118,9 +137,10 @@ class BoxController extends Controller
'left_per_day' => app('amount')->formatAnything($currency, $leftPerDayAmount, false),
'title' => $boxTitle,
];
app('log')->debug('Final output', $return);
$cache->store($return);
app('log')->debug('Now done with available()');
return response()->json($return);
}

View File

@@ -75,6 +75,7 @@ class FrontpageController extends Controller
$html = view('json.piggy-banks', compact('info'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render json.piggy-banks: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$html = 'Could not render view.';
throw new FireflyException($html, 0, $e);
}

View File

@@ -157,6 +157,7 @@ class ReconcileController extends Controller
)->render();
} catch (Throwable $e) {
Log::debug(sprintf('View error: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$view = sprintf('Could not render accounts.reconcile.overview: %s', $e->getMessage());
throw new FireflyException($view, 0, $e);
}
@@ -258,6 +259,7 @@ class ReconcileController extends Controller
)->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$html = sprintf('Could not render accounts.reconcile.transactions: %s', $e->getMessage());
throw new FireflyException($html, 0, $e);
}

View File

@@ -55,6 +55,7 @@ class RuleController extends Controller
$view = view('rules.partials.action', compact('actions', 'count'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render rules.partials.action: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$view = 'Could not render view.';
throw new FireflyException($view, 0, $e);
}
@@ -86,6 +87,7 @@ class RuleController extends Controller
$view = view('rules.partials.trigger', compact('triggers', 'count'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render rules.partials.trigger: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$view = 'Could not render view.';
throw new FireflyException($view, 0, $e);
}

View File

@@ -28,6 +28,7 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Preference;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Notifications\UrlValidator;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
@@ -207,7 +208,7 @@ class PreferencesController extends Controller
// slack URL:
if (!auth()->user()->hasRole('demo')) {
$url = (string)$request->get('slackUrl');
if (str_starts_with($url, 'https://hooks.slack.com/services/')) {
if (UrlValidator::isValidWebhookURL($url)) {
app('preferences')->set('slack_webhook_url', $url);
}
if ('' === $url) {

View File

@@ -65,7 +65,8 @@ class AccountController extends Controller
try {
$result = view('reports.partials.accounts', compact('accountReport'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.accounts: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.accounts: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = 'Could not render view.';
throw new FireflyException($result, 0, $e);
}

View File

@@ -141,7 +141,8 @@ class BalanceController extends Controller
try {
$result = view('reports.partials.balance', compact('report'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.balance: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.balance: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = 'Could not render view.';
throw new FireflyException($result, 0, $e);
}

View File

@@ -61,7 +61,8 @@ class BillController extends Controller
try {
$result = view('reports.partials.bills', compact('report'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.budgets: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.budgets: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = 'Could not render view.';
throw new FireflyException($result, 0, $e);
}

View File

@@ -195,8 +195,9 @@ class BudgetController extends Controller
try {
$result = view('reports.budget.partials.avg-expenses', compact('result'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
$result = sprintf('Could not render view: %s', $e->getMessage());
Log::error($e->getTraceAsString());
throw new FireflyException($result, 0, $e);
}
@@ -353,7 +354,8 @@ class BudgetController extends Controller
try {
$result = view('reports.partials.budget-period', compact('report', 'periods'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = 'Could not render view.';
throw new FireflyException($result, 0, $e);
}
@@ -406,7 +408,7 @@ class BudgetController extends Controller
try {
$result = view('reports.budget.partials.top-expenses', compact('result'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
$result = sprintf('Could not render view: %s', $e->getMessage());
throw new FireflyException($result, 0, $e);
}

View File

@@ -315,7 +315,7 @@ class CategoryController extends Controller
try {
$result = view('reports.category.partials.avg-expenses', compact('result'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
$result = sprintf('Could not render view: %s', $e->getMessage());
throw new FireflyException($result, 0, $e);
}
@@ -368,7 +368,7 @@ class CategoryController extends Controller
try {
$result = view('reports.category.partials.avg-income', compact('result'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
$result = sprintf('Could not render view: %s', $e->getMessage());
throw new FireflyException($result, 0, $e);
}

View File

@@ -115,7 +115,7 @@ class DoubleController extends Controller
try {
$result = view('reports.double.partials.avg-expenses', compact('result'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
$result = sprintf('Could not render view: %s', $e->getMessage());
throw new FireflyException($e->getMessage(), 0, $e);
}
@@ -168,7 +168,7 @@ class DoubleController extends Controller
try {
$result = view('reports.double.partials.avg-income', compact('result'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
$result = sprintf('Could not render view: %s', $e->getMessage());
throw new FireflyException($e->getMessage(), 0, $e);
}
@@ -463,7 +463,7 @@ class DoubleController extends Controller
try {
$result = view('reports.double.partials.top-expenses', compact('result'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
$result = sprintf('Could not render view: %s', $e->getMessage());
throw new FireflyException($e->getMessage(), 0, $e);
}
@@ -514,7 +514,7 @@ class DoubleController extends Controller
try {
$result = view('reports.double.partials.top-income', compact('result'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage()));
$result = sprintf('Could not render view: %s', $e->getMessage());
throw new FireflyException($e->getMessage(), 0, $e);
}

View File

@@ -85,7 +85,8 @@ class OperationsController extends Controller
try {
$result = view('reports.partials.income-expenses', compact('report', 'type'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.income-expense: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.income-expense: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = 'Could not render view.';
throw new FireflyException($result, 0, $e);
}
@@ -121,7 +122,8 @@ class OperationsController extends Controller
try {
$result = view('reports.partials.income-expenses', compact('report', 'type'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.income-expenses: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.income-expenses: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = 'Could not render view.';
throw new FireflyException($result, 0, $e);
}
@@ -177,7 +179,8 @@ class OperationsController extends Controller
try {
$result = view('reports.partials.operations', compact('sums'))->render();
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.operations: %s', $e->getMessage()));
Log::error(sprintf('Could not render reports.partials.operations: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = 'Could not render view.';
throw new FireflyException($result, 0, $e);
}

View File

@@ -128,6 +128,7 @@ class SearchController extends Controller
$html = view('search.search', compact('groups', 'hasPages', 'searchTime'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Cannot render search.search: %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$html = 'Could not render view.';
throw new FireflyException($html, 0, $e);
}

View File

@@ -158,6 +158,7 @@ class ReportFormRequest extends FormRequest
} catch (Exception $e) { // intentional generic exception
$error = sprintf('"%s" is not a valid date range: %s', $range, $e->getMessage());
Log::error($error);
Log::error($e->getTraceAsString());
throw new FireflyException($error, 0, $e);
}
return $date;
@@ -192,6 +193,7 @@ class ReportFormRequest extends FormRequest
} catch (Exception $e) { // intentional generic exception
$error = sprintf('"%s" is not a valid date range: %s', $range, $e->getMessage());
Log::error($error);
Log::error($e->getTraceAsString());
throw new FireflyException($error, 0, $e);
}
return $date;
@@ -220,19 +222,18 @@ class ReportFormRequest extends FormRequest
}
if (!is_array($set)) {
Log::error(sprintf('Set is not an array! "%s"', $set));
return $collection;
}
if (is_array($set)) {
foreach ($set as $tagTag) {
Log::debug(sprintf('Now searching for "%s"', $tagTag));
$tag = $repository->findByTag($tagTag);
if (null !== $tag) {
$collection->push($tag);
continue;
}
$tag = $repository->find((int)$tagTag);
if (null !== $tag) {
$collection->push($tag);
}
foreach ($set as $tagTag) {
Log::debug(sprintf('Now searching for "%s"', $tagTag));
$tag = $repository->findByTag($tagTag);
if (null !== $tag) {
$collection->push($tag);
continue;
}
$tag = $repository->find((int)$tagTag);
if (null !== $tag) {
$collection->push($tag);
}
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Notifications\Admin;
use FireflyIII\Support\Notifications\UrlValidator;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
@@ -99,9 +100,9 @@ class TestNotification extends Notification
public function via($notifiable)
{
/** @var User|null $user */
$user = auth()->user();
$user = auth()->user();
$slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data;
if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) {
if (UrlValidator::isValidWebhookURL($slackUrl)) {
return ['mail', 'slack'];
}
return ['mail'];

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Notifications\Admin;
use FireflyIII\Models\InvitedUser;
use FireflyIII\Support\Notifications\UrlValidator;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
@@ -102,9 +103,9 @@ class UserInvitation extends Notification
public function via($notifiable)
{
/** @var User|null $user */
$user = auth()->user();
$user = auth()->user();
$slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data;
if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) {
if (UrlValidator::isValidWebhookURL($slackUrl)) {
return ['mail', 'slack'];
}
return ['mail'];

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Notifications\Admin;
use FireflyIII\Support\Notifications\UrlValidator;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
@@ -99,9 +100,9 @@ class UserRegistration extends Notification
public function via($notifiable)
{
/** @var User|null $user */
$user = auth()->user();
$user = auth()->user();
$slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data;
if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) {
if (UrlValidator::isValidWebhookURL($slackUrl)) {
return ['mail', 'slack'];
}
return ['mail'];

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Notifications\Admin;
use FireflyIII\Support\Notifications\UrlValidator;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
@@ -87,21 +88,10 @@ class VersionCheckResult extends Notification
*/
public function toSlack($notifiable)
{
// return (new SlackMessage())->text($this->message)
// ->sectionBlock(function (SectionBlock $block) {
// $button = new ButtonElement('Button');
// $button->url('https://github.com/firefly-iii/firefly-iii/releases');
// $block->accessory($button);
// });
//// ->attachment(function ($attachment) {
//// $attachment->title('Firefly III @ GitHub', 'https://github.com/firefly-iii/firefly-iii/releases');
//// });
return (new SlackMessage())->content($this->message)
->attachment(function ($attachment) {
$attachment->title('Firefly III @ GitHub', 'https://github.com/firefly-iii/firefly-iii/releases');
});
->attachment(function ($attachment) {
$attachment->title('Firefly III @ GitHub', 'https://github.com/firefly-iii/firefly-iii/releases');
});
}
/**
@@ -114,9 +104,9 @@ class VersionCheckResult extends Notification
public function via($notifiable)
{
/** @var User|null $user */
$user = auth()->user();
$user = auth()->user();
$slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data;
if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) {
if (UrlValidator::isValidWebhookURL($slackUrl)) {
return ['mail', 'slack'];
}
return ['mail'];

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Notifications\User;
use FireflyIII\Models\Bill;
use FireflyIII\Support\Notifications\UrlValidator;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
@@ -38,8 +39,8 @@ class BillReminder extends Notification
{
use Queueable;
private Bill $bill;
private int $diff;
private Bill $bill;
private int $diff;
private string $field;
/**
@@ -49,9 +50,9 @@ class BillReminder extends Notification
*/
public function __construct(Bill $bill, string $field, int $diff)
{
$this->bill = $bill;
$this->bill = $bill;
$this->field = $field;
$this->diff = $diff;
$this->diff = $diff;
}
/**
@@ -101,7 +102,7 @@ class BillReminder extends Notification
$message = (string)trans(sprintf('email.bill_warning_subject_now_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]);
}
$bill = $this->bill;
$url = route('bills.show', [$bill->id]);
$url = route('bills.show', [$bill->id]);
return (new SlackMessage())
->warning()
->attachment(function ($attachment) use ($bill, $url) {
@@ -120,9 +121,9 @@ class BillReminder extends Notification
public function via($notifiable)
{
/** @var User|null $user */
$user = auth()->user();
$user = auth()->user();
$slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data;
if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) {
if (UrlValidator::isValidWebhookURL($slackUrl)) {
return ['mail', 'slack'];
}
return ['mail'];

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Notifications\User;
use FireflyIII\Support\Notifications\UrlValidator;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
@@ -96,9 +97,9 @@ class NewAccessToken extends Notification
public function via($notifiable)
{
/** @var User|null $user */
$user = auth()->user();
$user = auth()->user();
$slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data;
if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) {
if (UrlValidator::isValidWebhookURL($slackUrl)) {
return ['mail', 'slack'];
}
return ['mail'];

View File

@@ -0,0 +1,117 @@
<?php
/*
* NewAccessToken.php
* Copyright (c) 2022 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Notifications\User;
use FireflyIII\Support\Notifications\UrlValidator;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
/**
* Class RuleActionFailed
*/
class RuleActionFailed extends Notification
{
use Queueable;
private string $groupLink;
private string $groupTitle;
private string $message;
private string $ruleLink;
private string $ruleTitle;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct(array $params)
{
[$mainMessage, $groupTitle, $groupLink, $ruleTitle, $ruleLink] = $params;
$this->message = $mainMessage;
$this->groupTitle = $groupTitle;
$this->groupLink = $groupLink;
$this->ruleTitle = $ruleTitle;
$this->ruleLink = $ruleLink;
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
/**
* Get the Slack representation of the notification.
*
* @param mixed $notifiable
*
* @return SlackMessage
*/
public function toSlack($notifiable)
{
$groupTitle = $this->groupTitle;
$groupLink = $this->groupLink;
$ruleTitle = $this->ruleTitle;
$ruleLink = $this->ruleLink;
return (new SlackMessage())->content($this->message)->attachment(function ($attachment) use ($groupTitle, $groupLink) {
$attachment->title((string)trans('rules.inspect_transaction', ['title' => $groupTitle]), $groupLink);
})->attachment(function ($attachment) use ($ruleTitle, $ruleLink) {
$attachment->title((string)trans('rules.inspect_rule', ['title' => $ruleTitle]), $ruleLink);
});
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
/** @var User|null $user */
$user = auth()->user();
$slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data;
if (UrlValidator::isValidWebhookURL($slackUrl)) {
app('log')->debug('Will send ruleActionFailed through Slack!');
return ['slack'];
}
app('log')->debug('Will NOT send ruleActionFailed through Slack');
return [];
}
}

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Notifications\User;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Support\Notifications\UrlValidator;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
@@ -124,9 +125,9 @@ class UserLogin extends Notification
public function via($notifiable)
{
/** @var User|null $user */
$user = auth()->user();
$user = auth()->user();
$slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data;
if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) {
if (UrlValidator::isValidWebhookURL($slackUrl)) {
return ['mail', 'slack'];
}
return ['mail'];

View File

@@ -32,6 +32,8 @@ use FireflyIII\Events\DetectedNewIPAddress;
use FireflyIII\Events\Model\BudgetLimit\Created;
use FireflyIII\Events\Model\BudgetLimit\Deleted;
use FireflyIII\Events\Model\BudgetLimit\Updated;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject;
use FireflyIII\Events\NewVersionAvailable;
use FireflyIII\Events\RegisteredUser;
use FireflyIII\Events\RequestedNewPassword;
@@ -170,6 +172,14 @@ class EventServiceProvider extends ServiceProvider
'FireflyIII\Handlers\Events\Model\BudgetLimitHandler@deleted',
],
// rule actions
RuleActionFailedOnArray::class => [
'FireflyIII\Handlers\Events\Model\RuleHandler@ruleActionFailedOnArray',
],
RuleActionFailedOnObject::class => [
'FireflyIII\Handlers\Events\Model\RuleHandler@ruleActionFailedOnObject',
],
];
/**

View File

@@ -39,6 +39,49 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
{
private User $user;
/**
* @inheritDoc
*/
public function cleanup(): void
{
$exists = [];
$availableBudgets = $this->user->availableBudgets()->get();
/** @var AvailableBudget $availableBudget */
foreach ($availableBudgets as $availableBudget) {
$start = $availableBudget->start_date->format('Y-m-d');
$end = $availableBudget->end_date->format('Y-m-d');
$key = sprintf('%s-%s-%s', $availableBudget->transaction_currency_id, $start, $end);
if (array_key_exists($key, $exists)) {
app('log')->debug(sprintf('Found duplicate AB: %s %s, %s-%s. Has been deleted', $availableBudget->transaction_currency_id, $availableBudget->amount, $start, $end));
$availableBudget->delete();
}
$exists[$key] = true;
}
}
/**
* Return a list of all available budgets (in all currencies) (for the selected period).
*
* @param Carbon|null $start
* @param Carbon|null $end
*
* @return Collection
*/
public function get(?Carbon $start = null, ?Carbon $end = null): Collection
{
$query = $this->user->availableBudgets()->with(['transactionCurrency']);
if (null !== $start && null !== $end) {
$query->where(
static function (Builder $q1) use ($start, $end) {
$q1->where('start_date', '=', $start->format('Y-m-d'));
$q1->where('end_date', '=', $end->format('Y-m-d'));
}
);
}
return $query->get(['available_budgets.*']);
}
/**
* Delete all available budgets.
*/
@@ -122,29 +165,6 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
return $return;
}
/**
* Return a list of all available budgets (in all currencies) (for the selected period).
*
* @param Carbon|null $start
* @param Carbon|null $end
*
* @return Collection
*/
public function get(?Carbon $start = null, ?Carbon $end = null): Collection
{
$query = $this->user->availableBudgets()->with(['transactionCurrency']);
if (null !== $start && null !== $end) {
$query->where(
static function (Builder $q1) use ($start, $end) {
$q1->where('start_date', '=', $start->format('Y-m-d'));
$q1->where('end_date', '=', $end->format('Y-m-d'));
}
);
}
return $query->get(['available_budgets.*']);
}
/**
* Returns all available budget objects.
*
@@ -180,6 +200,23 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
return $query->get();
}
/**
* Returns all available budget objects.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*
*/
public function getAvailableBudgetsByExactDate(Carbon $start, Carbon $end): Collection
{
return $this->user->availableBudgets()
->where('start_date', '=', $start->format('Y-m-d'))
->where('end_date', '=', $end->format('Y-m-d'))
->get();
}
/**
* @inheritDoc
*/

View File

@@ -35,6 +35,11 @@ use Illuminate\Support\Collection;
*/
interface AvailableBudgetRepositoryInterface
{
/**
* @return void
*/
public function cleanup(): void;
/**
* Delete all available budgets.
*/
@@ -111,6 +116,14 @@ interface AvailableBudgetRepositoryInterface
*/
public function getAvailableBudgetsByDate(?Carbon $start, ?Carbon $end): Collection;
/**
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getAvailableBudgetsByExactDate(Carbon $start, Carbon $end): Collection;
/**
* Get by transaction currency and date. Should always result in one entry or NULL.
*

View File

@@ -294,7 +294,7 @@ trait RenderPartialViews
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getCurrentActions(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
throw new FireflyException('Could not render', 0, $e);
throw new FireflyException(sprintf('Could not render: %s', $e->getMessage()), 0, $e);
}
++$index;
@@ -349,7 +349,7 @@ trait RenderPartialViews
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getCurrentTriggers(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
throw new FireflyException('Could not render', 0, $e);
throw new FireflyException(sprintf('Could not render: %s', $e->getMessage()), 0, $e);
}
++$index;

View File

@@ -62,7 +62,7 @@ trait RuleManagement
} catch (Throwable $e) {
Log::error(sprintf('Throwable was thrown in getPreviousActions(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
throw new FireflyException('Could not render', 0, $e);
throw new FireflyException(sprintf('Could not render: %s', $e->getMessage()), 0, $e);
}
$index++;
}
@@ -109,7 +109,7 @@ trait RuleManagement
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
throw new FireflyException('Could not render', 0, $e);
throw new FireflyException(sprintf('Could not render: %s', $e->getMessage()), 0, $e);
}
$index++;
}
@@ -153,7 +153,7 @@ trait RuleManagement
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
throw new FireflyException('Could not render', 0, $e);
throw new FireflyException(sprintf('Could not render: %s', $e->getMessage()), 0, $e);
}
$index++;
}

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
/*
* UrlValidator.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/>.
*/
namespace FireflyIII\Support\Notifications;
/**
* Class UrlValidator
*/
class UrlValidator
{
/**
* @param string $url
*
* @return bool
*/
public static function isValidWebhookURL(string $url): bool
{
return str_starts_with($url, 'https://hooks.slack.com/services/') || str_starts_with($url, 'https://discord.com/api/webhooks/');
}
}

View File

@@ -1004,151 +1004,151 @@ class OperatorQuerySearch implements SearchInterface
//
case '-date_on':
case 'date_on':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setExactDateParams($range, $prohibited);
return false;
case 'date_before':
case '-date_after':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setDateBeforeParams($range);
return false;
case 'date_after':
case '-date_before':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setDateAfterParams($range);
return false;
case 'interest_date_on':
case '-interest_date_on':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setExactMetaDateParams('interest_date', $range, $prohibited);
return false;
case 'interest_date_before':
case '-interest_date_after':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setMetaDateBeforeParams('interest_date', $range);
return false;
case 'interest_date_after':
case '-interest_date_before':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setMetaDateAfterParams('interest_date', $range);
return false;
case 'book_date_on':
case '-book_date_on':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setExactMetaDateParams('book_date', $range, $prohibited);
return false;
case 'book_date_before':
case '-book_date_after':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setMetaDateBeforeParams('book_date', $range);
return false;
case 'book_date_after':
case '-book_date_before':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setMetaDateAfterParams('book_date', $range);
return false;
case 'process_date_on':
case '-process_date_on':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setExactMetaDateParams('process_date', $range, $prohibited);
return false;
case 'process_date_before':
case '-process_date_after':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setMetaDateBeforeParams('process_date', $range);
return false;
case 'process_date_after':
case '-process_date_before':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setMetaDateAfterParams('process_date', $range);
return false;
case 'due_date_on':
case '-due_date_on':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setExactMetaDateParams('due_date', $range, $prohibited);
return false;
case 'due_date_before':
case '-due_date_after':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setMetaDateBeforeParams('due_date', $range);
return false;
case 'due_date_after':
case '-due_date_before':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setMetaDateAfterParams('due_date', $range);
return false;
case 'payment_date_on':
case '-payment_date_on':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setExactMetaDateParams('payment_date', $range, $prohibited);
return false;
case 'payment_date_before':
case '-payment_date_after':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setMetaDateBeforeParams('payment_date', $range);
return false;
case 'payment_date_after':
case '-payment_date_before':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setMetaDateAfterParams('payment_date', $range);
return false;
case 'invoice_date_on':
case '-invoice_date_on':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setExactMetaDateParams('invoice_date', $range, $prohibited);
return false;
case 'invoice_date_before':
case '-invoice_date_after':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setMetaDateBeforeParams('invoice_date', $range);
return false;
case 'invoice_date_after':
case '-invoice_date_before':
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setMetaDateAfterParams('invoice_date', $range);
return false;
case 'created_at_on':
case '-created_at_on':
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setExactObjectDateParams('created_at', $range, $prohibited);
return false;
case 'created_at_before':
case '-created_at_after':
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setObjectDateBeforeParams('created_at', $range);
return false;
case 'created_at_after':
case '-created_at_before':
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setObjectDateAfterParams('created_at', $range);
return false;
case 'updated_at_on':
case '-updated_at_on':
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setExactObjectDateParams('updated_at', $range, $prohibited);
return false;
case 'updated_at_before':
case '-updated_at_after':
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setObjectDateBeforeParams('updated_at', $range);
return false;
case 'updated_at_after':
case '-updated_at_before':
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
$range = $this->parseDateRange($value);
$range = $this->parseDateRange($operator, $value);
$this->setObjectDateAfterParams('updated_at', $range);
return false;
//
@@ -1550,13 +1550,22 @@ class OperatorQuerySearch implements SearchInterface
* @return array
* @throws FireflyException
*/
private function parseDateRange(string $value): array
private function parseDateRange(string $type, string $value): array
{
$parser = new ParseDateString();
if ($parser->isDateRange($value)) {
return $parser->parseRange($value);
}
$parsedDate = $parser->parseDate($value);
try {
$parsedDate = $parser->parseDate($value);
} catch (FireflyException $e) {
Log::debug(sprintf('Could not parse date "%s", will return empty array.', $value));
$this->invalidOperators[] = [
'type' => $type,
'value' => (string)$value,
];
return [];
}
return [
'exact' => $parsedDate,

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Factory\TagFactory;
use FireflyIII\Models\RuleAction;
@@ -61,7 +62,7 @@ class AddTag implements ActionInterface
if (null === $tag) {
// could not find, could not create tag.
Log::error(sprintf('RuleAction AddTag. Could not find or create tag "%s"', $this->action->action_value));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.find_or_create_tag_failed', ['tag' => $this->action->action_value])));
return false;
}
@@ -78,12 +79,12 @@ class AddTag implements ActionInterface
// event for audit log entry
event(new TriggeredAuditLog($this->action->rule, $object, 'add_tag', null, $tag->tag));
return true;
}
Log::debug(
sprintf('RuleAction AddTag fired but tag %d ("%s") was already added to journal %d.', $tag->id, $tag->tag, $journal['transaction_journal_id'])
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.tag_already_added', ['tag' => $this->action->action_value])));
return false;
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\Note;
use FireflyIII\Models\RuleAction;
@@ -56,6 +57,7 @@ class AppendDescriptionToNotes implements ActionInterface
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
if (null === $object) {
Log::error(sprintf('No journal #%d belongs to user #%d.', $journal['transaction_journal_id'], $journal['user_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_other_user')));
return false;
}
$note = $object->notes()->first();

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\Note;
use FireflyIII\Models\RuleAction;
@@ -60,6 +61,7 @@ class AppendNotesToDescription implements ActionInterface
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
if (null === $object) {
Log::error(sprintf('No journal #%d belongs to user #%d.', $journal['transaction_journal_id'], $journal['user_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_other_user')));
return false;
}
$note = $object->notes()->first();
@@ -80,6 +82,7 @@ class AppendNotesToDescription implements ActionInterface
return true;
}
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.new_notes_empty')));
return false;
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal;
@@ -56,6 +57,7 @@ class ClearBudget implements ActionInterface
$budget = $object->budgets()->first();
if (null === $budget) {
Log::debug(sprintf('RuleAction ClearBudget, no budget in journal #%d.', $journal['transaction_journal_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_already_no_budget')));
return false;
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal;
@@ -56,6 +57,7 @@ class ClearCategory implements ActionInterface
$category = $object->categories()->first();
if (null === $category) {
Log::debug(sprintf('RuleAction ClearCategory, no category in journal #%d.', $journal['transaction_journal_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_already_no_category')));
return false;
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal;
@@ -55,6 +56,7 @@ class ClearNotes implements ActionInterface
$notes = $object->notes()->first();
if (null === $notes) {
Log::debug(sprintf('RuleAction ClearNotes, journal #%d has no notes.', $journal['transaction_journal_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_already_no_notes')));
return false;
}
$before = $notes->text;

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\AccountFactory;
@@ -65,11 +66,13 @@ class ConvertToDeposit implements ActionInterface
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
if (null === $object) {
Log::error(sprintf('Cannot find journal #%d, cannot convert to deposit.', $journal['transaction_journal_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_not_found')));
return false;
}
$groupCount = TransactionJournal::where('transaction_group_id', $journal['transaction_group_id'])->count();
if ($groupCount > 1) {
Log::error(sprintf('Group #%d has more than one transaction in it, cannot convert to deposit.', $journal['transaction_group_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.split_group')));
return false;
}
@@ -77,7 +80,7 @@ class ConvertToDeposit implements ActionInterface
$type = $object->transactionType->type;
if (TransactionType::DEPOSIT === $type) {
Log::error(sprintf('Journal #%d is already a deposit (rule #%d).', $journal['transaction_journal_id'], $this->action->rule_id));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.is_already_deposit')));
return false;
}
@@ -89,6 +92,7 @@ class ConvertToDeposit implements ActionInterface
} catch (JsonException | FireflyException $e) {
Log::debug('Could not convert withdrawal to deposit.');
Log::error($e->getMessage());
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.complex_error')));
return false;
}
@@ -104,13 +108,14 @@ class ConvertToDeposit implements ActionInterface
} catch (JsonException | FireflyException $e) {
Log::debug('Could not convert transfer to deposit.');
Log::error($e->getMessage());
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.complex_error')));
return false;
}
event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::TRANSFER, TransactionType::DEPOSIT));
return $res;
}
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.unsupported_transaction_type_deposit', ['type' => $type])));
return false;
}

View File

@@ -24,6 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
@@ -62,11 +64,13 @@ class ConvertToTransfer implements ActionInterface
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
if (null === $object) {
Log::error(sprintf('Cannot find journal #%d, cannot convert to transfer.', $journal['transaction_journal_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_not_found')));
return false;
}
$groupCount = TransactionJournal::where('transaction_group_id', $journal['transaction_group_id'])->count();
if ($groupCount > 1) {
Log::error(sprintf('Group #%d has more than one transaction in it, cannot convert to transfer.', $journal['transaction_group_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.split_group')));
return false;
}
@@ -77,15 +81,19 @@ class ConvertToTransfer implements ActionInterface
Log::error(
sprintf('Journal #%d is already a transfer so cannot be converted (rule #%d).', $object->id, $this->action->rule_id)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.is_already_transfer')));
return false;
}
if (TransactionType::DEPOSIT !== $type && TransactionType::WITHDRAWAL !== $type) {
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.unsupported_transaction_type_transfer', ['type' => $type])));
return false;
}
// find the asset account in the action value.
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
$repository->setUser($user);
$opposing = null;
$expectedType = null;
if (TransactionType::WITHDRAWAL === $type) {
$expectedType = $this->getSourceType($journalId);
@@ -107,6 +115,7 @@ class ConvertToTransfer implements ActionInterface
$this->action->rule_id
)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_valid_opposing', ['name' => $this->action->action_value])));
return false;
}
@@ -118,9 +127,12 @@ class ConvertToTransfer implements ActionInterface
} catch (FireflyException $e) {
Log::debug('Could not convert withdrawal to transfer.');
Log::error($e->getMessage());
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.complex_error')));
return false;
}
event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::WITHDRAWAL, TransactionType::TRANSFER));
if (false !== $res) {
event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::WITHDRAWAL, TransactionType::TRANSFER));
}
return $res;
}
if (TransactionType::DEPOSIT === $type) {
@@ -130,12 +142,15 @@ class ConvertToTransfer implements ActionInterface
} catch (FireflyException $e) {
Log::debug('Could not convert deposit to transfer.');
Log::error($e->getMessage());
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.complex_error')));
return false;
}
event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::DEPOSIT, TransactionType::TRANSFER));
if (false !== $res) {
event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::DEPOSIT, TransactionType::TRANSFER));
}
return $res;
}
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.unsupported_transaction_type_transfer', ['type' => $type])));
return false;
}
@@ -192,6 +207,7 @@ class ConvertToTransfer implements ActionInterface
[$journal->id, $opposing->name, $this->action->rule_id]
)
);
event(new RuleActionFailedOnObject($this->action, $journal, trans('rules.already_has_source_asset', ['name' => $opposing->name])));
return false;
}
@@ -250,6 +266,7 @@ class ConvertToTransfer implements ActionInterface
[$journal->id, $opposing->name, $this->action->rule_id]
)
);
event(new RuleActionFailedOnObject($this->action, $journal, trans('rules.already_has_destination_asset', ['name' => $opposing->name])));
return false;
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\AccountFactory;
@@ -65,21 +66,26 @@ class ConvertToWithdrawal implements ActionInterface
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
if (null === $object) {
Log::error(sprintf('Cannot find journal #%d, cannot convert to withdrawal.', $journal['transaction_journal_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_not_found')));
return false;
}
$groupCount = TransactionJournal::where('transaction_group_id', $journal['transaction_group_id'])->count();
if ($groupCount > 1) {
Log::error(sprintf('Group #%d has more than one transaction in it, cannot convert to withdrawal.', $journal['transaction_group_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.split_group')));
return false;
}
$type = $object->transactionType->type;
if (TransactionType::WITHDRAWAL === $type) {
Log::error(sprintf('Journal #%d is already a withdrawal (rule #%d).', $journal['transaction_journal_id'], $this->action->rule_id));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.is_already_withdrawal')));
return false;
}
if (TransactionType::DEPOSIT !== $type && TransactionType::TRANSFER !== $type) {
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.unsupported_transaction_type_withdrawal', ['type' => $type])));
return false;
}
if (TransactionType::DEPOSIT === $type) {
Log::debug('Going to transform a deposit to a withdrawal.');
try {
@@ -87,6 +93,7 @@ class ConvertToWithdrawal implements ActionInterface
} catch (JsonException | FireflyException $e) {
Log::debug('Could not convert transfer to deposit.');
Log::error($e->getMessage());
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.complex_error')));
return false;
}
event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::DEPOSIT, TransactionType::WITHDRAWAL));
@@ -101,13 +108,14 @@ class ConvertToWithdrawal implements ActionInterface
} catch (JsonException | FireflyException $e) {
Log::debug('Could not convert transfer to deposit.');
Log::error($e->getMessage());
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.complex_error')));
return false;
}
event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::TRANSFER, TransactionType::WITHDRAWAL));
return $res;
}
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.unsupported_transaction_type_withdrawal', ['type' => $type])));
return false;
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal;
@@ -73,6 +74,7 @@ class LinkToBill implements ActionInterface
$billName
)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.already_linked_to_subscription', ['name' => $billName])));
return false;
}
@@ -97,7 +99,7 @@ class LinkToBill implements ActionInterface
$billName
)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_subscription', ['name' => $billName])));
return false;
}
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\Note;
use FireflyIII\Models\RuleAction;
@@ -57,6 +58,7 @@ class MoveDescriptionToNotes implements ActionInterface
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
if (null === $object) {
Log::error(sprintf('No journal #%d belongs to user #%d.', $journal['transaction_journal_id'], $journal['user_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_other_user')));
return false;
}
$note = $object->notes()->first();

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal;
@@ -63,16 +64,19 @@ class MoveNotesToDescription implements ActionInterface
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
if (null === $object) {
Log::error(sprintf('No journal #%d belongs to user #%d.', $journal['transaction_journal_id'], $journal['user_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_other_user')));
return false;
}
$note = $object->notes()->first();
if (null === $note) {
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_notes_to_move')));
// nothing to move, return null
return false;
}
if ('' === $note->text) {
// nothing to move, return null
$note->delete();
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_notes_to_move')));
return false;
}
$before = $object->description;

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal;
@@ -55,6 +56,7 @@ class RemoveAllTags implements ActionInterface
$count = DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal['transaction_journal_id'])->count();
if (0 === $count) {
Log::debug(sprintf('RuleAction RemoveAllTags, journal #%d has no tags.', $journal['transaction_journal_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_tags_to_remove')));
return false;
}
Log::debug(sprintf('RuleAction RemoveAllTags removed all tags from journal %d.', $journal['transaction_journal_id']));

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal;
@@ -61,6 +62,7 @@ class RemoveTag implements ActionInterface
Log::debug(
sprintf('RuleAction RemoveTag tried to remove tag "%s" from journal #%d but no such tag exists.', $name, $journal['transaction_journal_id'])
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_tag', ['tag' => $name])));
return false;
}
$count = DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal['transaction_journal_id'])->where('tag_id', $tag->id)->count();
@@ -68,6 +70,7 @@ class RemoveTag implements ActionInterface
Log::debug(
sprintf('RuleAction RemoveTag tried to remove tag "%s" from journal #%d but no such tag is linked.', $name, $journal['transaction_journal_id'])
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_unlink_tag', ['tag' => $name])));
return false;
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal;
@@ -65,7 +66,7 @@ class SetBudget implements ActionInterface
$search
)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_budget', ['name' => $search])));
return false;
}
@@ -78,7 +79,7 @@ class SetBudget implements ActionInterface
$journal['transaction_type_type']
)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_set_budget', ['type' => $journal['transaction_type_type'], 'name' => $search])));
return false;
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Factory\CategoryFactory;
use FireflyIII\Models\RuleAction;
@@ -57,7 +58,7 @@ class SetCategory implements ActionInterface
$search = $this->action->action_value;
if (null === $user) {
Log::error(sprintf('Journal has no valid user ID so action SetCategory("%s") cannot be applied', $search), $journal);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_such_journal')));
return false;
}
@@ -73,7 +74,7 @@ class SetCategory implements ActionInterface
$search
)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_category', ['name' => $search])));
return false;
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\Account;
use FireflyIII\Models\RuleAction;
@@ -65,7 +66,7 @@ class SetDestinationAccount implements ActionInterface
if (null === $object) {
Log::error('Could not find journal.');
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_such_journal')));
return false;
}
$type = $object->transactionType->type;
@@ -81,7 +82,7 @@ class SetDestinationAccount implements ActionInterface
$this->action->action_value
)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_asset', ['name' => $this->action->action_value])));
return false;
}
@@ -90,13 +91,13 @@ class SetDestinationAccount implements ActionInterface
$source = $object->transactions()->where('amount', '<', 0)->first();
if (null === $source) {
Log::error('Could not find source transaction.');
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_source_transaction')));
return false;
}
// account must not be deleted (in the meantime):
if (null === $source->account) {
Log::error('Could not find source transaction account.');
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_source_transaction_account')));
return false;
}
if (null !== $newAccount && (int)$newAccount->id === (int)$source->account_id) {
@@ -108,6 +109,7 @@ class SetDestinationAccount implements ActionInterface
)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.already_has_destination', ['name' => $newAccount->name])));
return false;
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\Account;
use FireflyIII\Models\RuleAction;
@@ -64,7 +65,7 @@ class SetSourceAccount implements ActionInterface
$this->repository = app(AccountRepositoryInterface::class);
if (null === $object) {
Log::error('Could not find journal.');
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_such_journal')));
return false;
}
$type = $object->transactionType->type;
@@ -76,7 +77,7 @@ class SetSourceAccount implements ActionInterface
Log::error(
sprintf('Cant change source account of journal #%d because no asset account with name "%s" exists.', $object->id, $this->action->action_value)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_asset', ['name' => $this->action->action_value])));
return false;
}
@@ -85,13 +86,13 @@ class SetSourceAccount implements ActionInterface
$destination = $object->transactions()->where('amount', '>', 0)->first();
if (null === $destination) {
Log::error('Could not find destination transaction.');
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_destination_transaction')));
return false;
}
// account must not be deleted (in the meantime):
if (null === $destination->account) {
Log::error('Could not find destination transaction account.');
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_destination_transaction_account')));
return false;
}
if (null !== $newAccount && (int)$newAccount->id === (int)$destination->account_id) {
@@ -102,12 +103,12 @@ class SetSourceAccount implements ActionInterface
$destination->account_id
)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.already_has_source', ['name' => $newAccount->name])));
return false;
}
// if this is a deposit, the new source account must be a revenue account and may be created:
// or its a liability
// or it's a liability
if (TransactionType::DEPOSIT === $type) {
$newAccount = $this->findDepositSourceAccount();
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use DB;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\Transaction;
@@ -59,18 +60,20 @@ class SwitchAccounts implements ActionInterface
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
if (null === $object) {
Log::error(sprintf('Cannot find journal #%d, cannot switch accounts.', $journal['transaction_journal_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_such_journal')));
return false;
}
$groupCount = TransactionJournal::where('transaction_group_id', $journal['transaction_group_id'])->count();
if ($groupCount > 1) {
Log::error(sprintf('Group #%d has more than one transaction in it, cannot switch accounts.', $journal['transaction_group_id']));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.split_group')));
return false;
}
$type = $object->transactionType->type;
if (TransactionType::TRANSFER !== $type) {
Log::error(sprintf('Journal #%d is NOT a transfer (rule #%d), cannot switch accounts.', $journal['transaction_journal_id'], $this->action->rule_id));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.is_not_transfer')));
return false;
}
@@ -80,7 +83,7 @@ class SwitchAccounts implements ActionInterface
$destTransaction = $object->transactions()->where('amount', '>', 0)->first();
if (null === $sourceTransaction || null === $destTransaction) {
Log::error(sprintf('Journal #%d has no source or destination transaction (rule #%d), cannot switch accounts.', $journal['transaction_journal_id'], $this->action->rule_id));
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_accounts')));
return false;
}
$sourceAccountId = (int)$sourceTransaction->account_id;

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\RuleAction;
@@ -61,16 +62,15 @@ class UpdatePiggybank implements ActionInterface
// refresh the transaction type.
$user = User::find($journal['user_id']);
/** @var TransactionJournal $journalObj */
$journalObj = $user->transactionJournals()->find($journal['transaction_journal_id']);
$type = TransactionType::find((int)$journalObj->transaction_type_id);
$journal['transaction_type_type'] = $type->type;
$journalObj = $user->transactionJournals()->find($journal['transaction_journal_id']);
$type = TransactionType::find((int)$journalObj->transaction_type_id);
$piggyBank = $this->findPiggyBank($user);
if (null === $piggyBank) {
Log::info(
sprintf('No piggy bank named "%s", cant execute action #%d of rule #%d', $this->action->action_value, $this->action->id, $this->action->rule_id)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_piggy', ['name' => $this->action->action_value])));
return false;
}
@@ -130,7 +130,7 @@ class UpdatePiggybank implements ActionInterface
$destination->account_id
)
);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_link_piggy', ['name' => $this->action->action_value])));
return false;
}

View File

@@ -28,6 +28,7 @@ use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use Illuminate\Support\Collection;
@@ -38,6 +39,7 @@ use Illuminate\Support\Collection;
class AccountTransformer extends AbstractTransformer
{
private array $accountMeta;
private array $accountTypes;
private array $balances;
private array $convertedBalances;
private array $currencies;
@@ -51,6 +53,7 @@ class AccountTransformer extends AbstractTransformer
{
$this->currencies = [];
$this->accountMeta = [];
$this->accountTypes = [];
$this->balances = app('steam')->balancesByAccounts($objects, $this->getDate());
$this->convertedBalances = app('steam')->balancesByAccountsConverted($objects, $this->getDate());
$repository = app(CurrencyRepositoryInterface::class);
@@ -72,6 +75,15 @@ class AccountTransformer extends AbstractTransformer
$id = (int)$entry->account_id;
$this->accountMeta[$id][$entry->name] = $entry->data;
}
// get account types:
// select accounts.id, account_types.type from account_types left join accounts on accounts.account_type_id = account_types.id;
$accountTypes = AccountType::leftJoin('accounts', 'accounts.account_type_id', '=', 'account_types.id')
->whereIn('accounts.id', $accountIds)
->get(['accounts.id', 'account_types.type']);
/** @var AccountType $row */
foreach ($accountTypes as $row) {
$this->accountTypes[(int)$row->id] = (string)config(sprintf('firefly.shortNamesByFullName.%s', $row->type));
}
}
/**
@@ -96,10 +108,13 @@ class AccountTransformer extends AbstractTransformer
*/
public function transform(Account $account): array
{
//$fullType = $account->accountType->type;
//$accountType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $fullType));
$id = (int)$account->id;
// various meta
$accountRole = $this->accountMeta[$id]['account_role'] ?? null;
$accountType = $this->accountTypes[$id];
$order = (int)$account->order;
// no currency? use default
$currency = $this->default;
if (0 !== (int)$this->accountMeta[$id]['currency_id']) {
@@ -109,16 +124,21 @@ class AccountTransformer extends AbstractTransformer
$balance = $this->balances[$id] ?? null;
$nativeBalance = $this->convertedBalances[$id]['native_balance'] ?? null;
// no order for some accounts:
if (!in_array(strtolower($accountType), ['liability', 'liabilities', 'asset'], true)) {
$order = null;
}
return [
'id' => (string)$account->id,
'created_at' => $account->created_at->toAtomString(),
'updated_at' => $account->updated_at->toAtomString(),
'active' => $account->active,
//'order' => $order,
'order' => $order,
'name' => $account->name,
'iban' => '' === $account->iban ? null : $account->iban,
// 'type' => strtolower($accountType),
// 'account_role' => $accountRole,
'type' => strtolower($accountType),
'account_role' => $accountRole,
'currency_id' => (string)$currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,

View File

@@ -302,7 +302,7 @@ class TransactionGroupTransformer extends AbstractTransformer
if (null === $string) {
return null;
}
Log::debug(sprintf('Now in date("%s")', $string));
// Log::debug(sprintf('Now in date("%s")', $string));
if (10 === strlen($string)) {
return Carbon::createFromFormat('Y-m-d', $string, config('app.timezone'));
}

View File

@@ -114,7 +114,11 @@ trait DepositValidation
// source can be any of the following types.
$validTypes = array_keys($this->combinations[$this->transactionType]);
if (null === $accountId && null === $accountName && false === $this->canCreateTypes($validTypes)) {
if (null === $accountId &&
null === $accountName &&
null === $accountIban &&
null === $accountNumber &&
false === $this->canCreateTypes($validTypes)) {
// if both values are NULL return false,
// because the source of a deposit can't be created.
// (this never happens).
@@ -122,12 +126,12 @@ trait DepositValidation
$result = false;
}
// if there is an iban, it can only be in use by a revenue account or we will fail.
// if there is an iban, it can only be in use by a revenue account, or we will fail.
if (null !== $accountIban && '' !== $accountIban) {
app('log')->debug('Check if there is not already an account with this IBAN');
$existing = $this->findExistingAccount([AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], ['iban' => $accountIban]);
if (null !== $existing) {
$this->destError = (string)trans('validation.deposit_src_iban_exists');
$this->sourceError = (string)trans('validation.deposit_src_iban_exists');
return false;
}
}

View File

@@ -265,6 +265,7 @@ class AccountValidator
if (null !== $accountId && $accountId > 0) {
$first = $this->accountRepository->find($accountId);
if ((null !== $first) && in_array($first->accountType->type, $validTypes, true)) {
app('log')->debug(sprintf('ID: Found %s account #%d ("%s", IBAN "%s")', $first->accountType->type, $first->id, $first->name, $first->iban ?? 'no iban'));
return $first;
}
}
@@ -273,6 +274,7 @@ class AccountValidator
if (null !== $accountIban && '' !== (string)$accountIban) {
$first = $this->accountRepository->findByIbanNull($accountIban, $validTypes);
if ((null !== $first) && in_array($first->accountType->type, $validTypes, true)) {
app('log')->debug(sprintf('Iban: Found %s account #%d ("%s", IBAN "%s")', $first->accountType->type, $first->id, $first->name, $first->iban ?? 'no iban'));
return $first;
}
}
@@ -281,14 +283,19 @@ class AccountValidator
if (null !== $accountNumber && '' !== (string)$accountNumber) {
$first = $this->accountRepository->findByAccountNumber($accountNumber, $validTypes);
if ((null !== $first) && in_array($first->accountType->type, $validTypes, true)) {
app('log')->debug(sprintf('Number: Found %s account #%d ("%s", IBAN "%s")', $first->accountType->type, $first->id, $first->name, $first->iban ?? 'no iban'));
return $first;
}
}
// find by name:
if ('' !== (string)$accountName) {
return $this->accountRepository->findByName($accountName, $validTypes);
$first = $this->accountRepository->findByName($accountName, $validTypes);
if (null !== $first) {
app('log')->debug(sprintf('Name: Found %s account #%d ("%s", IBAN "%s")', $first->accountType->type, $first->id, $first->name, $first->iban ?? 'no iban'));
}
}
app('log')->debug('Found nothing!');
return null;
}

View File

@@ -103,6 +103,7 @@ trait TransactionValidation
*/
protected function validateSingleAccount(Validator $validator, int $index, string $transactionType, array $transaction): void
{
app('log')->debug(sprintf('Now in validateSingleAccount(%d)', $index));
/** @var AccountValidator $accountValidator */
$accountValidator = app(AccountValidator::class);
@@ -784,8 +785,8 @@ trait TransactionValidation
private function compareAccountData(string $type, array $comparison): bool
{
return match ($type) {
default => $this->compareAccountDataWithdrawal($comparison),
'deposit' => $this->compareAccountDataDeposit($comparison),
default => $this->compareAccountDataWithdrawal($comparison),
'deposit' => $this->compareAccountDataDeposit($comparison),
'transfer' => $this->compareAccountDataTransfer($comparison),
};
}

View File

@@ -3,6 +3,31 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## 6.0.21 - 2023-09-02
### Added
- Rules will now report failures if a Slack/Discord notification channel is configured
- Notifications can be sent to Discord
- Beta layout `v2`, activate with `FIRELY_III_LAYOUT=v2`
### Changed
- Audit log settings are changed, refer to the `.env.example`-file.
- Many URLs are new rendered as relative URLs.
### Fixed
- [Issue 7853](https://github.com/firefly-iii/firefly-iii/issues/7853) Left to spend on main page shows incorrect value
- [Issue 7883](https://github.com/firefly-iii/firefly-iii/issues/7883) Missing translation
- [Issue 7910](https://github.com/firefly-iii/firefly-iii/issues/7910) Type format error
- Home page respects account order
- JS errors for users using Firefly III in a subdir.
### API
- Bumped to v2.0.6 but only so the docs match again.
## 6.0.20 - 2023-08-13
### Fixed

View File

@@ -85,7 +85,7 @@
"diglactic/laravel-breadcrumbs": "^8.1",
"doctrine/dbal": "3.*",
"gdbots/query-parser": "^3.0",
"guzzlehttp/guzzle": "^7.7",
"guzzlehttp/guzzle": "^7.8",
"jc5/google2fa-laravel": "^2.0",
"jc5/recovery": "^2",
"laravel/framework": "^10",
@@ -111,7 +111,7 @@
},
"require-dev": {
"barryvdh/laravel-ide-helper": "2.*",
"ergebnis/phpstan-rules": "^2.0",
"ergebnis/phpstan-rules": "^2.1",
"fakerphp/faker": "1.*",
"filp/whoops": "2.*",
"mockery/mockery": "1.*",

670
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -110,7 +110,7 @@ return [
'handle_debts' => true,
// see cer.php for exchange rates feature flag.
],
'version' => '6.0.20',
'version' => '6.0.21',
'api_version' => '2.0.6',
'db_version' => 20,
@@ -148,7 +148,7 @@ return [
'update_minimum_age' => 7,
// notifications
'available_notifications' => ['bill_reminder', 'new_access_token', 'transaction_creation', 'user_login'],
'available_notifications' => ['bill_reminder', 'new_access_token', 'transaction_creation', 'user_login', 'rule_action_failures'],
'admin_notifications' => ['admin_new_reg', 'user_new_reg', 'new_version', 'invite_created', 'invite_redeemed'],
// enabled languages

View File

@@ -24,6 +24,30 @@ declare(strict_types=1);
use FireflyIII\Support\Logging\AuditLogger;
use Monolog\Handler\SyslogUdpHandler;
// standard config for both log things:
$defaultChannels = ['daily', 'stdout'];
$auditChannels = ['audit_daily', 'audit_stdout'];
// validChannels is missing 'stack' because we already check for that one.
$validChannels = ['single', 'papertrail', 'stdout', 'daily', 'syslog', 'errorlog'];
$validAuditChannels = ['audit_papertrail', 'audit_stdout', 'audit_stdout', 'audit_daily', 'audit_syslog', 'audit_errorlog'];
// which settings did the user set, if any?
$defaultLogChannel = (string)envNonEmpty('LOG_CHANNEL', 'stack');
$auditLogChannel = (string)envNonEmpty('AUDIT_LOG_CHANNEL', '');
if ('stack' === $defaultLogChannel) {
$defaultChannels = ['daily', 'stdout'];
}
if (in_array($defaultLogChannel, $validChannels, true)) {
$defaultChannels = [$defaultLogChannel];
}
if (in_array($auditLogChannel, $validAuditChannels, true)) {
$auditChannels = [$auditLogChannel];
}
return [
/*
|--------------------------------------------------------------------------
@@ -53,16 +77,27 @@ return [
*/
'channels' => [
// default channels for 'stack' and audit logs:
'stack' => [
/*
* 'stack' and 'audit' are the two "generic" channels that
* are valid destinations for logs.
*/
'stack' => [
'driver' => 'stack',
'channels' => ['daily', 'stdout'],
'channels' => $defaultChannels,
],
'audit' => [
'audit' => [
'driver' => 'stack',
'channels' => ['audit_daily', 'audit_stdout'],
'channels' => $auditChannels,
],
'papertrail' => [
/*
* There are 6 valid destinations for the normal logs, listed below:
*/
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
],
'papertrail' => [
'driver' => 'monolog',
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
'handler' => SyslogUdpHandler::class,
@@ -71,55 +106,65 @@ return [
'port' => env('PAPERTRAIL_PORT'),
],
],
// single laravel log file:
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
],
// stdout, used in stack 'stack' by default:
'stdout' => [
'stdout' => [
'driver' => 'single',
'path' => 'php://stdout',
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
],
// daily, used in stack 'stack' by default:
'daily' => [
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/ff3-' . PHP_SAPI . '.log'),
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
'days' => 7,
],
'syslog' => [
'driver' => 'syslog',
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
],
'errorlog' => [
'driver' => 'errorlog',
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
],
// the audit log destinations:
'audit_daily' => [
/*
* There are 5 valid destinations for the audit logs, listed below.
* The only one missing is "single".
*/
'audit_papertrail' => [
'driver' => 'monolog',
'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'),
'handler' => SyslogUdpHandler::class,
'tap' => [AuditLogger::class],
'handler_with' => [
'host' => env('PAPERTRAIL_HOST'),
'port' => env('PAPERTRAIL_PORT'),
],
],
'audit_stdout' => [
'driver' => 'single',
'path' => 'php://stdout',
'tap' => [AuditLogger::class],
'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'),
],
'audit_daily' => [
'driver' => 'daily',
'path' => storage_path('logs/ff3-audit.log'),
'tap' => [AuditLogger::class],
'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'),
'days' => 90,
],
'audit_stdout' => [
'driver' => 'single',
'path' => 'php://stdout',
'audit_syslog' => [
'driver' => 'syslog',
'tap' => [AuditLogger::class],
'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'),
],
'audit_errorlog' => [
'driver' => 'errorlog',
'tap' => [AuditLogger::class],
'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'),
],
// syslog destination
'syslog' => [
'driver' => 'syslog',
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
],
// errorlog destination
'errorlog' => [
'driver' => 'errorlog',
'level' => envNonEmpty('APP_LOG_LEVEL', 'info'),
],
],
];

View File

@@ -105,9 +105,9 @@ export default {
"rule_trigger_destination_account_nr_contains_choice": "El n\u00famero \/ IBAN del compte de dest\u00ed cont\u00e9..",
"rule_trigger_transaction_type_choice": "La transacci\u00f3 \u00e9s del tipus..",
"rule_trigger_category_is_choice": "La categoria \u00e9s..",
"rule_trigger_amount_less_choice": "Amount is less than or equal to ..",
"rule_trigger_amount_less_choice": "La quantitat \u00e9s menor o igual a ..",
"rule_trigger_amount_is_choice": "La quantitat \u00e9s..",
"rule_trigger_amount_more_choice": "Amount is more than or equal to..",
"rule_trigger_amount_more_choice": "La quantitat \u00e9s major o igual a..",
"rule_trigger_description_starts_choice": "La descripci\u00f3 comen\u00e7a per..",
"rule_trigger_description_ends_choice": "La descripci\u00f3 acaba amb..",
"rule_trigger_description_contains_choice": "La descripci\u00f3 cont\u00e9..",
@@ -140,7 +140,7 @@ export default {
"rule_trigger_external_id_is_choice": "L'ID externa \u00e9s..",
"rule_trigger_internal_reference_is_choice": "La refer\u00e8ncia interna \u00e9s..",
"rule_trigger_journal_id_choice": "L'ID del llibre de transaccions \u00e9s..",
"rule_trigger_any_external_url_choice": "Transaction has an (any) external URL",
"rule_trigger_any_external_url_choice": "La transaci\u00f3 t\u00e9 (cap) URL externa",
"rule_trigger_no_external_url_choice": "La transacci\u00f3 no t\u00e9 URL extern",
"rule_trigger_id_choice": "L'ID de la transacci\u00f3 \u00e9s..",
"rule_action_delete_transaction_choice": "ELIMINAR transacci\u00f3(!)",

View File

@@ -105,9 +105,9 @@ export default {
"rule_trigger_destination_account_nr_contains_choice": "\ub300\uc0c1 \uacc4\uc88c \ubc88\ud638 \/ IBAN\uc740...\ub97c \ud3ec\ud568\ud569\ub2c8\ub2e4",
"rule_trigger_transaction_type_choice": "\uac70\ub798\ub294 .. \uc720\ud615\uc785\ub2c8\ub2e4",
"rule_trigger_category_is_choice": "\uce74\ud14c\uace0\ub9ac\ub294 ..",
"rule_trigger_amount_less_choice": "Amount is less than or equal to ..",
"rule_trigger_amount_less_choice": "\uae08\uc561\uc774 .. \uc640 \uc791\uac70\ub098 \uac19\uc74c",
"rule_trigger_amount_is_choice": "\uae08\uc561\uc740..",
"rule_trigger_amount_more_choice": "Amount is more than or equal to..",
"rule_trigger_amount_more_choice": "\uae08\uc561\uc774 .. \uc640 \ud06c\uac70\ub098 \uac19\uc74c",
"rule_trigger_description_starts_choice": "\uc124\uba85\uc774 ..\ub85c \uc2dc\uc791\ud569\ub2c8\ub2e4",
"rule_trigger_description_ends_choice": "\uc124\uba85\uc774 ..\ub85c \ub05d\ub0a9\ub2c8\ub2e4",
"rule_trigger_description_contains_choice": "\uc124\uba85\uc740 ..\ub97c \ud3ec\ud568\ud569\ub2c8\ub2e4",
@@ -140,7 +140,7 @@ export default {
"rule_trigger_external_id_is_choice": "\uc678\ubd80 ID\ub294..",
"rule_trigger_internal_reference_is_choice": "\ub0b4\ubd80 \ucc38\uc870\ub294..",
"rule_trigger_journal_id_choice": "\uac70\ub798 \uc800\ub110 ID\ub294..",
"rule_trigger_any_external_url_choice": "Transaction has an (any) external URL",
"rule_trigger_any_external_url_choice": "\uac70\ub798\uc5d0 (\uc5b4\ub5a4) \uc678\ubd80 URL\uc774 \uc788\uc74c",
"rule_trigger_no_external_url_choice": "\uac70\ub798\uc5d0 \uc678\ubd80 URL\uc774 \uc5c6\uc2b5\ub2c8\ub2e4",
"rule_trigger_id_choice": "\uac70\ub798 ID\ub294..",
"rule_action_delete_transaction_choice": "\uac70\ub798 \uc0ad\uc81c(!)",

View File

@@ -105,9 +105,9 @@ export default {
"rule_trigger_destination_account_nr_contains_choice": "Numer konta docelowego \/ IBAN zawiera..",
"rule_trigger_transaction_type_choice": "Transakcja jest typu..",
"rule_trigger_category_is_choice": "Kategoria to..",
"rule_trigger_amount_less_choice": "Amount is less than or equal to ..",
"rule_trigger_amount_less_choice": "Kwota jest mniejsza lub r\u00f3wna ..",
"rule_trigger_amount_is_choice": "Kwota to..",
"rule_trigger_amount_more_choice": "Amount is more than or equal to..",
"rule_trigger_amount_more_choice": "Kwota jest wi\u0119ksza lub r\u00f3wna..",
"rule_trigger_description_starts_choice": "Opis zaczyna si\u0119 od..",
"rule_trigger_description_ends_choice": "Opis ko\u0144czy si\u0119 na..",
"rule_trigger_description_contains_choice": "Opis zawiera..",
@@ -140,7 +140,7 @@ export default {
"rule_trigger_external_id_is_choice": "Zewn\u0119trzne ID to..",
"rule_trigger_internal_reference_is_choice": "Wewn\u0119trzne odwo\u0142anie to..",
"rule_trigger_journal_id_choice": "ID dziennika transakcji to..",
"rule_trigger_any_external_url_choice": "Transaction has an (any) external URL",
"rule_trigger_any_external_url_choice": "Transakcja ma (dowolny) zewn\u0119trzny adres URL",
"rule_trigger_no_external_url_choice": "Transakcja nie ma zewn\u0119trznego adresu URL",
"rule_trigger_id_choice": "Identyfikator transakcji to..",
"rule_action_delete_transaction_choice": "USU\u0143 transakcj\u0119(!)",

View File

@@ -105,9 +105,9 @@ export default {
"rule_trigger_destination_account_nr_contains_choice": "N\u00famero da conta de destino (IBAN) cont\u00e9m..",
"rule_trigger_transaction_type_choice": "Transa\u00e7\u00e3o \u00e9 do tipo..",
"rule_trigger_category_is_choice": "A categoria \u00e9..",
"rule_trigger_amount_less_choice": "Amount is less than or equal to ..",
"rule_trigger_amount_less_choice": "Valor \u00e9 menor ou igual a ..",
"rule_trigger_amount_is_choice": "Quantia \u00e9..",
"rule_trigger_amount_more_choice": "Amount is more than or equal to..",
"rule_trigger_amount_more_choice": "Valor \u00e9 maior ou igual a..",
"rule_trigger_description_starts_choice": "Descri\u00e7\u00e3o come\u00e7a com..",
"rule_trigger_description_ends_choice": "Descri\u00e7\u00e3o termina com..",
"rule_trigger_description_contains_choice": "Descri\u00e7\u00e3o cont\u00e9m..",
@@ -140,7 +140,7 @@ export default {
"rule_trigger_external_id_is_choice": "ID externo \u00e9..",
"rule_trigger_internal_reference_is_choice": "Refer\u00eancia interna \u00e9..",
"rule_trigger_journal_id_choice": "ID do livro de transa\u00e7\u00e3o \u00e9..",
"rule_trigger_any_external_url_choice": "Transaction has an (any) external URL",
"rule_trigger_any_external_url_choice": "A transa\u00e7\u00e3o tem uma URL externa (qualquer)",
"rule_trigger_no_external_url_choice": "A transa\u00e7\u00e3o n\u00e3o tem um link externo",
"rule_trigger_id_choice": "O identificador da transa\u00e7\u00e3o \u00e9..",
"rule_action_delete_transaction_choice": "EXCLUIR transa\u00e7\u00e3o(!)",

View File

@@ -50,8 +50,8 @@ export default {
"transactions": "Transakcije",
"title_expenses": "Stro\u0161ki",
"title_withdrawal": "Stro\u0161ki",
"title_revenue": "Dohodki \/ prihodki",
"title_deposit": "Dohodki \/ prihodki",
"title_revenue": "Dohodki prihodki",
"title_deposit": "Dohodki\/prihodki",
"title_transfer": "Prenosi",
"title_transfers": "Prenosi",
"asset_accounts": "Premo\u017eenjski ra\u010duni",
@@ -60,7 +60,7 @@ export default {
"liabilities_accounts": "Obveznosti"
},
"firefly": {
"administration_index": "Financial administration",
"administration_index": "Finan\u010dna administracija",
"actions": "Dejanja",
"edit": "uredi",
"delete": "izbri\u0161i",
@@ -81,87 +81,87 @@ export default {
"budgeted": "Prora\u010dun",
"spent": "Porabljeno",
"no_bill": "(ni ra\u010duna)",
"rule_trigger_source_account_starts_choice": "Source account name starts with..",
"rule_trigger_source_account_ends_choice": "Source account name ends with..",
"rule_trigger_source_account_is_choice": "Source account name is..",
"rule_trigger_source_account_contains_choice": "Source account name contains..",
"rule_trigger_account_id_choice": "Either account ID is exactly..",
"rule_trigger_source_account_id_choice": "Source account ID is exactly..",
"rule_trigger_destination_account_id_choice": "Destination account ID is exactly..",
"rule_trigger_account_is_cash_choice": "Either account is cash",
"rule_trigger_source_is_cash_choice": "Source account is (cash) account",
"rule_trigger_destination_is_cash_choice": "Destination account is (cash) account",
"rule_trigger_source_account_nr_starts_choice": "Source account number \/ IBAN starts with..",
"rule_trigger_source_account_nr_ends_choice": "Source account number \/ IBAN ends with..",
"rule_trigger_source_account_nr_is_choice": "Source account number \/ IBAN is..",
"rule_trigger_source_account_nr_contains_choice": "Source account number \/ IBAN contains..",
"rule_trigger_destination_account_starts_choice": "Destination account name starts with..",
"rule_trigger_destination_account_ends_choice": "Destination account name ends with..",
"rule_trigger_destination_account_is_choice": "Destination account name is..",
"rule_trigger_destination_account_contains_choice": "Destination account name contains..",
"rule_trigger_destination_account_nr_starts_choice": "Destination account number \/ IBAN starts with..",
"rule_trigger_destination_account_nr_ends_choice": "Destination account number \/ IBAN ends with..",
"rule_trigger_destination_account_nr_is_choice": "Destination account number \/ IBAN is..",
"rule_trigger_destination_account_nr_contains_choice": "Destination account number \/ IBAN contains..",
"rule_trigger_source_account_starts_choice": "Ime izvornega ra\u010duna se za\u010dne z ...",
"rule_trigger_source_account_ends_choice": "Ime izvornega ra\u010duna se kon\u010da s\/z ...",
"rule_trigger_source_account_is_choice": "Ime izvornega ra\u010duna je ...",
"rule_trigger_source_account_contains_choice": "Ime izvornega ra\u010duna vsebuje ...",
"rule_trigger_account_id_choice": "ID ra\u010duna je natan\u010dno ...",
"rule_trigger_source_account_id_choice": "ID izvornega ra\u010duna je to\u010dno ...",
"rule_trigger_destination_account_id_choice": "ID ciljnega ra\u010duna je to\u010dno ...",
"rule_trigger_account_is_cash_choice": "Kateri koli ra\u010dun je gotovina",
"rule_trigger_source_is_cash_choice": "Izvorni ra\u010dun je gotovinski ra\u010dun",
"rule_trigger_destination_is_cash_choice": "Ciljni ra\u010dun je (gotovinski) ra\u010dun",
"rule_trigger_source_account_nr_starts_choice": "Izvorna \u0161tevilka ra\u010duna \/ IBAN se za\u010dne z ...",
"rule_trigger_source_account_nr_ends_choice": "Izvorna \u0161tevilka ra\u010duna \/ IBAN se kon\u010da z ...",
"rule_trigger_source_account_nr_is_choice": "Izvorna \u0161tevilka ra\u010duna \/ IBAN je ...",
"rule_trigger_source_account_nr_contains_choice": "Izvorna \u0161tevilka ra\u010duna \/ IBAN vsebuje ...",
"rule_trigger_destination_account_starts_choice": "Ime ciljnega ra\u010duna se za\u010dne z ...",
"rule_trigger_destination_account_ends_choice": "Ime ciljnega ra\u010duna se kon\u010da z ...",
"rule_trigger_destination_account_is_choice": "Ime ciljnega ra\u010duna je ...",
"rule_trigger_destination_account_contains_choice": "Ime ciljnega ra\u010duna vsebuje ...",
"rule_trigger_destination_account_nr_starts_choice": "\u0160tevilka ciljnega ra\u010duna \/ IBAN se za\u010dne s\/z ...",
"rule_trigger_destination_account_nr_ends_choice": "\u0160tevilka ciljnega ra\u010duna \/ IBAN se kon\u010da s\/z ...",
"rule_trigger_destination_account_nr_is_choice": "\u0160tevilka ciljnega ra\u010duna \/ IBAN je ...",
"rule_trigger_destination_account_nr_contains_choice": "\u0160tevilka ciljnega ra\u010duna \/ IBAN vsebuje ...",
"rule_trigger_transaction_type_choice": "Tip transakcije je..",
"rule_trigger_category_is_choice": "Kategorija je..",
"rule_trigger_amount_less_choice": "Amount is less than or equal to ..",
"rule_trigger_amount_less_choice": "Znesek je manj\u0161i ali enak ...",
"rule_trigger_amount_is_choice": "Znesek je..",
"rule_trigger_amount_more_choice": "Amount is more than or equal to..",
"rule_trigger_amount_more_choice": "Znesek je ve\u010dji ali enak ...",
"rule_trigger_description_starts_choice": "Opis se za\u010dne s\/z..",
"rule_trigger_description_ends_choice": "Opis se kon\u010da z..",
"rule_trigger_description_contains_choice": "Opis vsebuje..",
"rule_trigger_description_is_choice": "Opis je..",
"rule_trigger_date_on_choice": "Transaction date is..",
"rule_trigger_date_before_choice": "Transaction date is before..",
"rule_trigger_date_after_choice": "Transaction date is after..",
"rule_trigger_created_at_on_choice": "Transaction was made on..",
"rule_trigger_updated_at_on_choice": "Transaction was last edited on..",
"rule_trigger_date_on_choice": "Datum transakcije je ...",
"rule_trigger_date_before_choice": "Datum transakcije je pred ...",
"rule_trigger_date_after_choice": "Datum transakcije je po ...",
"rule_trigger_created_at_on_choice": "Transakcija je bila izvedena dne ...",
"rule_trigger_updated_at_on_choice": "Transakcija je bila nazadnje urejena ...",
"rule_trigger_budget_is_choice": "Prora\u010dun je..",
"rule_trigger_tag_is_choice": "Any tag is..",
"rule_trigger_tag_is_choice": "Vsaka oznaka je ...",
"rule_trigger_currency_is_choice": "Valuta transakcije je..",
"rule_trigger_foreign_currency_is_choice": "Transaction foreign currency is..",
"rule_trigger_foreign_currency_is_choice": "Tuja valuta transakcije je ...",
"rule_trigger_has_attachments_choice": "Ima vsaj toliko priponk",
"rule_trigger_has_no_category_choice": "Nima kategorije",
"rule_trigger_has_any_category_choice": "Ima kategorijo",
"rule_trigger_has_no_budget_choice": "Nima prora\u010duna",
"rule_trigger_has_any_budget_choice": "Ima (katerikoli) prora\u010dun",
"rule_trigger_has_no_bill_choice": "Nima ra\u010duna",
"rule_trigger_has_any_bill_choice": "Has a (any) bill",
"rule_trigger_has_any_bill_choice": "Ima (kateri koli) trajnik",
"rule_trigger_has_no_tag_choice": "Nima oznak",
"rule_trigger_has_any_tag_choice": "Ima eno ali ve\u010d oznak",
"rule_trigger_any_notes_choice": "Ima zaznamke",
"rule_trigger_no_notes_choice": "Nima zaznamkov",
"rule_trigger_notes_is_choice": "Opombe so..",
"rule_trigger_notes_contains_choice": "Notes contain..",
"rule_trigger_notes_starts_choice": "Notes start with..",
"rule_trigger_notes_ends_choice": "Notes end with..",
"rule_trigger_notes_contains_choice": "Opombe vsebujejo ...",
"rule_trigger_notes_starts_choice": "Opombe se za\u010dnejo s\/z ...",
"rule_trigger_notes_ends_choice": "Opombe se kon\u010dajo s\/z ...",
"rule_trigger_bill_is_choice": "Ra\u010dun je..",
"rule_trigger_external_id_is_choice": "External ID is..",
"rule_trigger_internal_reference_is_choice": "Internal reference is..",
"rule_trigger_journal_id_choice": "Transaction journal ID is..",
"rule_trigger_any_external_url_choice": "Transaction has an (any) external URL",
"rule_trigger_no_external_url_choice": "Transaction has no external URL",
"rule_trigger_id_choice": "Transaction ID is..",
"rule_action_delete_transaction_choice": "DELETE transaction(!)",
"rule_action_set_category_choice": "Set category to ..",
"rule_trigger_external_id_is_choice": "Zunanji ID je ...",
"rule_trigger_internal_reference_is_choice": "Notranja referenca je ..",
"rule_trigger_journal_id_choice": "ID dnevnika transakcij je ...",
"rule_trigger_any_external_url_choice": "Transakcija ima (kateri koli) zunanji URL",
"rule_trigger_no_external_url_choice": "Transakcija nima zunanjega URL-ja",
"rule_trigger_id_choice": "ID transakcije je ...",
"rule_action_delete_transaction_choice": "IZBRI\u0160ITE transakcijo (!)",
"rule_action_set_category_choice": "Nastavi kategorijo na ...",
"rule_action_clear_category_choice": "Po\u010disti kategorijo",
"rule_action_set_budget_choice": "Set budget to ..",
"rule_action_set_budget_choice": "Nastavi prora\u010dun na ...",
"rule_action_clear_budget_choice": "Po\u010disti prora\u010dun",
"rule_action_add_tag_choice": "Dodaj oznako ..",
"rule_action_remove_tag_choice": "Remove tag ..",
"rule_action_remove_tag_choice": "Odstrani oznako ...",
"rule_action_remove_all_tags_choice": "Odstrani vse oznake",
"rule_action_set_description_choice": "Set description to ..",
"rule_action_set_description_choice": "Nastavi opis na ...",
"rule_action_update_piggy_choice": "Add \/ remove transaction amount in piggy bank ..",
"rule_action_append_description_choice": "Append description with ..",
"rule_action_prepend_description_choice": "Prepend description with ..",
"rule_action_set_source_account_choice": "Set source account to ..",
"rule_action_set_destination_account_choice": "Set destination account to ..",
"rule_action_append_notes_choice": "Append notes with ..",
"rule_action_prepend_notes_choice": "Prepend notes with ..",
"rule_action_append_description_choice": "Za opis dodaj ...",
"rule_action_prepend_description_choice": "Pred opis dodaj ...",
"rule_action_set_source_account_choice": "Nastavi izvorni ra\u010dun na ...",
"rule_action_set_destination_account_choice": "Nastavi ciljni ra\u010dun na ...",
"rule_action_append_notes_choice": "Za opombo dodaj ...",
"rule_action_prepend_notes_choice": "Pred opombo dodaj ...",
"rule_action_clear_notes_choice": "Odstrani opombe",
"rule_action_set_notes_choice": "Set notes to ..",
"rule_action_link_to_bill_choice": "Link to a bill ..",
"rule_action_set_notes_choice": "Nastavi opombe na ...",
"rule_action_link_to_bill_choice": "Pove\u017ei s trajnikom ...",
"rule_action_convert_deposit_choice": "Pretvori transakcijo v polog",
"rule_action_convert_withdrawal_choice": "Pretvori transakcijo v odliv",
"rule_action_convert_transfer_choice": "Pretvori transakcijo v prenos",
@@ -185,7 +185,7 @@ export default {
"asset_accounts": "premo\u017eenjski ra\u010duni",
"expense_accounts": "Ra\u010duni stro\u0161kov",
"liabilities_accounts": "Obveznosti",
"undefined_accounts": "Accounts",
"undefined_accounts": "Ra\u010duni",
"name": "Ime",
"revenue_accounts": "Ra\u010dun prihodkov",
"description": "Opis",
@@ -213,13 +213,13 @@ export default {
"transactions": "Transakcije",
"balance": "Stanje",
"budgets": "Prora\u010duni",
"subscriptions": "Subscriptions",
"subscriptions": "Naro\u010dnine",
"welcome_back": "Kaj dogaja?",
"bills_to_pay": "Trajnik za pla\u010dilo",
"net_worth": "Neto vrednost",
"pref_last365": "Zadnje leto",
"pref_last90": "Last 90 days",
"pref_last30": "Last 30 days",
"pref_last90": "Zadnjih 90 dni",
"pref_last30": "Zadnjih 30 dni",
"pref_last7": "Zadnjih 7 dni",
"pref_YTD": "Leto do datuma",
"pref_QTD": "Quarter to date",

View File

@@ -338,7 +338,7 @@ page container: q-ma-xs (margin all, xs) AND q-mb-md to give the page content so
<q-footer bordered class="bg-grey-8 text-white">
<q-toolbar>
<div>
<small>Firefly III v v6.0.19 &copy; James Cole, AGPL-3.0-or-later.</small>
<small>Firefly III v v6.0.21 &copy; James Cole, AGPL-3.0-or-later.</small>
</div>
</q-toolbar>
</q-footer>

82
package-lock.json generated
View File

@@ -7,9 +7,10 @@
"dependencies": {
"@fortawesome/fontawesome-free": "^6.4.0",
"@popperjs/core": "^2.11.8",
"alpinejs": "^3.12.3",
"alpinejs": "^3.13.0",
"bootstrap": "^5.3.0",
"chart.js": "^4.3.3",
"bootstrap5-autocomplete": "^1.1.20",
"chart.js": "^4.4.0",
"chartjs-adapter-date-fns": "^3.0.0",
"chartjs-chart-sankey": "^0.12.0",
"date-fns": "^2.30.0",
@@ -17,17 +18,17 @@
"store": "^2.0.12"
},
"devDependencies": {
"axios": "^1.1.2",
"laravel-vite-plugin": "^0.7.5",
"sass": "^1.64.2",
"axios": "^1.5.0",
"laravel-vite-plugin": "^0.8.0",
"sass": "^1.66.1",
"vite": "^4.0.0",
"vite-plugin-manifest-sri": "^0.1.0"
}
},
"node_modules/@babel/runtime": {
"version": "7.22.10",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz",
"integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==",
"version": "7.22.11",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.11.tgz",
"integrity": "sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@@ -424,9 +425,9 @@
"integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA=="
},
"node_modules/alpinejs": {
"version": "3.12.3",
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.12.3.tgz",
"integrity": "sha512-fLz2dfYQ3xCk7Ip8LiIpV2W+9brUyex2TAE7Z0BCvZdUDklJE+n+a8gCgLWzfZ0GzZNZu7HUP8Z0z6Xbm6fsSA==",
"version": "3.13.0",
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.0.tgz",
"integrity": "sha512-7FYR1Yz3evIjlJD1mZ3SYWSw+jlOmQGeQ1QiSufSQ6J84XMQFkzxm6OobiZ928SfqhGdoIp2SsABNsS4rXMMJw==",
"dependencies": {
"@vue/reactivity": "~3.1.1"
}
@@ -451,9 +452,9 @@
"dev": true
},
"node_modules/axios": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz",
"integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==",
"dev": true,
"dependencies": {
"follow-redirects": "^1.15.0",
@@ -462,9 +463,9 @@
}
},
"node_modules/bignumber.js": {
"version": "9.1.1",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz",
"integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==",
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz",
"integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==",
"engines": {
"node": "*"
}
@@ -496,6 +497,11 @@
"@popperjs/core": "^2.11.8"
}
},
"node_modules/bootstrap5-autocomplete": {
"version": "1.1.20",
"resolved": "https://registry.npmjs.org/bootstrap5-autocomplete/-/bootstrap5-autocomplete-1.1.20.tgz",
"integrity": "sha512-lvX/Za+GnZ7fC1NqVXQr4DWA0eQMR+/uyFjTasdfNSwAMTFhBTIexCsEM+0pXiKdJJnZUXbfcxaNxW1I0rAwLw=="
},
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
@@ -509,9 +515,9 @@
}
},
"node_modules/chart.js": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.3.tgz",
"integrity": "sha512-aTk7pBw+x6sQYhon/NR3ikfUJuym/LdgpTlgZRe2PaEhjUMKBKyNaFCMVRAyTEWYFNO7qRu7iQVqOw/OqzxZxQ==",
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.0.tgz",
"integrity": "sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ==",
"dependencies": {
"@kurkle/color": "^0.3.0"
},
@@ -683,9 +689,9 @@
}
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"optional": true,
@@ -718,9 +724,9 @@
}
},
"node_modules/immutable": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.2.tgz",
"integrity": "sha512-oGXzbEDem9OOpDWZu88jGiYCvIsLHMvGw+8OXlpsvTFvIQplQbjg1B1cvKg8f7Hoch6+NGjpPsH1Fr+Mc2D1aA==",
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz",
"integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==",
"dev": true
},
"node_modules/is-binary-path": {
@@ -766,9 +772,9 @@
}
},
"node_modules/laravel-vite-plugin": {
"version": "0.7.8",
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-0.7.8.tgz",
"integrity": "sha512-HWYqpQYHR3kEQ1LsHX7gHJoNNf0bz5z5mDaHBLzS+PGLCTmYqlU5/SZyeEgObV7z7bC/cnStYcY9H1DI1D5Udg==",
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-0.8.0.tgz",
"integrity": "sha512-6VjLI+azBpeK6rWBiKcb/En5GnTdYpL0U4zS8gXYvb2/VSq4mlau5H3NWpSktUDBMM1b97LLgICx5zevi8IY0w==",
"dev": true,
"dependencies": {
"picocolors": "^1.0.0",
@@ -853,9 +859,9 @@
}
},
"node_modules/postcss": {
"version": "8.4.27",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz",
"integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==",
"version": "8.4.29",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.29.tgz",
"integrity": "sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==",
"dev": true,
"funding": [
{
@@ -904,9 +910,9 @@
"integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
},
"node_modules/rollup": {
"version": "3.28.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.0.tgz",
"integrity": "sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==",
"version": "3.28.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.1.tgz",
"integrity": "sha512-R9OMQmIHJm9znrU3m3cpE8uhN0fGdXiawME7aZIpQqvpS/85+Vt1Hq1/yVIcYfOmaQiHjvXkQAoJukvLpau6Yw==",
"dev": true,
"bin": {
"rollup": "dist/bin/rollup"
@@ -920,9 +926,9 @@
}
},
"node_modules/sass": {
"version": "1.65.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.65.1.tgz",
"integrity": "sha512-9DINwtHmA41SEd36eVPQ9BJKpn7eKDQmUHmpI0y5Zv2Rcorrh0zS+cFrt050hdNbmmCNKTW3hV5mWfuegNRsEA==",
"version": "1.66.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.66.1.tgz",
"integrity": "sha512-50c+zTsZOJVgFfTgwwEzkjA3/QACgdNsKueWPyAR0mRINIvLAStVQBbPg14iuqEQ74NPDbXzJARJ/O4SI1zftA==",
"dev": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",

View File

@@ -6,18 +6,19 @@
"build": "vite build"
},
"devDependencies": {
"axios": "^1.1.2",
"laravel-vite-plugin": "^0.7.5",
"sass": "^1.64.2",
"axios": "^1.5.0",
"laravel-vite-plugin": "^0.8.0",
"sass": "^1.66.1",
"vite": "^4.0.0",
"vite-plugin-manifest-sri": "^0.1.0"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.4.0",
"@popperjs/core": "^2.11.8",
"alpinejs": "^3.12.3",
"alpinejs": "^3.13.0",
"bootstrap": "^5.3.0",
"chart.js": "^4.3.3",
"bootstrap5-autocomplete": "^1.1.20",
"chart.js": "^4.4.0",
"chartjs-adapter-date-fns": "^3.0.0",
"chartjs-chart-sankey": "^0.12.0",
"date-fns": "^2.30.0",

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