mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-08-24 22:09:50 +00:00
Compare commits
76 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a59d7ccdc2 | ||
|
2c1ca428db | ||
|
224970f3bd | ||
|
742d934ddb | ||
|
1699513023 | ||
|
488a8a7e86 | ||
|
dd571d6221 | ||
|
4cc5128b4c | ||
|
2636a6557a | ||
|
0bf97ccf22 | ||
|
592fc71b4e | ||
|
0e7712d3b8 | ||
|
80f21d2a4f | ||
|
5513ec068e | ||
|
14a46a6197 | ||
|
b93ee5efd8 | ||
|
cdd4dc6065 | ||
|
0d8b2ae799 | ||
|
77dc79b638 | ||
|
f48723db40 | ||
|
ebf91078c5 | ||
|
90d0d85dd6 | ||
|
0c5b4f7f64 | ||
|
9c4bb08ed1 | ||
|
1d3bbde4b0 | ||
|
b6faee033d | ||
|
05e0f88d11 | ||
|
ae9a151140 | ||
|
da633e3c62 | ||
|
8cb384d3cf | ||
|
de2a34c3ec | ||
|
b7c65446a8 | ||
|
bc648b187c | ||
|
4de0828b5d | ||
|
b2364d26ec | ||
|
83d94cb792 | ||
|
66cc3f48bc | ||
|
63297c43b7 | ||
|
5b0637558f | ||
|
e9a8e104be | ||
|
0f524e7800 | ||
|
969e0bccc9 | ||
|
ba3e026927 | ||
|
0c6868d477 | ||
|
7f70cf47ec | ||
|
fa4492287d | ||
|
60809c688e | ||
|
2404f5299c | ||
|
21a394eaf5 | ||
|
419d7846c9 | ||
|
0827accc39 | ||
|
2e53f7d0b7 | ||
|
bdfcf8ec95 | ||
|
6a20170e00 | ||
|
0c974f1ff7 | ||
|
9c098d45c5 | ||
|
cfdf9aa8dc | ||
|
2ea74542e6 | ||
|
7fcaa2b5fb | ||
|
e9e905e495 | ||
|
f67ff98d78 | ||
|
e3c4dde4ff | ||
|
9787561000 | ||
|
cd041b4c75 | ||
|
60ee70c926 | ||
|
00de78b6f1 | ||
|
33a841b831 | ||
|
df66dcf102 | ||
|
086a7a0b1e | ||
|
ec0ba3d212 | ||
|
b0ab06b7eb | ||
|
965acd6d45 | ||
|
4d156870ef | ||
|
499720df46 | ||
|
610bc108e7 | ||
|
53f1b0218c |
338
.ci/php-cs-fixer/composer.lock
generated
338
.ci/php-cs-fixer/composer.lock
generated
@@ -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",
|
||||
|
32
.env.example
32
.env.example
@@ -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
|
||||
|
@@ -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) {
|
||||
|
@@ -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 {
|
||||
|
45
app/Api/V2/Controllers/Model/Transaction/StoreController.php
Normal file
45
app/Api/V2/Controllers/Model/Transaction/StoreController.php
Normal 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([]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -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)
|
||||
|
@@ -42,7 +42,7 @@ class BalanceChartRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'accounts' => $this->getAccountList(),
|
||||
'period' => $this->string('period'),
|
||||
'period' => $this->convertString('period'),
|
||||
];
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
52
app/Events/Model/Rule/RuleActionFailedOnArray.php
Normal file
52
app/Events/Model/Rule/RuleActionFailedOnArray.php
Normal 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;
|
||||
}
|
||||
}
|
53
app/Events/Model/Rule/RuleActionFailedOnObject.php
Normal file
53
app/Events/Model/Rule/RuleActionFailedOnObject.php
Normal 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;
|
||||
}
|
||||
}
|
@@ -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
|
||||
|
@@ -26,6 +26,7 @@ namespace FireflyIII\Factory;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class AccountMetaFactory
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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.');
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
95
app/Handlers/Events/Model/RuleHandler.php
Normal file
95
app/Handlers/Events/Model/RuleHandler.php
Normal 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));
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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'];
|
||||
|
@@ -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'];
|
||||
|
@@ -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'];
|
||||
|
@@ -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'];
|
||||
|
@@ -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'];
|
||||
|
@@ -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'];
|
||||
|
117
app/Notifications/User/RuleActionFailed.php
Normal file
117
app/Notifications/User/RuleActionFailed.php
Normal 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 [];
|
||||
}
|
||||
}
|
@@ -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'];
|
||||
|
@@ -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',
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -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.
|
||||
*
|
||||
|
@@ -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;
|
||||
|
@@ -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++;
|
||||
}
|
||||
|
40
app/Support/Notifications/UrlValidator.php
Normal file
40
app/Support/Notifications/UrlValidator.php
Normal 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/');
|
||||
}
|
||||
}
|
@@ -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,
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
|
@@ -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']));
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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'));
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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),
|
||||
};
|
||||
}
|
||||
|
25
changelog.md
25
changelog.md
@@ -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
|
||||
|
@@ -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
670
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
@@ -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'),
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
|
@@ -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(!)",
|
||||
|
@@ -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(!)",
|
||||
|
@@ -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(!)",
|
||||
|
@@ -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(!)",
|
||||
|
@@ -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",
|
||||
|
@@ -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 © James Cole, AGPL-3.0-or-later.</small>
|
||||
<small>Firefly III v v6.0.21 © James Cole, AGPL-3.0-or-later.</small>
|
||||
</div>
|
||||
</q-toolbar>
|
||||
</q-footer>
|
||||
|
82
package-lock.json
generated
82
package-lock.json
generated
@@ -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",
|
||||
|
11
package.json
11
package.json
@@ -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
Reference in New Issue
Block a user