mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-01-06 22:21:42 +00:00
Compare commits
97 Commits
develop-20
...
develop-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79fd43f32b | ||
|
|
7a7bd65a27 | ||
|
|
01a9ecccac | ||
|
|
c1b3c71090 | ||
|
|
323d04fe6c | ||
|
|
80c2f1ea3f | ||
|
|
784494871d | ||
|
|
8e93af5cc7 | ||
|
|
ebfdeeedaa | ||
|
|
1d02ed6a56 | ||
|
|
cca53cb0e8 | ||
|
|
ab33aee4b1 | ||
|
|
41d4fab071 | ||
|
|
f0a1913dc6 | ||
|
|
b956b463c2 | ||
|
|
43603c4990 | ||
|
|
196e738f60 | ||
|
|
59e2ea357a | ||
|
|
5e9d942069 | ||
|
|
53d5bedd85 | ||
|
|
49c68af07b | ||
|
|
c84c8e1aef | ||
|
|
a8d43d7174 | ||
|
|
1087278890 | ||
|
|
ae5912ab52 | ||
|
|
035bd96ae5 | ||
|
|
7283c616a0 | ||
|
|
5706666bb6 | ||
|
|
4607466fb6 | ||
|
|
34bcfcfe9b | ||
|
|
05986cb6a6 | ||
|
|
0c4ee9f043 | ||
|
|
ff222795cf | ||
|
|
e0c76695ee | ||
|
|
ae126e8322 | ||
|
|
8f9c35fbe8 | ||
|
|
84efd6e2ee | ||
|
|
b1fbe4e909 | ||
|
|
8576877072 | ||
|
|
c298aced01 | ||
|
|
ac61a78d8d | ||
|
|
fce90a94c4 | ||
|
|
023a4f178d | ||
|
|
ef254995ad | ||
|
|
faeb74634b | ||
|
|
b5baae373f | ||
|
|
63de711cda | ||
|
|
bd28d116cb | ||
|
|
7efc2861bc | ||
|
|
5c689a2ca2 | ||
|
|
d5d65df76f | ||
|
|
df7d4f700c | ||
|
|
efebe3cb41 | ||
|
|
2ba5b6ae49 | ||
|
|
31d93efab2 | ||
|
|
657b95485c | ||
|
|
3bfc12f93b | ||
|
|
ccfd2f2ac3 | ||
|
|
fb3fe0d87b | ||
|
|
c80c6d52fe | ||
|
|
0fb3c0c7bf | ||
|
|
43c625bee2 | ||
|
|
967a5dd256 | ||
|
|
3c9d1bcaa1 | ||
|
|
8cd2de14a9 | ||
|
|
7728a35e04 | ||
|
|
49000da123 | ||
|
|
32a8f89875 | ||
|
|
49e5a81bd3 | ||
|
|
a8efe86af0 | ||
|
|
4f07b089d2 | ||
|
|
e786bf47c2 | ||
|
|
be11778c53 | ||
|
|
3d7325424c | ||
|
|
f4ffed99ef | ||
|
|
52dfe9a738 | ||
|
|
a0bc8b2ba2 | ||
|
|
4ffca9e2ca | ||
|
|
a6afec9afa | ||
|
|
5d859222f8 | ||
|
|
0e3ba14666 | ||
|
|
860767fe5a | ||
|
|
91b0ad625c | ||
|
|
67bab2561a | ||
|
|
b7908ebcb4 | ||
|
|
a20601ea85 | ||
|
|
14622329a8 | ||
|
|
5577be7b08 | ||
|
|
e3bab9d7d8 | ||
|
|
e0512bee3d | ||
|
|
20827a5fd1 | ||
|
|
8819dac1e1 | ||
|
|
da0a07262c | ||
|
|
adbf785aba | ||
|
|
1fae39a49d | ||
|
|
659240a98b | ||
|
|
e9644c9679 |
@@ -19,26 +19,24 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use PhpCsFixer\Runner\Parallel\ParallelConfigFactory;
|
|
||||||
|
|
||||||
$current = __DIR__;
|
$current = __DIR__;
|
||||||
|
|
||||||
$paths = [
|
$paths = [
|
||||||
$current . '/../../app',
|
$current . '/../../app',
|
||||||
$current . '/../../config',
|
$current . '/../../config',
|
||||||
$current . '/../../database',
|
|
||||||
$current . '/../../routes',
|
$current . '/../../routes',
|
||||||
$current . '/../../tests',
|
$current . '/../../tests',
|
||||||
$current . '/../../resources/lang/en_US',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$finder = PhpCsFixer\Finder::create()
|
$finder = PhpCsFixer\Finder::create()
|
||||||
->in($paths);
|
->in($paths);
|
||||||
|
|
||||||
|
|
||||||
$config = new PhpCsFixer\Config();
|
$config = (new PhpCsFixer\Config())
|
||||||
$config->setParallelConfig(ParallelConfigFactory::detect());
|
->setParallelConfig(PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect())
|
||||||
|
;
|
||||||
return $config->setRules(
|
return $config->setRules(
|
||||||
|
|
||||||
[
|
[
|
||||||
// rule sets
|
// rule sets
|
||||||
'@PHP83Migration' => true,
|
'@PHP83Migration' => true,
|
||||||
@@ -53,9 +51,6 @@ return $config->setRules(
|
|||||||
'statement_indentation' => true,
|
'statement_indentation' => true,
|
||||||
'void_return' => true,
|
'void_return' => true,
|
||||||
|
|
||||||
// about importing statements
|
|
||||||
'global_namespace_import' => ['import_classes' => true, 'import_constants' => true, 'import_functions' => true],
|
|
||||||
|
|
||||||
// disabled rules
|
// disabled rules
|
||||||
'native_function_invocation' => false, // annoying
|
'native_function_invocation' => false, // annoying
|
||||||
'php_unit_data_provider_name' => false, // bloody annoying long test names
|
'php_unit_data_provider_name' => false, // bloody annoying long test names
|
||||||
@@ -64,9 +59,15 @@ return $config->setRules(
|
|||||||
'comment_to_phpdoc' => false, // breaks phpstan lines in combination with PHPStorm.
|
'comment_to_phpdoc' => false, // breaks phpstan lines in combination with PHPStorm.
|
||||||
'type_declaration_spaces' => false,
|
'type_declaration_spaces' => false,
|
||||||
'cast_spaces' => false,
|
'cast_spaces' => false,
|
||||||
'phpdoc_to_comment' => false, // do not overrule single line comment style, breaks phpstan.
|
|
||||||
|
// enabled rules
|
||||||
|
'global_namespace_import' => true, // matches with rector.
|
||||||
|
|
||||||
// complex rules
|
// complex rules
|
||||||
|
'phpdoc_to_comment' => ['ignored_tags' => ['var']],
|
||||||
|
'php_unit_test_case_static_method_calls' => [
|
||||||
|
'call_type' => 'this',
|
||||||
|
],
|
||||||
'array_syntax' => ['syntax' => 'short'],
|
'array_syntax' => ['syntax' => 'short'],
|
||||||
'binary_operator_spaces' => [
|
'binary_operator_spaces' => [
|
||||||
'default' => 'at_least_single_space',
|
'default' => 'at_least_single_space',
|
||||||
@@ -76,5 +77,7 @@ return $config->setRules(
|
|||||||
'??=' => 'align_single_space_minimal_by_scope',
|
'??=' => 'align_single_space_minimal_by_scope',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
])
|
]
|
||||||
|
|
||||||
|
)
|
||||||
->setFinder($finder);
|
->setFinder($finder);
|
||||||
|
|||||||
65
.ci/php-cs-fixer/composer.lock
generated
65
.ci/php-cs-fixer/composer.lock
generated
@@ -406,58 +406,59 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "friendsofphp/php-cs-fixer",
|
"name": "friendsofphp/php-cs-fixer",
|
||||||
"version": "v3.75.0",
|
"version": "v3.76.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||||
"reference": "399a128ff2fdaf4281e4e79b755693286cdf325c"
|
"reference": "0e3c484cef0ae9314b0f85986a36296087432c40"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/399a128ff2fdaf4281e4e79b755693286cdf325c",
|
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/0e3c484cef0ae9314b0f85986a36296087432c40",
|
||||||
"reference": "399a128ff2fdaf4281e4e79b755693286cdf325c",
|
"reference": "0e3c484cef0ae9314b0f85986a36296087432c40",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"clue/ndjson-react": "^1.0",
|
"clue/ndjson-react": "^1.0",
|
||||||
"composer/semver": "^3.4",
|
"composer/semver": "^3.4",
|
||||||
"composer/xdebug-handler": "^3.0.3",
|
"composer/xdebug-handler": "^3.0.5",
|
||||||
"ext-filter": "*",
|
"ext-filter": "*",
|
||||||
"ext-hash": "*",
|
"ext-hash": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-tokenizer": "*",
|
"ext-tokenizer": "*",
|
||||||
"fidry/cpu-core-counter": "^1.2",
|
"fidry/cpu-core-counter": "^1.2",
|
||||||
"php": "^7.4 || ^8.0",
|
"php": "^7.4 || ^8.0",
|
||||||
"react/child-process": "^0.6.5",
|
"react/child-process": "^0.6.6",
|
||||||
"react/event-loop": "^1.0",
|
"react/event-loop": "^1.0",
|
||||||
"react/promise": "^2.0 || ^3.0",
|
"react/promise": "^2.11 || ^3.0",
|
||||||
"react/socket": "^1.0",
|
"react/socket": "^1.0",
|
||||||
"react/stream": "^1.0",
|
"react/stream": "^1.0",
|
||||||
"sebastian/diff": "^4.0 || ^5.1 || ^6.0 || ^7.0",
|
"sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0",
|
||||||
"symfony/console": "^5.4 || ^6.4 || ^7.0",
|
"symfony/console": "^5.4.45 || ^6.4.13 || ^7.0",
|
||||||
"symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0",
|
"symfony/event-dispatcher": "^5.4.45 || ^6.4.13 || ^7.0",
|
||||||
"symfony/filesystem": "^5.4 || ^6.4 || ^7.0",
|
"symfony/filesystem": "^5.4.45 || ^6.4.13 || ^7.0",
|
||||||
"symfony/finder": "^5.4 || ^6.4 || ^7.0",
|
"symfony/finder": "^5.4.45 || ^6.4.17 || ^7.0",
|
||||||
"symfony/options-resolver": "^5.4 || ^6.4 || ^7.0",
|
"symfony/options-resolver": "^5.4.45 || ^6.4.16 || ^7.0",
|
||||||
"symfony/polyfill-mbstring": "^1.31",
|
"symfony/polyfill-mbstring": "^1.32",
|
||||||
"symfony/polyfill-php80": "^1.31",
|
"symfony/polyfill-php80": "^1.32",
|
||||||
"symfony/polyfill-php81": "^1.31",
|
"symfony/polyfill-php81": "^1.32",
|
||||||
"symfony/process": "^5.4 || ^6.4 || ^7.2",
|
"symfony/process": "^5.4.47 || ^6.4.20 || ^7.2",
|
||||||
"symfony/stopwatch": "^5.4 || ^6.4 || ^7.0"
|
"symfony/stopwatch": "^5.4.45 || ^6.4.19 || ^7.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"facile-it/paraunit": "^1.3.1 || ^2.6",
|
"facile-it/paraunit": "^1.3.1 || ^2.6",
|
||||||
"infection/infection": "^0.29.14",
|
"infection/infection": "^0.29.14",
|
||||||
"justinrainbow/json-schema": "^5.3 || ^6.2",
|
"justinrainbow/json-schema": "^5.3 || ^6.4",
|
||||||
"keradus/cli-executor": "^2.1",
|
"keradus/cli-executor": "^2.2",
|
||||||
"mikey179/vfsstream": "^1.6.12",
|
"mikey179/vfsstream": "^1.6.12",
|
||||||
"php-coveralls/php-coveralls": "^2.7",
|
"php-coveralls/php-coveralls": "^2.8",
|
||||||
"php-cs-fixer/accessible-object": "^1.1",
|
"php-cs-fixer/accessible-object": "^1.1",
|
||||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6",
|
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6",
|
||||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6",
|
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6",
|
||||||
"phpunit/phpunit": "^9.6.22 || ^10.5.45 || ^11.5.12",
|
"phpunit/phpunit": "^9.6.23 || ^10.5.47 || ^11.5.25",
|
||||||
"symfony/var-dumper": "^5.4.48 || ^6.4.18 || ^7.2.3",
|
"symfony/polyfill-php84": "^1.32",
|
||||||
"symfony/yaml": "^5.4.45 || ^6.4.18 || ^7.2.3"
|
"symfony/var-dumper": "^5.4.48 || ^6.4.23 || ^7.3.1",
|
||||||
|
"symfony/yaml": "^5.4.45 || ^6.4.23 || ^7.3.1"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-dom": "For handling output formats in XML",
|
"ext-dom": "For handling output formats in XML",
|
||||||
@@ -498,7 +499,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
||||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.75.0"
|
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.76.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -506,7 +507,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-03-31T18:40:42+00:00"
|
"time": "2025-06-30T14:15:06+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/container",
|
"name": "psr/container",
|
||||||
@@ -1256,16 +1257,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v7.3.0",
|
"version": "v7.3.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/console.git",
|
"url": "https://github.com/symfony/console.git",
|
||||||
"reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44"
|
"reference": "9e27aecde8f506ba0fd1d9989620c04a87697101"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44",
|
"url": "https://api.github.com/repos/symfony/console/zipball/9e27aecde8f506ba0fd1d9989620c04a87697101",
|
||||||
"reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44",
|
"reference": "9e27aecde8f506ba0fd1d9989620c04a87697101",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1330,7 +1331,7 @@
|
|||||||
"terminal"
|
"terminal"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/console/tree/v7.3.0"
|
"source": "https://github.com/symfony/console/tree/v7.3.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1346,7 +1347,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-05-24T10:34:04+00:00"
|
"time": "2025-06-27T19:55:54+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/deprecation-contracts",
|
"name": "symfony/deprecation-contracts",
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ composer update --quiet
|
|||||||
rm -f .php-cs-fixer.cache
|
rm -f .php-cs-fixer.cache
|
||||||
PHP_CS_FIXER_IGNORE_ENV=true ./vendor/bin/php-cs-fixer fix \
|
PHP_CS_FIXER_IGNORE_ENV=true ./vendor/bin/php-cs-fixer fix \
|
||||||
--config $SCRIPT_DIR/php-cs-fixer/.php-cs-fixer.php \
|
--config $SCRIPT_DIR/php-cs-fixer/.php-cs-fixer.php \
|
||||||
--format=txt -v \
|
--format=txt \
|
||||||
|
-v \
|
||||||
--allow-risky=yes
|
--allow-risky=yes
|
||||||
|
|
||||||
EXIT_CODE=$?
|
EXIT_CODE=$?
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
use Rector\Config\RectorConfig;
|
use Rector\Config\RectorConfig;
|
||||||
use Rector\EarlyReturn\Rector\If_\ChangeOrIfContinueToMultiContinueRector;
|
use Rector\EarlyReturn\Rector\If_\ChangeOrIfContinueToMultiContinueRector;
|
||||||
|
use Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector;
|
||||||
use Rector\Transform\Rector\String_\StringToClassConstantRector;
|
use Rector\Transform\Rector\String_\StringToClassConstantRector;
|
||||||
use RectorLaravel\Set\LaravelLevelSetList;
|
use RectorLaravel\Set\LaravelLevelSetList;
|
||||||
|
|
||||||
@@ -32,6 +33,7 @@ use RectorLaravel\Set\LaravelLevelSetList;
|
|||||||
return RectorConfig::configure()
|
return RectorConfig::configure()
|
||||||
->withSkip([
|
->withSkip([
|
||||||
ChangeOrIfContinueToMultiContinueRector::class,
|
ChangeOrIfContinueToMultiContinueRector::class,
|
||||||
|
AddParamBasedOnParentClassMethodRector::class,
|
||||||
StringToClassConstantRector::class => [
|
StringToClassConstantRector::class => [
|
||||||
__DIR__ . '/../app/Http/Controllers/Auth/LoginController.php',
|
__DIR__ . '/../app/Http/Controllers/Auth/LoginController.php',
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ FIREFLY_III_LAYOUT=v1
|
|||||||
# Which Query Parser implementation to use for the search engine and rules
|
# Which Query Parser implementation to use for the search engine and rules
|
||||||
# 'new' is experimental, 'legacy' is the classic one
|
# 'new' is experimental, 'legacy' is the classic one
|
||||||
#
|
#
|
||||||
QUERY_PARSER_IMPLEMENTATION=legacy
|
QUERY_PARSER_IMPLEMENTATION=new
|
||||||
|
|
||||||
#
|
#
|
||||||
# Please make sure this URL matches the external URL of your Firefly III installation.
|
# Please make sure this URL matches the external URL of your Firefly III installation.
|
||||||
|
|||||||
13
.github/ISSUE_TEMPLATE/bug.yml
vendored
13
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Bug Report
|
name: Bug report
|
||||||
description: Report a bug in Firefly III (or associated tools)
|
description: Report a bug in Firefly III (or associated tools)
|
||||||
body:
|
body:
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
@@ -12,7 +12,7 @@ body:
|
|||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
attributes:
|
attributes:
|
||||||
label: I've found a bug and checked that ...
|
label: I've found a bug and checked that ...
|
||||||
description: Make sure that your request fulfills all of the following requirements. If one requirement cannot be satisfied, explain in detail why.
|
description: Make sure that your request fulfills all of the following requirements. If one requirement cannot be satisfied, please explain why.
|
||||||
options:
|
options:
|
||||||
- label: ... [the documentation](https://docs.firefly-iii.org/) does not mention anything about my problem
|
- label: ... [the documentation](https://docs.firefly-iii.org/) does not mention anything about my problem
|
||||||
- label: ... there are no open or closed issues that are related to my problem
|
- label: ... there are no open or closed issues that are related to my problem
|
||||||
@@ -33,13 +33,6 @@ body:
|
|||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Expected behaviour
|
|
||||||
description: Please describe precisely what you'd expect to happen. Be specific.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Steps to reproduce
|
label: Steps to reproduce
|
||||||
@@ -54,4 +47,4 @@ body:
|
|||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Additional info
|
label: Additional info
|
||||||
description: Please provide any additional information that seem useful.
|
description: Please provide any additional information that seems useful.
|
||||||
|
|||||||
3
.github/ISSUE_TEMPLATE/config.yml
vendored
3
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -3,3 +3,6 @@ contact_links:
|
|||||||
- name: Ask a question
|
- name: Ask a question
|
||||||
url: https://github.com/firefly-iii/firefly-iii/discussions
|
url: https://github.com/firefly-iii/firefly-iii/discussions
|
||||||
about: Please ask and answer questions here.
|
about: Please ask and answer questions here.
|
||||||
|
- name: I need support!
|
||||||
|
url: https://github.com/firefly-iii/firefly-iii/discussions
|
||||||
|
about: I think I broke something...
|
||||||
|
|||||||
7
.github/ISSUE_TEMPLATE/fr.yml
vendored
7
.github/ISSUE_TEMPLATE/fr.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Feature Request
|
name: Feature request
|
||||||
description: Request a feature or enhancement in Firefly III (or associated tools)
|
description: Request a feature or enhancement in Firefly III (or associated tools)
|
||||||
body:
|
body:
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
@@ -31,11 +31,6 @@ body:
|
|||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: What are alternatives?
|
|
||||||
description: Please describe what alternatives currently exist.
|
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Additional context
|
label: Additional context
|
||||||
|
|||||||
28
.github/workflows/release.yml
vendored
28
.github/workflows/release.yml
vendored
@@ -259,6 +259,12 @@ jobs:
|
|||||||
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
|
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
|
||||||
echo "" >> output.txt
|
echo "" >> output.txt
|
||||||
echo ":warning: Please be careful with this pre-release, as it may not work as expected." >> output.txt
|
echo ":warning: Please be careful with this pre-release, as it may not work as expected." >> output.txt
|
||||||
|
|
||||||
|
# donations!
|
||||||
|
echo '' >> output.txt
|
||||||
|
echo '### Support Firefly III' >> output.txt
|
||||||
|
echo 'Did you know you can support the development of Firefly III? You can donate in many ways, like GitHub Sponsors or Patreon. For more information, please [follow this link](https://bit.ly/donate-to-Firefly-III) for more information.' >> output.txt
|
||||||
|
echo '' >> output.txt
|
||||||
fi
|
fi
|
||||||
# describe a branch release
|
# describe a branch release
|
||||||
if [[ "$version" == branch* ]]; then
|
if [[ "$version" == branch* ]]; then
|
||||||
@@ -279,16 +285,31 @@ jobs:
|
|||||||
if [[ "develop" != "$version" ]] && [[ "$version" != branch* ]] && [[ "$version" != *alpha* ]] && [[ "$version" != *beta* ]]; then
|
if [[ "develop" != "$version" ]] && [[ "$version" != branch* ]] && [[ "$version" != *alpha* ]] && [[ "$version" != *beta* ]]; then
|
||||||
echo 'Describe the latest release'
|
echo 'Describe the latest release'
|
||||||
sudo chown -R runner:docker output.txt
|
sudo chown -R runner:docker output.txt
|
||||||
|
|
||||||
|
# the changelog is in output.txt
|
||||||
|
mv output.txt output2.txt
|
||||||
|
|
||||||
touch output.txt
|
touch output.txt
|
||||||
echo '' >> output.txt
|
echo '' >> output.txt
|
||||||
echo "Welcome to release $version of Firefly III. It contains the the latest fixes, translations and features. Docker users can find this release under the \`latest\` tag." >> output.txt
|
echo "Welcome to release $version of Firefly III. It contains the the latest fixes, translations and features. Docker users can find this release under the \`latest\` tag." >> output.txt
|
||||||
echo '' >> output.txt
|
echo '' >> output.txt
|
||||||
|
|
||||||
|
# add changelog to file.
|
||||||
|
cat output2.txt >> output.txt
|
||||||
|
echo '' >> output.txt
|
||||||
|
rm -f output2.txt
|
||||||
|
|
||||||
echo '### Instructions' >> output.txt
|
echo '### Instructions' >> output.txt
|
||||||
echo '' >> output.txt
|
echo '' >> output.txt
|
||||||
echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
|
echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
|
||||||
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
|
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
|
||||||
echo "* The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
echo "* The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt
|
||||||
|
|
||||||
|
# donations!
|
||||||
|
echo '' >> output.txt
|
||||||
|
echo '### Support Firefly III' >> output.txt
|
||||||
|
echo 'Did you know you can support the development of Firefly III? You can donate in many ways, like GitHub Sponsors or Patreon. For more information, please [follow this link](https://bit.ly/donate-to-Firefly-III) for more information.' >> output.txt
|
||||||
|
echo '' >> output.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# describe alpha release
|
# describe alpha release
|
||||||
@@ -465,20 +486,27 @@ jobs:
|
|||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
run: |
|
run: |
|
||||||
# add zip file to release.
|
# add zip file to release.
|
||||||
|
echo "Upload $zipName to $releaseName"
|
||||||
gh release upload $releaseName $zipName
|
gh release upload $releaseName $zipName
|
||||||
|
echo "Upload $tarName to $releaseName"
|
||||||
gh release upload $releaseName $tarName
|
gh release upload $releaseName $tarName
|
||||||
|
|
||||||
# add sha256 sum to release
|
# add sha256 sum to release
|
||||||
|
echo "Upload $zipName.sha256 to $releaseName"
|
||||||
gh release upload $releaseName $zipName.sha256
|
gh release upload $releaseName $zipName.sha256
|
||||||
|
echo "Upload $tarName.sha256 to $releaseName"
|
||||||
gh release upload $releaseName $tarName.sha256
|
gh release upload $releaseName $tarName.sha256
|
||||||
|
|
||||||
# add signatures to release
|
# add signatures to release
|
||||||
|
echo "Upload $zipName.asc to $releaseName"
|
||||||
gh release upload $releaseName $zipName.asc
|
gh release upload $releaseName $zipName.asc
|
||||||
|
echo "Upload $tarName.asc to $releaseName"
|
||||||
gh release upload $releaseName $tarName.asc
|
gh release upload $releaseName $tarName.asc
|
||||||
|
|
||||||
# get current HEAD and add as file to the release
|
# get current HEAD and add as file to the release
|
||||||
HEAD=$(git rev-parse HEAD)
|
HEAD=$(git rev-parse HEAD)
|
||||||
echo $HEAD > HEAD.txt
|
echo $HEAD > HEAD.txt
|
||||||
|
echo "Upload HEAD.txt to $releaseName"
|
||||||
gh release upload $releaseName HEAD.txt
|
gh release upload $releaseName HEAD.txt
|
||||||
|
|
||||||
# remove all temporary files
|
# remove all temporary files
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
||||||
|
|
||||||
|
use Deprecated;
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
@@ -83,9 +84,8 @@ class CurrencyController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Documentation for this endpoint is at:
|
* Documentation for this endpoint is at:
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getCurrenciesCodeAC
|
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getCurrenciesCodeAC
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
|
#[Deprecated]
|
||||||
public function currenciesWithCode(AutocompleteRequest $request): JsonResponse
|
public function currenciesWithCode(AutocompleteRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getData();
|
$data = $request->getData();
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Controllers\Chart;
|
namespace FireflyIII\Api\V1\Controllers\Chart;
|
||||||
|
|
||||||
|
use FireflyIII\Exceptions\ValidationException;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
@@ -35,6 +36,7 @@ use FireflyIII\Models\Account;
|
|||||||
use FireflyIII\Models\Preference;
|
use FireflyIII\Models\Preference;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Support\Chart\ChartData;
|
use FireflyIII\Support\Chart\ChartData;
|
||||||
|
use FireflyIII\Support\Facades\Preferences;
|
||||||
use FireflyIII\Support\Facades\Steam;
|
use FireflyIII\Support\Facades\Steam;
|
||||||
use FireflyIII\Support\Http\Api\ApiSupport;
|
use FireflyIII\Support\Http\Api\ApiSupport;
|
||||||
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;
|
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;
|
||||||
@@ -139,7 +141,7 @@ class AccountController extends Controller
|
|||||||
* This endpoint is documented at:
|
* This endpoint is documented at:
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/charts/getChartAccountOverview
|
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/charts/getChartAccountOverview
|
||||||
*
|
*
|
||||||
* @throws FireflyException
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public function overview(DateRequest $request): JsonResponse
|
public function overview(DateRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -160,7 +162,7 @@ class AccountController extends Controller
|
|||||||
$defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
|
$defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
|
||||||
|
|
||||||
/** @var Preference $frontpage */
|
/** @var Preference $frontpage */
|
||||||
$frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
|
$frontpage = Preferences::get('frontpageAccounts', $defaultSet);
|
||||||
|
|
||||||
if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {
|
if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {
|
||||||
$frontpage->data = $defaultSet;
|
$frontpage->data = $defaultSet;
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ class BudgetController extends Controller
|
|||||||
*/
|
*/
|
||||||
private function budgetLimits(Budget $budget, Collection $limits): array
|
private function budgetLimits(Budget $budget, Collection $limits): array
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in budgetLimits(#%d)', $budget->id));
|
Log::debug(sprintf('Now in budgetLimits(#%d)', $budget->id));
|
||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
/** @var BudgetLimit $limit */
|
/** @var BudgetLimit $limit */
|
||||||
@@ -233,16 +233,11 @@ class BudgetController extends Controller
|
|||||||
$end->endOfDay();
|
$end->endOfDay();
|
||||||
$spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection([$budget]));
|
$spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection([$budget]));
|
||||||
$limitCurrencyId = $limit->transaction_currency_id;
|
$limitCurrencyId = $limit->transaction_currency_id;
|
||||||
$filtered = [];
|
|
||||||
|
|
||||||
/** @var array $entry */
|
/** @var array $entry */
|
||||||
foreach ($spent as $currencyId => $entry) {
|
// only spent the entry where the entry's currency matches the budget limit's currency
|
||||||
// only spent the entry where the entry's currency matches the budget limit's currency
|
// so $filtered will only have 1 or 0 entries
|
||||||
// so $filtered will only have 1 or 0 entries
|
$filtered = array_filter($spent, fn ($entry) => $entry['currency_id'] === $limitCurrencyId);
|
||||||
if ($entry['currency_id'] === $limitCurrencyId) {
|
|
||||||
$filtered[$currencyId] = $entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$result = $this->processExpenses($budget->id, $filtered, $limit->start_date, $end);
|
$result = $this->processExpenses($budget->id, $filtered, $limit->start_date, $end);
|
||||||
if (1 === count($result)) {
|
if (1 === count($result)) {
|
||||||
$compare = bccomp($limit->amount, (string) app('steam')->positive($result[$limitCurrencyId]['spent']));
|
$compare = bccomp($limit->amount, (string) app('steam')->positive($result[$limitCurrencyId]['spent']));
|
||||||
|
|||||||
@@ -127,7 +127,6 @@ abstract class Controller extends BaseController
|
|||||||
Log::error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $field));
|
Log::error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $field));
|
||||||
Log::error($e->getMessage());
|
Log::error($e->getMessage());
|
||||||
Log::error($e->getTraceAsString());
|
Log::error($e->getTraceAsString());
|
||||||
$value = null;
|
|
||||||
}
|
}
|
||||||
$obj = null;
|
$obj = null;
|
||||||
if (null !== $date) {
|
if (null !== $date) {
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class DestroyController extends Controller
|
|||||||
public function destroy(DestroyRequest $request): JsonResponse
|
public function destroy(DestroyRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$objects = $request->getObjects();
|
$objects = $request->getObjects();
|
||||||
$this->unused = $request->boolean('unused', false);
|
$this->unused = $request->boolean('unused');
|
||||||
|
|
||||||
$allExceptAssets = [AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::RECONCILIATION->value, AccountTypeEnum::REVENUE->value];
|
$allExceptAssets = [AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::RECONCILIATION->value, AccountTypeEnum::REVENUE->value];
|
||||||
$all = [AccountTypeEnum::ASSET->value, AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::RECONCILIATION->value];
|
$all = [AccountTypeEnum::ASSET->value, AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::RECONCILIATION->value];
|
||||||
@@ -176,14 +176,14 @@ class DestroyController extends Controller
|
|||||||
foreach ($collection as $account) {
|
foreach ($collection as $account) {
|
||||||
$count = $account->transactions()->count();
|
$count = $account->transactions()->count();
|
||||||
if (true === $this->unused && 0 === $count) {
|
if (true === $this->unused && 0 === $count) {
|
||||||
app('log')->info(sprintf('Deleted unused account #%d "%s"', $account->id, $account->name));
|
Log::info(sprintf('Deleted unused account #%d "%s"', $account->id, $account->name));
|
||||||
Log::channel('audit')->info(sprintf('Deleted unused account #%d "%s"', $account->id, $account->name));
|
Log::channel('audit')->info(sprintf('Deleted unused account #%d "%s"', $account->id, $account->name));
|
||||||
$service->destroy($account, null);
|
$service->destroy($account, null);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (false === $this->unused) {
|
if (false === $this->unused) {
|
||||||
app('log')->info(sprintf('Deleting account #%d "%s"', $account->id, $account->name));
|
Log::info(sprintf('Deleting account #%d "%s"', $account->id, $account->name));
|
||||||
Log::channel('audit')->warning(sprintf('Deleted account #%d "%s"', $account->id, $account->name));
|
Log::channel('audit')->warning(sprintf('Deleted account #%d "%s"', $account->id, $account->name));
|
||||||
$service->destroy($account, null);
|
$service->destroy($account, null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Data\Export\ExportRequest;
|
|||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Support\Export\ExportDataGenerator;
|
use FireflyIII\Support\Export\ExportDataGenerator;
|
||||||
use Illuminate\Http\Response as LaravelResponse;
|
use Illuminate\Http\Response as LaravelResponse;
|
||||||
|
use Safe\Exceptions\DatetimeException;
|
||||||
|
|
||||||
use function Safe\date;
|
use function Safe\date;
|
||||||
|
|
||||||
@@ -72,6 +73,7 @@ class ExportController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
|
* @throws DatetimeException
|
||||||
*/
|
*/
|
||||||
private function returnExport(string $key): LaravelResponse
|
private function returnExport(string $key): LaravelResponse
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
|||||||
use FireflyIII\Transformers\AccountTransformer;
|
use FireflyIII\Transformers\AccountTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,7 +68,7 @@ class UpdateController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function update(UpdateRequest $request, Account $account): JsonResponse
|
public function update(UpdateRequest $request, Account $account): JsonResponse
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||||
$data = $request->getUpdateData();
|
$data = $request->getUpdateData();
|
||||||
$data['type'] = config('firefly.shortNamesByFullName.'.$account->accountType->type);
|
$data['type'] = config('firefly.shortNamesByFullName.'.$account->accountType->type);
|
||||||
$account = $this->repository->update($account, $data);
|
$account = $this->repository->update($account, $data);
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ class StoreController extends Controller
|
|||||||
|
|
||||||
throw new NotFoundHttpException();
|
throw new NotFoundHttpException();
|
||||||
}
|
}
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$attachment = $this->repository->store($data);
|
$attachment = $this->repository->store($data);
|
||||||
$manager = $this->getManager();
|
$manager = $this->getManager();
|
||||||
@@ -109,13 +109,13 @@ class StoreController extends Controller
|
|||||||
$helper = app(AttachmentHelperInterface::class);
|
$helper = app(AttachmentHelperInterface::class);
|
||||||
$body = $request->getContent();
|
$body = $request->getContent();
|
||||||
if ('' === $body) {
|
if ('' === $body) {
|
||||||
app('log')->error('Body of attachment is empty.');
|
Log::error('Body of attachment is empty.');
|
||||||
|
|
||||||
return response()->json([], 422);
|
return response()->json([], 422);
|
||||||
}
|
}
|
||||||
$result = $helper->saveAttachmentFromApi($attachment, $body);
|
$result = $helper->saveAttachmentFromApi($attachment, $body);
|
||||||
if (false === $result) {
|
if (false === $result) {
|
||||||
app('log')->error('Could not save attachment from API.');
|
Log::error('Could not save attachment from API.');
|
||||||
|
|
||||||
return response()->json([], 422);
|
return response()->json([], 422);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ class StoreController extends Controller
|
|||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$data['start_date'] = $data['start'];
|
$data['start_date'] = $data['start'];
|
||||||
$data['end_date'] = $data['end'];
|
$data['end_date'] = $data['end'];
|
||||||
$data['notes'] = $data['notes'];
|
|
||||||
$data['budget_id'] = $budget->id;
|
$data['budget_id'] = $budget->id;
|
||||||
|
|
||||||
$budgetLimit = $this->blRepository->store($data);
|
$budgetLimit = $this->blRepository->store($data);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
|||||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepository;
|
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepository;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class DestroyController
|
* Class DestroyController
|
||||||
@@ -73,7 +74,7 @@ class DestroyController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function destroy(TransactionGroup $transactionGroup): JsonResponse
|
public function destroy(TransactionGroup $transactionGroup): JsonResponse
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||||
// grab asset account(s) from group:
|
// grab asset account(s) from group:
|
||||||
$accounts = [];
|
$accounts = [];
|
||||||
|
|
||||||
@@ -95,7 +96,7 @@ class DestroyController extends Controller
|
|||||||
|
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
app('log')->debug(sprintf('Now going to trigger updated account event for account #%d', $account->id));
|
Log::debug(sprintf('Now going to trigger updated account event for account #%d', $account->id));
|
||||||
event(new UpdatedAccount($account));
|
event(new UpdatedAccount($account));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class StoreController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function store(StoreRequest $request): JsonResponse
|
public function store(StoreRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
app('log')->debug('Now in API StoreController::store()');
|
Log::debug('Now in API StoreController::store()');
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$data['user'] = auth()->user();
|
$data['user'] = auth()->user();
|
||||||
$data['user_group'] = $this->userGroup;
|
$data['user_group'] = $this->userGroup;
|
||||||
@@ -95,13 +95,13 @@ class StoreController extends Controller
|
|||||||
try {
|
try {
|
||||||
$transactionGroup = $this->groupRepository->store($data);
|
$transactionGroup = $this->groupRepository->store($data);
|
||||||
} catch (DuplicateTransactionException $e) {
|
} catch (DuplicateTransactionException $e) {
|
||||||
app('log')->warning('Caught a duplicate transaction. Return error message.');
|
Log::warning('Caught a duplicate transaction. Return error message.');
|
||||||
$validator = Validator::make(['transactions' => [['description' => $e->getMessage()]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
|
$validator = Validator::make(['transactions' => [['description' => $e->getMessage()]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
|
||||||
|
|
||||||
throw new ValidationException($validator);
|
throw new ValidationException($validator);
|
||||||
} catch (FireflyException $e) {
|
} catch (FireflyException $e) {
|
||||||
app('log')->warning('Caught an exception. Return error message.');
|
Log::warning('Caught an exception. Return error message.');
|
||||||
app('log')->error($e->getMessage());
|
Log::error($e->getMessage());
|
||||||
$message = sprintf('Internal exception: %s', $e->getMessage());
|
$message = sprintf('Internal exception: %s', $e->getMessage());
|
||||||
$validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
|
$validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]);
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
|||||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ class UpdateController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
||||||
{
|
{
|
||||||
app('log')->debug('Now in update routine for transaction group');
|
Log::debug('Now in update routine for transaction group');
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$oldHash = $this->groupRepository->getCompareHash($transactionGroup);
|
$oldHash = $this->groupRepository->getCompareHash($transactionGroup);
|
||||||
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
|||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class DestroyController
|
* Class DestroyController
|
||||||
@@ -65,6 +66,7 @@ class DestroyController extends Controller
|
|||||||
* Remove the specified resource from storage.
|
* Remove the specified resource from storage.
|
||||||
*
|
*
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public function destroy(TransactionCurrency $currency): JsonResponse
|
public function destroy(TransactionCurrency $currency): JsonResponse
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -250,10 +250,8 @@ class ListController extends Controller
|
|||||||
$collection = $unfiltered->filter(
|
$collection = $unfiltered->filter(
|
||||||
static function (Recurrence $recurrence) use ($currency) { // @phpstan-ignore-line
|
static function (Recurrence $recurrence) use ($currency) { // @phpstan-ignore-line
|
||||||
/** @var RecurrenceTransaction $transaction */
|
/** @var RecurrenceTransaction $transaction */
|
||||||
foreach ($recurrence->recurrenceTransactions as $transaction) {
|
if (array_any($recurrence->recurrenceTransactions, fn ($transaction) => $transaction->transaction_currency_id === $currency->id || $transaction->foreign_currency_id === $currency->id)) {
|
||||||
if ($transaction->transaction_currency_id === $currency->id || $transaction->foreign_currency_id === $currency->id) {
|
return $recurrence;
|
||||||
return $recurrence;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -297,10 +295,8 @@ class ListController extends Controller
|
|||||||
$collection = $unfiltered->filter(
|
$collection = $unfiltered->filter(
|
||||||
static function (Rule $rule) use ($currency) { // @phpstan-ignore-line
|
static function (Rule $rule) use ($currency) { // @phpstan-ignore-line
|
||||||
/** @var RuleTrigger $trigger */
|
/** @var RuleTrigger $trigger */
|
||||||
foreach ($rule->ruleTriggers as $trigger) {
|
if (array_any($rule->ruleTriggers, fn ($trigger) => 'currency_is' === $trigger->trigger_type && $currency->name === $trigger->trigger_value)) {
|
||||||
if ('currency_is' === $trigger->trigger_type && $currency->name === $trigger->trigger_value) {
|
return $rule;
|
||||||
return $rule;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -27,13 +27,13 @@ namespace FireflyIII\Api\V1\Controllers\Models\TransactionLinkType;
|
|||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Models\TransactionLinkType\StoreRequest;
|
use FireflyIII\Api\V1\Requests\Models\TransactionLinkType\StoreRequest;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
|
||||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
use FireflyIII\Support\Http\Api\TransactionFilter;
|
use FireflyIII\Support\Http\Api\TransactionFilter;
|
||||||
use FireflyIII\Transformers\LinkTypeTransformer;
|
use FireflyIII\Transformers\LinkTypeTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +71,7 @@ class StoreController extends Controller
|
|||||||
*
|
*
|
||||||
* Store new object.
|
* Store new object.
|
||||||
*
|
*
|
||||||
* @throws FireflyException
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public function store(StoreRequest $request): JsonResponse
|
public function store(StoreRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ use FireflyIII\Support\Http\Api\TransactionFilter;
|
|||||||
use FireflyIII\Transformers\LinkTypeTransformer;
|
use FireflyIII\Transformers\LinkTypeTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,6 +74,7 @@ class UpdateController extends Controller
|
|||||||
* Update object.
|
* Update object.
|
||||||
*
|
*
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public function update(UpdateRequest $request, LinkType $linkType): JsonResponse
|
public function update(UpdateRequest $request, LinkType $linkType): JsonResponse
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ use FireflyIII\Models\UserGroup;
|
|||||||
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
|
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
|
||||||
use FireflyIII\Transformers\UserGroupTransformer;
|
use FireflyIII\Transformers\UserGroupTransformer;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class UpdateController extends Controller
|
class UpdateController extends Controller
|
||||||
{
|
{
|
||||||
@@ -54,7 +55,7 @@ class UpdateController extends Controller
|
|||||||
|
|
||||||
public function update(UpdateRequest $request, UserGroup $userGroup): JsonResponse
|
public function update(UpdateRequest $request, UserGroup $userGroup): JsonResponse
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||||
$data = $request->getData();
|
$data = $request->getData();
|
||||||
$userGroup = $this->repository->update($userGroup, $data);
|
$userGroup = $this->repository->update($userGroup, $data);
|
||||||
$userGroup->refresh();
|
$userGroup->refresh();
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ use Illuminate\Http\JsonResponse;
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||||
use League\Fractal\Resource\Collection as FractalCollection;
|
use League\Fractal\Resource\Collection as FractalCollection;
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ class AccountController extends Controller
|
|||||||
if ('' === $query || !in_array($field, $this->validFields, true)) {
|
if ('' === $query || !in_array($field, $this->validFields, true)) {
|
||||||
return response(null, 422);
|
return response(null, 422);
|
||||||
}
|
}
|
||||||
app('log')->debug(sprintf('Now in account search("%s", "%s")', $field, $query));
|
Log::debug(sprintf('Now in account search("%s", "%s")', $field, $query));
|
||||||
$types = $this->mapAccountTypes($type);
|
$types = $this->mapAccountTypes($type);
|
||||||
|
|
||||||
/** @var AccountSearch $search */
|
/** @var AccountSearch $search */
|
||||||
|
|||||||
@@ -130,8 +130,6 @@ class BasicController extends Controller
|
|||||||
$convertToNative = Amount::convertToNative();
|
$convertToNative = Amount::convertToNative();
|
||||||
$default = Amount::getNativeCurrency();
|
$default = Amount::getNativeCurrency();
|
||||||
// prep some arrays:
|
// prep some arrays:
|
||||||
$incomes = [];
|
|
||||||
$expenses = [];
|
|
||||||
$sums = [];
|
$sums = [];
|
||||||
$return = [];
|
$return = [];
|
||||||
$currencies = [
|
$currencies = [
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Controllers\System;
|
namespace FireflyIII\Api\V1\Controllers\System;
|
||||||
|
|
||||||
|
use FireflyIII\Support\Facades\FireflyConfig;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\System\UpdateRequest;
|
use FireflyIII\Api\V1\Requests\System\UpdateRequest;
|
||||||
@@ -31,6 +33,7 @@ use FireflyIII\Exceptions\FireflyException;
|
|||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
use FireflyIII\Support\Binder\EitherConfigKey;
|
use FireflyIII\Support\Binder\EitherConfigKey;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ConfigurationController
|
* Class ConfigurationController
|
||||||
@@ -65,8 +68,8 @@ class ConfigurationController extends Controller
|
|||||||
try {
|
try {
|
||||||
$dynamicData = $this->getDynamicConfiguration();
|
$dynamicData = $this->getDynamicConfiguration();
|
||||||
} catch (FireflyException $e) {
|
} catch (FireflyException $e) {
|
||||||
app('log')->error($e->getMessage());
|
Log::error($e->getMessage());
|
||||||
app('log')->error($e->getTraceAsString());
|
Log::error($e->getTraceAsString());
|
||||||
|
|
||||||
throw new FireflyException('200030: Could not load config variables.', 0, $e);
|
throw new FireflyException('200030: Could not load config variables.', 0, $e);
|
||||||
}
|
}
|
||||||
@@ -92,13 +95,15 @@ class ConfigurationController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all config values.
|
* Get all config values.
|
||||||
|
*
|
||||||
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
private function getDynamicConfiguration(): array
|
private function getDynamicConfiguration(): array
|
||||||
{
|
{
|
||||||
$isDemoSite = app('fireflyconfig')->get('is_demo_site');
|
$isDemoSite = FireflyConfig::get('is_demo_site');
|
||||||
$updateCheck = app('fireflyconfig')->get('permission_update_check');
|
$updateCheck = FireflyConfig::get('permission_update_check');
|
||||||
$lastCheck = app('fireflyconfig')->get('last_update_check');
|
$lastCheck = FireflyConfig::get('last_update_check');
|
||||||
$singleUser = app('fireflyconfig')->get('single_user_mode');
|
$singleUser = FireflyConfig::get('single_user_mode');
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'is_demo_site' => $isDemoSite?->data,
|
'is_demo_site' => $isDemoSite?->data,
|
||||||
@@ -153,6 +158,7 @@ class ConfigurationController extends Controller
|
|||||||
* Update the configuration.
|
* Update the configuration.
|
||||||
*
|
*
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public function update(UpdateRequest $request, string $name): JsonResponse
|
public function update(UpdateRequest $request, string $name): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -164,7 +170,7 @@ class ConfigurationController extends Controller
|
|||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$shortName = str_replace('configuration.', '', $name);
|
$shortName = str_replace('configuration.', '', $name);
|
||||||
|
|
||||||
app('fireflyconfig')->set($shortName, $data['value']);
|
FireflyConfig::set($shortName, $data['value']);
|
||||||
|
|
||||||
// get updated config:
|
// get updated config:
|
||||||
$newConfig = $this->getDynamicConfiguration();
|
$newConfig = $this->getDynamicConfiguration();
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
|||||||
use FireflyIII\Api\V1\Requests\System\CronRequest;
|
use FireflyIII\Api\V1\Requests\System\CronRequest;
|
||||||
use FireflyIII\Support\Http\Controllers\CronRunner;
|
use FireflyIII\Support\Http\Controllers\CronRunner;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CronController
|
* Class CronController
|
||||||
@@ -44,8 +45,8 @@ class CronController extends Controller
|
|||||||
{
|
{
|
||||||
$config = $request->getAll();
|
$config = $request->getAll();
|
||||||
|
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||||
app('log')->debug(sprintf('Date is %s', $config['date']->toIsoString()));
|
Log::debug(sprintf('Date is %s', $config['date']->toIsoString()));
|
||||||
$return = [];
|
$return = [];
|
||||||
$return['recurring_transactions'] = $this->runRecurring($config['force'], $config['date']);
|
$return['recurring_transactions'] = $this->runRecurring($config['force'], $config['date']);
|
||||||
$return['auto_budgets'] = $this->runAutoBudget($config['force'], $config['date']);
|
$return['auto_budgets'] = $this->runAutoBudget($config['force'], $config['date']);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ use FireflyIII\Transformers\UserTransformer;
|
|||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||||
use League\Fractal\Resource\Collection as FractalCollection;
|
use League\Fractal\Resource\Collection as FractalCollection;
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
@@ -174,7 +175,7 @@ class UserController extends Controller
|
|||||||
|
|
||||||
// can only update 'blocked' when user is admin.
|
// can only update 'blocked' when user is admin.
|
||||||
if (!$this->repository->hasRole(auth()->user(), 'owner')) {
|
if (!$this->repository->hasRole(auth()->user(), 'owner')) {
|
||||||
app('log')->debug('Quietly drop fields "blocked" and "blocked_code" from request.');
|
Log::debug('Quietly drop fields "blocked" and "blocked_code" from request.');
|
||||||
unset($data['blocked'], $data['blocked_code']);
|
unset($data['blocked'], $data['blocked_code']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ class ShowController extends Controller
|
|||||||
throw new NotFoundHttpException('Webhooks are not enabled.');
|
throw new NotFoundHttpException('Webhooks are not enabled.');
|
||||||
}
|
}
|
||||||
|
|
||||||
app('log')->debug(sprintf('Now in triggerTransaction(%d, %d)', $webhook->id, $group->id));
|
Log::debug(sprintf('Now in triggerTransaction(%d, %d)', $webhook->id, $group->id));
|
||||||
Log::channel('audit')->info(sprintf('User triggers webhook #%d on transaction group #%d.', $webhook->id, $group->id));
|
Log::channel('audit')->info(sprintf('User triggers webhook #%d on transaction group #%d.', $webhook->id, $group->id));
|
||||||
|
|
||||||
/** @var MessageGeneratorInterface $engine */
|
/** @var MessageGeneratorInterface $engine */
|
||||||
@@ -155,7 +155,7 @@ class ShowController extends Controller
|
|||||||
$engine->generateMessages();
|
$engine->generateMessages();
|
||||||
|
|
||||||
// trigger event to send them:
|
// trigger event to send them:
|
||||||
app('log')->debug('send event RequestedSendWebhookMessages');
|
Log::debug('send event RequestedSendWebhookMessages');
|
||||||
event(new RequestedSendWebhookMessages());
|
event(new RequestedSendWebhookMessages());
|
||||||
|
|
||||||
return response()->json([], 204);
|
return response()->json([], 204);
|
||||||
|
|||||||
@@ -76,6 +76,6 @@ class SubmitController extends Controller
|
|||||||
SendWebhookMessage::dispatch($message)->afterResponse();
|
SendWebhookMessage::dispatch($message)->afterResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json([]);
|
return response()->json();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ class TransactionRequest extends FormRequest
|
|||||||
'query' => json_decode($this->get('query'), true, 8, JSON_THROW_ON_ERROR),
|
'query' => json_decode($this->get('query'), true, 8, JSON_THROW_ON_ERROR),
|
||||||
];
|
];
|
||||||
} catch (JsonException $e) {
|
} catch (JsonException $e) {
|
||||||
// dont really care. the validation should catch invalid json.
|
// don't really care. the validation should catch invalid json.
|
||||||
app('log')->error($e->getMessage());
|
Log::error($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class StoreRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function getAll(): array
|
public function getAll(): array
|
||||||
{
|
{
|
||||||
app('log')->debug('Raw fields in Bill StoreRequest', $this->all());
|
Log::debug('Raw fields in Bill StoreRequest', $this->all());
|
||||||
$fields = [
|
$fields = [
|
||||||
'name' => ['name', 'convertString'],
|
'name' => ['name', 'convertString'],
|
||||||
'amount_min' => ['amount_min', 'convertString'],
|
'amount_min' => ['amount_min', 'convertString'],
|
||||||
@@ -128,7 +128,6 @@ class StoreRequest extends FormRequest
|
|||||||
$failed = $validator->fails();
|
$failed = $validator->fails();
|
||||||
} catch (TypeError $e) {
|
} catch (TypeError $e) {
|
||||||
Log::error($e->getMessage());
|
Log::error($e->getMessage());
|
||||||
$failed = false;
|
|
||||||
}
|
}
|
||||||
if ($failed) {
|
if ($failed) {
|
||||||
Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray());
|
Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray());
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class StoreRequest extends FormRequest
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
|
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
|
||||||
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
|
* standards, but it just has a lot of ??-statements because of the fields that may or may not exist.
|
||||||
*/
|
*/
|
||||||
private function getTransactionData(): array
|
private function getTransactionData(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ class UpdateRequest extends FormRequest
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
|
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
|
||||||
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
|
* standards, but it just has a lot of ??-statements because of the fields that may or may not exist.
|
||||||
*/
|
*/
|
||||||
private function getTransactionData(): array
|
private function getTransactionData(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class StoreRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function getAll(): array
|
public function getAll(): array
|
||||||
{
|
{
|
||||||
app('log')->debug('get all data in TransactionStoreRequest');
|
Log::debug('get all data in TransactionStoreRequest');
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'group_title' => $this->convertString('group_title'),
|
'group_title' => $this->convertString('group_title'),
|
||||||
@@ -175,7 +175,7 @@ class StoreRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
app('log')->debug('Collect rules of TransactionStoreRequest');
|
Log::debug('Collect rules of TransactionStoreRequest');
|
||||||
$validProtocols = config('firefly.valid_url_protocols');
|
$validProtocols = config('firefly.valid_url_protocols');
|
||||||
$locationRules = Location::requestRules([]);
|
$locationRules = Location::requestRules([]);
|
||||||
|
|
||||||
@@ -276,9 +276,9 @@ class StoreRequest extends FormRequest
|
|||||||
$this->validateTransactionArray($validator);
|
$this->validateTransactionArray($validator);
|
||||||
|
|
||||||
// must submit at least one transaction.
|
// must submit at least one transaction.
|
||||||
app('log')->debug('Now going to validateOneTransaction');
|
Log::debug('Now going to validateOneTransaction');
|
||||||
$this->validateOneTransaction($validator);
|
$this->validateOneTransaction($validator);
|
||||||
app('log')->debug('Now done with validateOneTransaction');
|
Log::debug('Now done with validateOneTransaction');
|
||||||
|
|
||||||
// all journals must have a description
|
// all journals must have a description
|
||||||
$this->validateDescriptions($validator);
|
$this->validateDescriptions($validator);
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ class UpdateRequest extends FormRequest
|
|||||||
foreach ($this->dateFields as $fieldName) {
|
foreach ($this->dateFields as $fieldName) {
|
||||||
app('log')->debug(sprintf('Now at date field %s', $fieldName));
|
app('log')->debug(sprintf('Now at date field %s', $fieldName));
|
||||||
if (array_key_exists($fieldName, $transaction)) {
|
if (array_key_exists($fieldName, $transaction)) {
|
||||||
app('log')->debug(sprintf('New value: "%s"', (string) $transaction[$fieldName]));
|
Log::debug(sprintf('New value: "%s"', $transaction[$fieldName]));
|
||||||
$current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
|
$current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Requests\Models\UserGroup;
|
namespace FireflyIII\Api\V1\Requests\Models\UserGroup;
|
||||||
|
|
||||||
use FireflyIII\Models\UserGroup;
|
|
||||||
use FireflyIII\Support\Request\ChecksLogin;
|
use FireflyIII\Support\Request\ChecksLogin;
|
||||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
@@ -53,9 +52,6 @@ class UpdateRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
/** @var UserGroup $userGroup */
|
|
||||||
$userGroup = $this->route()->parameter('userGroup');
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => ['required', 'min:1', 'max:255'],
|
'title' => ['required', 'min:1', 'max:255'],
|
||||||
'native_currency_id' => 'exists:transaction_currencies,id',
|
'native_currency_id' => 'exists:transaction_currencies,id',
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ use League\Fractal\Resource\Collection as FractalCollection;
|
|||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
use League\Fractal\Serializer\JsonApiSerializer;
|
use League\Fractal\Serializer\JsonApiSerializer;
|
||||||
use Psr\Container\ContainerExceptionInterface;
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
use Psr\Container\NotFoundExceptionInterface;
|
|
||||||
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
|
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
|
||||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||||
|
|
||||||
@@ -82,7 +81,7 @@ class Controller extends BaseController
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$page = (int) request()->get('page');
|
$page = (int) request()->get('page');
|
||||||
} catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) {
|
} catch (ContainerExceptionInterface) {
|
||||||
$page = 1;
|
$page = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class ListController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index(): JsonResponse
|
public function index(): JsonResponse
|
||||||
{
|
{
|
||||||
return response()->json([]);
|
return response()->json();
|
||||||
// throw new FireflyException('Needs refactoring, move to IndexController.');
|
// throw new FireflyException('Needs refactoring, move to IndexController.');
|
||||||
// $pageSize = $this->parameters->get('limit');
|
// $pageSize = $this->parameters->get('limit');
|
||||||
// $dates = $request->getAll();
|
// $dates = $request->getAll();
|
||||||
|
|||||||
@@ -65,29 +65,28 @@ class UpdateController extends Controller
|
|||||||
public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
||||||
{
|
{
|
||||||
app('log')->debug('Now in update routine for transaction group [v2]!');
|
app('log')->debug('Now in update routine for transaction group [v2]!');
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
||||||
$applyRules = $data['apply_rules'] ?? true;
|
$applyRules = $data['apply_rules'] ?? true;
|
||||||
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
||||||
$runRecalculations = true;
|
|
||||||
|
|
||||||
event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks, $runRecalculations));
|
event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks, true));
|
||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
|
|
||||||
/** @var User $admin */
|
/** @var User $admin */
|
||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
|
|
||||||
// use new group collector:
|
// use new group collector:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setUser($admin)->setTransactionGroup($transactionGroup);
|
$collector->setUser($admin)->setTransactionGroup($transactionGroup);
|
||||||
|
|
||||||
$selectedGroup = $collector->getGroups()->first();
|
$selectedGroup = $collector->getGroups()->first();
|
||||||
if (null === $selectedGroup) {
|
if (null === $selectedGroup) {
|
||||||
throw new FireflyException('200032: Cannot find transaction. Possibly, a rule deleted this transaction after its creation.');
|
throw new FireflyException('200032: Cannot find transaction. Possibly, a rule deleted this transaction after its creation.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$transformer = new TransactionGroupTransformer();
|
$transformer = new TransactionGroupTransformer();
|
||||||
$transformer->setParameters($this->parameters);
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
return response()->api($this->jsonApiObject('transactions', $selectedGroup, $transformer))->header('Content-Type', self::CONTENT_TYPE);
|
return response()->api($this->jsonApiObject('transactions', $selectedGroup, $transformer))->header('Content-Type', self::CONTENT_TYPE);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
|||||||
use FireflyIII\Transformers\CurrencyTransformer;
|
use FireflyIII\Transformers\CurrencyTransformer;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
class IndexController extends Controller
|
class IndexController extends Controller
|
||||||
{
|
{
|
||||||
@@ -56,6 +57,7 @@ class IndexController extends Controller
|
|||||||
public function index(IndexRequest $request): JsonResponse
|
public function index(IndexRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$settings = $request->getAll();
|
$settings = $request->getAll();
|
||||||
|
$currencies = new Collection();
|
||||||
if (true === $settings['enabled']) {
|
if (true === $settings['enabled']) {
|
||||||
$currencies = $this->repository->get();
|
$currencies = $this->repository->get();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ class UpdateRequest extends Request
|
|||||||
#[Override]
|
#[Override]
|
||||||
public function getAll(): array
|
public function getAll(): array
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||||
$this->integerFields = ['order', 'currency_id', 'foreign_currency_id', 'transaction_journal_id', 'source_id', 'destination_id', 'budget_id', 'category_id', 'bill_id', 'recurrence_id'];
|
$this->integerFields = ['order', 'currency_id', 'foreign_currency_id', 'transaction_journal_id', 'source_id', 'destination_id', 'budget_id', 'category_id', 'bill_id', 'recurrence_id'];
|
||||||
$this->dateFields = ['date', 'interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];
|
$this->dateFields = ['date', 'interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];
|
||||||
$this->textareaFields = ['notes'];
|
$this->textareaFields = ['notes'];
|
||||||
@@ -101,7 +101,7 @@ class UpdateRequest extends Request
|
|||||||
*/
|
*/
|
||||||
private function getTransactionData(): array
|
private function getTransactionData(): array
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||||
$return = [];
|
$return = [];
|
||||||
|
|
||||||
/** @var null|array $transactions */
|
/** @var null|array $transactions */
|
||||||
@@ -185,9 +185,9 @@ class UpdateRequest extends Request
|
|||||||
private function getDateData(array $current, array $transaction): array
|
private function getDateData(array $current, array $transaction): array
|
||||||
{
|
{
|
||||||
foreach ($this->dateFields as $fieldName) {
|
foreach ($this->dateFields as $fieldName) {
|
||||||
app('log')->debug(sprintf('Now at date field %s', $fieldName));
|
Log::debug(sprintf('Now at date field %s', $fieldName));
|
||||||
if (array_key_exists($fieldName, $transaction)) {
|
if (array_key_exists($fieldName, $transaction)) {
|
||||||
app('log')->debug(sprintf('New value: "%s"', (string) $transaction[$fieldName]));
|
Log::debug(sprintf('New value: "%s"', $transaction[$fieldName]));
|
||||||
$current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
|
$current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -252,7 +252,7 @@ class UpdateRequest extends Request
|
|||||||
#[Override]
|
#[Override]
|
||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in %s', __METHOD__));
|
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||||
$validProtocols = config('firefly.valid_url_protocols');
|
$validProtocols = config('firefly.valid_url_protocols');
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@@ -336,7 +336,7 @@ class UpdateRequest extends Request
|
|||||||
#[Override]
|
#[Override]
|
||||||
public function withValidator(Validator $validator): void
|
public function withValidator(Validator $validator): void
|
||||||
{
|
{
|
||||||
app('log')->debug('Now in withValidator');
|
Log::debug('Now in withValidator');
|
||||||
|
|
||||||
/** @var TransactionGroup $transactionGroup */
|
/** @var TransactionGroup $transactionGroup */
|
||||||
$transactionGroup = $this->route()->parameter('userGroupTransaction');
|
$transactionGroup = $this->route()->parameter('userGroupTransaction');
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ use FireflyIII\Enums\TransactionTypeEnum;
|
|||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Facades\Steam;
|
||||||
use FireflyIII\Support\Models\AccountBalanceCalculator;
|
use FireflyIII\Support\Models\AccountBalanceCalculator;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
@@ -140,6 +141,7 @@ class CorrectsUnevenAmount extends Command
|
|||||||
/** @var stdClass $entry */
|
/** @var stdClass $entry */
|
||||||
foreach ($journals as $entry) {
|
foreach ($journals as $entry) {
|
||||||
$sum = (string) $entry->the_sum;
|
$sum = (string) $entry->the_sum;
|
||||||
|
$sum = Steam::floatalize($sum);
|
||||||
if (!is_numeric($sum)
|
if (!is_numeric($sum)
|
||||||
|| '' === $sum // @phpstan-ignore-line
|
|| '' === $sum // @phpstan-ignore-line
|
||||||
|| str_contains($sum, 'e')
|
|| str_contains($sum, 'e')
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Console\Commands\Integrity;
|
|||||||
|
|
||||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Facades\Steam;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
@@ -60,6 +61,8 @@ class ReportsSums extends Command
|
|||||||
$foreign = (string) $user->transactions()->selectRaw('SUM(foreign_amount) as total')->value('total');
|
$foreign = (string) $user->transactions()->selectRaw('SUM(foreign_amount) as total')->value('total');
|
||||||
$sum = '' === $sum ? '0' : $sum;
|
$sum = '' === $sum ? '0' : $sum;
|
||||||
$foreign = '' === $foreign ? '0' : $foreign;
|
$foreign = '' === $foreign ? '0' : $foreign;
|
||||||
|
$sum = Steam::floatalize($sum);
|
||||||
|
$foreign = Steam::floatalize($foreign);
|
||||||
$total = bcadd($sum, $foreign);
|
$total = bcadd($sum, $foreign);
|
||||||
|
|
||||||
if (0 !== bccomp($total, '0')) {
|
if (0 !== bccomp($total, '0')) {
|
||||||
|
|||||||
@@ -87,6 +87,12 @@ class UpgradesMultiPiggyBanks extends Command
|
|||||||
|
|
||||||
private function upgradePiggyBank(PiggyBank $piggyBank): void
|
private function upgradePiggyBank(PiggyBank $piggyBank): void
|
||||||
{
|
{
|
||||||
|
if (null === $piggyBank->account) {
|
||||||
|
// #10432 account has been deleted, delete piggy bank.
|
||||||
|
$piggyBank->delete();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
$this->repository->setUser($piggyBank->account->user);
|
$this->repository->setUser($piggyBank->account->user);
|
||||||
$this->accountRepository->setUser($piggyBank->account->user);
|
$this->accountRepository->setUser($piggyBank->account->user);
|
||||||
$repetition = $this->repository->getRepetition($piggyBank, true);
|
$repetition = $this->repository->getRepetition($piggyBank, true);
|
||||||
|
|||||||
@@ -58,11 +58,13 @@ use function Safe\parse_url;
|
|||||||
*/
|
*/
|
||||||
class Handler extends ExceptionHandler
|
class Handler extends ExceptionHandler
|
||||||
{
|
{
|
||||||
|
public static ?Throwable $lastError = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<int, class-string<Throwable>>
|
* @var array<int, class-string<Throwable>>
|
||||||
*/
|
*/
|
||||||
protected $dontReport
|
protected $dontReport
|
||||||
= [
|
= [
|
||||||
AuthenticationException::class,
|
AuthenticationException::class,
|
||||||
LaravelValidationException::class,
|
LaravelValidationException::class,
|
||||||
NotFoundHttpException::class,
|
NotFoundHttpException::class,
|
||||||
@@ -123,7 +125,7 @@ class Handler extends ExceptionHandler
|
|||||||
// somehow Laravel handler does not catch this:
|
// somehow Laravel handler does not catch this:
|
||||||
app('log')->debug('Return JSON unauthenticated error.');
|
app('log')->debug('Return JSON unauthenticated error.');
|
||||||
|
|
||||||
return response()->json(['message' => 'Unauthenticated', 'exception' => 'AuthenticationException'], 401);
|
return response()->json(['message' => $e->getMessage(), 'exception' => 'AuthenticationException'], 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($e instanceof OAuthServerException && $expectsJson) {
|
if ($e instanceof OAuthServerException && $expectsJson) {
|
||||||
@@ -215,13 +217,14 @@ class Handler extends ExceptionHandler
|
|||||||
#[Override]
|
#[Override]
|
||||||
public function report(Throwable $e): void
|
public function report(Throwable $e): void
|
||||||
{
|
{
|
||||||
$doMailError = (bool) config('firefly.send_error_message');
|
self::$lastError = $e;
|
||||||
|
$doMailError = (bool) config('firefly.send_error_message');
|
||||||
if ($this->shouldntReportLocal($e) || !$doMailError) {
|
if ($this->shouldntReportLocal($e) || !$doMailError) {
|
||||||
parent::report($e);
|
parent::report($e);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$userData = [
|
$userData = [
|
||||||
'id' => 0,
|
'id' => 0,
|
||||||
'email' => 'unknown@example.com',
|
'email' => 'unknown@example.com',
|
||||||
];
|
];
|
||||||
@@ -230,9 +233,9 @@ class Handler extends ExceptionHandler
|
|||||||
$userData['email'] = auth()->user()->email;
|
$userData['email'] = auth()->user()->email;
|
||||||
}
|
}
|
||||||
|
|
||||||
$headers = request()->headers->all();
|
$headers = request()->headers->all();
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'class' => $e::class,
|
'class' => $e::class,
|
||||||
'errorMessage' => $e->getMessage(),
|
'errorMessage' => $e->getMessage(),
|
||||||
'time' => Carbon::now()->format('r'),
|
'time' => Carbon::now()->format('r'),
|
||||||
@@ -250,8 +253,8 @@ class Handler extends ExceptionHandler
|
|||||||
];
|
];
|
||||||
|
|
||||||
// create job that will mail.
|
// create job that will mail.
|
||||||
$ipAddress = request()->ip() ?? '0.0.0.0';
|
$ipAddress = request()->ip() ?? '0.0.0.0';
|
||||||
$job = new MailError($userData, (string) config('firefly.site_owner'), $ipAddress, $data);
|
$job = new MailError($userData, (string) config('firefly.site_owner'), $ipAddress, $data);
|
||||||
dispatch($job);
|
dispatch($job);
|
||||||
|
|
||||||
parent::report($e);
|
parent::report($e);
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ class PiggyBankFactory
|
|||||||
{
|
{
|
||||||
use CreatesObjectGroups;
|
use CreatesObjectGroups;
|
||||||
|
|
||||||
public User $user;
|
public User $user;
|
||||||
private AccountRepositoryInterface $accountRepository;
|
private AccountRepositoryInterface $accountRepository;
|
||||||
private CurrencyRepositoryInterface $currencyRepository;
|
private CurrencyRepositoryInterface $currencyRepository;
|
||||||
private PiggyBankRepositoryInterface $piggyBankRepository;
|
private PiggyBankRepositoryInterface $piggyBankRepository;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
@@ -78,7 +78,7 @@ class PiggyBankFactory
|
|||||||
unset($piggyBankData['object_group_title'], $piggyBankData['transaction_currency_code'], $piggyBankData['transaction_currency_id'], $piggyBankData['accounts'], $piggyBankData['object_group_id'], $piggyBankData['notes']);
|
unset($piggyBankData['object_group_title'], $piggyBankData['transaction_currency_code'], $piggyBankData['transaction_currency_id'], $piggyBankData['accounts'], $piggyBankData['object_group_id'], $piggyBankData['notes']);
|
||||||
|
|
||||||
// validate amount:
|
// validate amount:
|
||||||
if (array_key_exists('target_amount', $piggyBankData) && '' === (string) $piggyBankData['target_amount']) {
|
if (array_key_exists('target_amount', $piggyBankData) && '' === (string)$piggyBankData['target_amount']) {
|
||||||
$piggyBankData['target_amount'] = '0';
|
$piggyBankData['target_amount'] = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ class PiggyBankFactory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// try also with ID
|
// try also with ID
|
||||||
$objectGroupId = (int) ($data['object_group_id'] ?? 0);
|
$objectGroupId = (int)($data['object_group_id'] ?? 0);
|
||||||
if (0 !== $objectGroupId) {
|
if (0 !== $objectGroupId) {
|
||||||
$objectGroup = $this->findObjectGroupById($objectGroupId);
|
$objectGroup = $this->findObjectGroupById($objectGroupId);
|
||||||
if ($objectGroup instanceof ObjectGroup) {
|
if ($objectGroup instanceof ObjectGroup) {
|
||||||
@@ -129,10 +129,10 @@ class PiggyBankFactory
|
|||||||
$defaultCurrency = app('amount')->getNativeCurrency();
|
$defaultCurrency = app('amount')->getNativeCurrency();
|
||||||
$currency = null;
|
$currency = null;
|
||||||
if (array_key_exists('transaction_currency_code', $data)) {
|
if (array_key_exists('transaction_currency_code', $data)) {
|
||||||
$currency = $this->currencyRepository->findByCode((string) ($data['transaction_currency_code'] ?? ''));
|
$currency = $this->currencyRepository->findByCode((string)($data['transaction_currency_code'] ?? ''));
|
||||||
}
|
}
|
||||||
if (array_key_exists('transaction_currency_id', $data)) {
|
if (array_key_exists('transaction_currency_id', $data)) {
|
||||||
$currency = $this->currencyRepository->find((int) ($data['transaction_currency_id'] ?? 0));
|
$currency = $this->currencyRepository->find((int)($data['transaction_currency_id'] ?? 0));
|
||||||
}
|
}
|
||||||
$currency ??= $defaultCurrency;
|
$currency ??= $defaultCurrency;
|
||||||
|
|
||||||
@@ -141,8 +141,8 @@ class PiggyBankFactory
|
|||||||
|
|
||||||
public function find(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank
|
public function find(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank
|
||||||
{
|
{
|
||||||
$piggyBankId = (int) $piggyBankId;
|
$piggyBankId = (int)$piggyBankId;
|
||||||
$piggyBankName = (string) $piggyBankName;
|
$piggyBankName = (string)$piggyBankName;
|
||||||
if ('' === $piggyBankName && 0 === $piggyBankId) {
|
if ('' === $piggyBankName && 0 === $piggyBankId) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -221,7 +221,7 @@ class PiggyBankFactory
|
|||||||
|
|
||||||
private function getMaxOrder(): int
|
private function getMaxOrder(): int
|
||||||
{
|
{
|
||||||
return (int) $this->piggyBankRepository->getPiggyBanks()->max('order');
|
return (int)$this->piggyBankRepository->getPiggyBanks()->max('order');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,12 +230,13 @@ class PiggyBankFactory
|
|||||||
Log::debug(sprintf('Linking piggy bank #%d to %d accounts.', $piggyBank->id, count($accounts)), $accounts);
|
Log::debug(sprintf('Linking piggy bank #%d to %d accounts.', $piggyBank->id, count($accounts)), $accounts);
|
||||||
// collect current current_amount so the sync does not remove them.
|
// collect current current_amount so the sync does not remove them.
|
||||||
// TODO this is a tedious check. Feels like a hack.
|
// TODO this is a tedious check. Feels like a hack.
|
||||||
$toBeLinked = [];
|
$toBeLinked = [];
|
||||||
|
$oldSavedAmount = $this->piggyBankRepository->getCurrentAmount($piggyBank);
|
||||||
foreach ($piggyBank->accounts as $account) {
|
foreach ($piggyBank->accounts as $account) {
|
||||||
Log::debug(sprintf('Checking account #%d', $account->id));
|
Log::debug(sprintf('Checking account #%d', $account->id));
|
||||||
foreach ($accounts as $info) {
|
foreach ($accounts as $info) {
|
||||||
Log::debug(sprintf(' Checking other account #%d', $info['account_id']));
|
Log::debug(sprintf(' Checking other account #%d', $info['account_id']));
|
||||||
if ((int) $account->id === (int) $info['account_id']) {
|
if ((int)$account->id === (int)$info['account_id']) {
|
||||||
$toBeLinked[$account->id] = ['current_amount' => $account->pivot->current_amount ?? '0'];
|
$toBeLinked[$account->id] = ['current_amount' => $account->pivot->current_amount ?? '0'];
|
||||||
Log::debug(sprintf('Prefilled for account #%d with amount %s', $account->id, $account->pivot->current_amount ?? '0'));
|
Log::debug(sprintf('Prefilled for account #%d with amount %s', $account->id, $account->pivot->current_amount ?? '0'));
|
||||||
}
|
}
|
||||||
@@ -244,9 +245,9 @@ class PiggyBankFactory
|
|||||||
|
|
||||||
/** @var array $info */
|
/** @var array $info */
|
||||||
foreach ($accounts as $info) {
|
foreach ($accounts as $info) {
|
||||||
$account = $this->accountRepository->find((int) ($info['account_id'] ?? 0));
|
$account = $this->accountRepository->find((int)($info['account_id'] ?? 0));
|
||||||
if (!$account instanceof Account) {
|
if (!$account instanceof Account) {
|
||||||
Log::debug(sprintf('Account #%d not found, skipping.', (int) ($info['account_id'] ?? 0)));
|
Log::debug(sprintf('Account #%d not found, skipping.', (int)($info['account_id'] ?? 0)));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -290,7 +291,16 @@ class PiggyBankFactory
|
|||||||
}
|
}
|
||||||
Log::debug(sprintf('Link information: %s', json_encode($toBeLinked)));
|
Log::debug(sprintf('Link information: %s', json_encode($toBeLinked)));
|
||||||
if (0 !== count($toBeLinked)) {
|
if (0 !== count($toBeLinked)) {
|
||||||
|
Log::debug('Syncing accounts to piggy bank.');
|
||||||
$piggyBank->accounts()->sync($toBeLinked);
|
$piggyBank->accounts()->sync($toBeLinked);
|
||||||
|
$piggyBank->refresh();
|
||||||
|
$newSavedAmount = $this->piggyBankRepository->getCurrentAmount($piggyBank);
|
||||||
|
Log::debug(sprintf('Old saved amount: %s, new saved amount is %s', $oldSavedAmount, $newSavedAmount));
|
||||||
|
if (0 !== bccomp($oldSavedAmount, $newSavedAmount)) {
|
||||||
|
Log::debug('Amount changed, will create event for it.');
|
||||||
|
// create event for difference.
|
||||||
|
event(new ChangedAmount($piggyBank, bcsub($newSavedAmount, $oldSavedAmount), null, null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (0 === count($toBeLinked)) {
|
if (0 === count($toBeLinked)) {
|
||||||
Log::warning('No accounts to link to piggy bank, will not change whatever is there now.');
|
Log::warning('No accounts to link to piggy bank, will not change whatever is there now.');
|
||||||
|
|||||||
@@ -32,11 +32,14 @@ use FireflyIII\Models\TransactionGroup;
|
|||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Models\Webhook;
|
use FireflyIII\Models\Webhook;
|
||||||
use FireflyIII\Models\WebhookMessage;
|
use FireflyIII\Models\WebhookMessage;
|
||||||
|
use FireflyIII\Support\Facades\Amount;
|
||||||
|
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||||
use FireflyIII\Transformers\AccountTransformer;
|
use FireflyIII\Transformers\AccountTransformer;
|
||||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Ramsey\Uuid\Uuid;
|
use Ramsey\Uuid\Uuid;
|
||||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||||
|
|
||||||
@@ -59,14 +62,14 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
|
|
||||||
public function generateMessages(): void
|
public function generateMessages(): void
|
||||||
{
|
{
|
||||||
app('log')->debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
// get the webhooks:
|
// get the webhooks:
|
||||||
if (0 === $this->webhooks->count()) {
|
if (0 === $this->webhooks->count()) {
|
||||||
$this->webhooks = $this->getWebhooks();
|
$this->webhooks = $this->getWebhooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
// do some debugging
|
// do some debugging
|
||||||
app('log')->debug(
|
Log::debug(
|
||||||
sprintf('StandardMessageGenerator will generate messages for %d object(s) and %d webhook(s).', $this->objects->count(), $this->webhooks->count())
|
sprintf('StandardMessageGenerator will generate messages for %d object(s) and %d webhook(s).', $this->objects->count(), $this->webhooks->count())
|
||||||
);
|
);
|
||||||
$this->run();
|
$this->run();
|
||||||
@@ -79,13 +82,13 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
|
|
||||||
private function run(): void
|
private function run(): void
|
||||||
{
|
{
|
||||||
app('log')->debug('Now in StandardMessageGenerator::run');
|
Log::debug('Now in StandardMessageGenerator::run');
|
||||||
|
|
||||||
/** @var Webhook $webhook */
|
/** @var Webhook $webhook */
|
||||||
foreach ($this->webhooks as $webhook) {
|
foreach ($this->webhooks as $webhook) {
|
||||||
$this->runWebhook($webhook);
|
$this->runWebhook($webhook);
|
||||||
}
|
}
|
||||||
app('log')->debug('Done with StandardMessageGenerator::run');
|
Log::debug('Done with StandardMessageGenerator::run');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -93,7 +96,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
*/
|
*/
|
||||||
private function runWebhook(Webhook $webhook): void
|
private function runWebhook(Webhook $webhook): void
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in runWebhook(#%d)', $webhook->id));
|
Log::debug(sprintf('Now in runWebhook(#%d)', $webhook->id));
|
||||||
|
|
||||||
/** @var Model $object */
|
/** @var Model $object */
|
||||||
foreach ($this->objects as $object) {
|
foreach ($this->objects as $object) {
|
||||||
@@ -108,7 +111,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
{
|
{
|
||||||
$class = $model::class;
|
$class = $model::class;
|
||||||
// Line is ignored because all of Firefly III's Models have an id property.
|
// Line is ignored because all of Firefly III's Models have an id property.
|
||||||
app('log')->debug(sprintf('Now in generateMessage(#%d, %s#%d)', $webhook->id, $class, $model->id));
|
Log::debug(sprintf('Now in generateMessage(#%d, %s#%d)', $webhook->id, $class, $model->id));
|
||||||
|
|
||||||
$uuid = Uuid::uuid4();
|
$uuid = Uuid::uuid4();
|
||||||
$basicMessage = [
|
$basicMessage = [
|
||||||
@@ -125,7 +128,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
switch ($class) {
|
switch ($class) {
|
||||||
default:
|
default:
|
||||||
// Line is ignored because all of Firefly III's Models have an id property.
|
// Line is ignored because all of Firefly III's Models have an id property.
|
||||||
app('log')->error(
|
Log::error(
|
||||||
sprintf('Webhook #%d was given %s#%d to deal with but can\'t extract user ID from it.', $webhook->id, $class, $model->id)
|
sprintf('Webhook #%d was given %s#%d to deal with but can\'t extract user ID from it.', $webhook->id, $class, $model->id)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -141,7 +144,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
// then depends on the response what to put in the message:
|
// then depends on the response what to put in the message:
|
||||||
switch ($webhook->response) {
|
switch ($webhook->response) {
|
||||||
default:
|
default:
|
||||||
app('log')->error(
|
Log::error(
|
||||||
sprintf('The response code for webhook #%d is "%d" and the message generator cant handle it. Soft fail.', $webhook->id, $webhook->response)
|
sprintf('The response code for webhook #%d is "%d" and the message generator cant handle it. Soft fail.', $webhook->id, $webhook->response)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -159,10 +162,10 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
try {
|
try {
|
||||||
$basicMessage['content'] = $transformer->transformObject($model);
|
$basicMessage['content'] = $transformer->transformObject($model);
|
||||||
} catch (FireflyException $e) {
|
} catch (FireflyException $e) {
|
||||||
app('log')->error(
|
Log::error(
|
||||||
sprintf('The transformer could not include the requested transaction group for webhook #%d: %s', $webhook->id, $e->getMessage())
|
sprintf('The transformer could not include the requested transaction group for webhook #%d: %s', $webhook->id, $e->getMessage())
|
||||||
);
|
);
|
||||||
app('log')->error($e->getTraceAsString());
|
Log::error($e->getTraceAsString());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -172,6 +175,10 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
case WebhookResponse::ACCOUNTS->value:
|
case WebhookResponse::ACCOUNTS->value:
|
||||||
/** @var TransactionGroup $model */
|
/** @var TransactionGroup $model */
|
||||||
$accounts = $this->collectAccounts($model);
|
$accounts = $this->collectAccounts($model);
|
||||||
|
$enrichment = new AccountEnrichment();
|
||||||
|
$enrichment->setUser($model->user);
|
||||||
|
$enrichment->setNative(Amount::getNativeCurrencyByUserGroup($model->userGroup));
|
||||||
|
$accounts = $enrichment->enrich($accounts);
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
$transformer = new AccountTransformer();
|
$transformer = new AccountTransformer();
|
||||||
$transformer->setParameters(new ParameterBag());
|
$transformer->setParameters(new ParameterBag());
|
||||||
@@ -210,7 +217,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
$webhookMessage->uuid = $message['uuid'];
|
$webhookMessage->uuid = $message['uuid'];
|
||||||
$webhookMessage->message = $message;
|
$webhookMessage->message = $message;
|
||||||
$webhookMessage->save();
|
$webhookMessage->save();
|
||||||
app('log')->debug(sprintf('Stored new webhook message #%d', $webhookMessage->id));
|
Log::debug(sprintf('Stored new webhook message #%d', $webhookMessage->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setObjects(Collection $objects): void
|
public function setObjects(Collection $objects): void
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Handlers\Events;
|
namespace FireflyIII\Handlers\Events;
|
||||||
|
|
||||||
|
use Deprecated;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Events\RequestedVersionCheckStatus;
|
use FireflyIII\Events\RequestedVersionCheckStatus;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
@@ -42,9 +43,8 @@ class VersionCheckEventHandler
|
|||||||
* Checks with GitHub to see if there is a new version.
|
* Checks with GitHub to see if there is a new version.
|
||||||
*
|
*
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*
|
|
||||||
* @deprecated ?
|
|
||||||
*/
|
*/
|
||||||
|
#[Deprecated(message: '?')]
|
||||||
public function checkForUpdates(RequestedVersionCheckStatus $event): void
|
public function checkForUpdates(RequestedVersionCheckStatus $event): void
|
||||||
{
|
{
|
||||||
Log::debug('Now in checkForUpdates()');
|
Log::debug('Now in checkForUpdates()');
|
||||||
|
|||||||
@@ -1094,6 +1094,10 @@ class GroupCollector implements GroupCollectorInterface
|
|||||||
->whereNull('transaction_groups.deleted_at')
|
->whereNull('transaction_groups.deleted_at')
|
||||||
->whereNull('transaction_journals.deleted_at')
|
->whereNull('transaction_journals.deleted_at')
|
||||||
->whereNull('source.deleted_at')
|
->whereNull('source.deleted_at')
|
||||||
|
|
||||||
|
// #10507 ignore opening balance.
|
||||||
|
->where('transaction_types.type', '!=', TransactionTypeEnum::OPENING_BALANCE->value)
|
||||||
|
|
||||||
->whereNotNull('transaction_groups.id')
|
->whereNotNull('transaction_groups.id')
|
||||||
->whereNull('destination.deleted_at')
|
->whereNull('destination.deleted_at')
|
||||||
->orderBy('transaction_journals.date', 'DESC')
|
->orderBy('transaction_journals.date', 'DESC')
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Helpers\Report;
|
namespace FireflyIII\Helpers\Report;
|
||||||
|
|
||||||
|
use Deprecated;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Enums\AccountTypeEnum;
|
use FireflyIII\Enums\AccountTypeEnum;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
@@ -81,7 +82,7 @@ class NetWorth implements NetWorthInterface
|
|||||||
|
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
Log::debug(sprintf('Now at account #%d ("%s")', $account->id, $account->name));
|
// Log::debug(sprintf('Now at account #%d ("%s")', $account->id, $account->name));
|
||||||
$currency = $this->accountRepository->getAccountCurrency($account) ?? $default;
|
$currency = $this->accountRepository->getAccountCurrency($account) ?? $default;
|
||||||
$useNative = $convertToNative && $default->id !== $currency->id;
|
$useNative = $convertToNative && $default->id !== $currency->id;
|
||||||
$currency = $useNative ? $default : $currency;
|
$currency = $useNative ? $default : $currency;
|
||||||
@@ -92,12 +93,12 @@ class NetWorth implements NetWorthInterface
|
|||||||
$balance = $balances[$account->id]['balance'] ?? '0';
|
$balance = $balances[$account->id]['balance'] ?? '0';
|
||||||
$nativeBalance = $balances[$account->id]['native_balance'] ?? '0';
|
$nativeBalance = $balances[$account->id]['native_balance'] ?? '0';
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('Balance is %s, native balance is %s', $balance, $nativeBalance));
|
// Log::debug(sprintf('Balance is %s, native balance is %s', $balance, $nativeBalance));
|
||||||
// always subtract virtual balance again.
|
// always subtract virtual balance again.
|
||||||
$balance = '' !== (string) $account->virtual_balance ? bcsub($balance, (string) $account->virtual_balance) : $balance;
|
$balance = '' !== (string) $account->virtual_balance ? bcsub($balance, (string) $account->virtual_balance) : $balance;
|
||||||
$nativeBalance = '' !== (string) $account->native_virtual_balance ? bcsub($nativeBalance, (string) $account->native_virtual_balance) : $nativeBalance;
|
$nativeBalance = '' !== (string) $account->native_virtual_balance ? bcsub($nativeBalance, (string) $account->native_virtual_balance) : $nativeBalance;
|
||||||
$amountToUse = $useNative ? $nativeBalance : $balance;
|
$amountToUse = $useNative ? $nativeBalance : $balance;
|
||||||
Log::debug(sprintf('Will use %s %s', $currencyCode, $amountToUse));
|
// Log::debug(sprintf('Will use %s %s', $currencyCode, $amountToUse));
|
||||||
|
|
||||||
$netWorth[$currencyCode] ??= [
|
$netWorth[$currencyCode] ??= [
|
||||||
'balance' => '0',
|
'balance' => '0',
|
||||||
@@ -134,9 +135,7 @@ class NetWorth implements NetWorthInterface
|
|||||||
$this->currencyRepos->setUserGroup($this->userGroup);
|
$this->currencyRepos->setUserGroup($this->userGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Deprecated]
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public function sumNetWorthByCurrency(Carbon $date): array
|
public function sumNetWorthByCurrency(Carbon $date): array
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Helpers\Report;
|
namespace FireflyIII\Helpers\Report;
|
||||||
|
|
||||||
|
use Deprecated;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Models\UserGroup;
|
use FireflyIII\Models\UserGroup;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
@@ -53,8 +54,7 @@ interface NetWorthInterface
|
|||||||
* TODO move to repository
|
* TODO move to repository
|
||||||
*
|
*
|
||||||
* Same as above but cleaner function with less dependencies.
|
* Same as above but cleaner function with less dependencies.
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
|
#[Deprecated]
|
||||||
public function sumNetWorthByCurrency(Carbon $date): array;
|
public function sumNetWorthByCurrency(Carbon $date): array;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,12 +61,12 @@ class ForgotPasswordController extends Controller
|
|||||||
*
|
*
|
||||||
* @return Factory|RedirectResponse|View
|
* @return Factory|RedirectResponse|View
|
||||||
*/
|
*/
|
||||||
public function sendResetLinkEmail(Request $request, ?UserRepositoryInterface $repository = null)
|
public function sendResetLinkEmail(Request $request, UserRepositoryInterface $repository)
|
||||||
{
|
{
|
||||||
app('log')->info('Start of sendResetLinkEmail()');
|
Log::info('Start of sendResetLinkEmail()');
|
||||||
if ('web' !== config('firefly.authentication_guard')) {
|
if ('web' !== config('firefly.authentication_guard')) {
|
||||||
$message = sprintf('Cannot reset password when authenticating over "%s".', config('firefly.authentication_guard'));
|
$message = sprintf('Cannot reset password when authenticating over "%s".', config('firefly.authentication_guard'));
|
||||||
app('log')->error($message);
|
Log::error($message);
|
||||||
|
|
||||||
return view('error', compact('message'));
|
return view('error', compact('message'));
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ class ForgotPasswordController extends Controller
|
|||||||
// need to show to the user. Finally, we'll send out a proper response.
|
// need to show to the user. Finally, we'll send out a proper response.
|
||||||
$result = $this->broker()->sendResetLink($request->only('email'));
|
$result = $this->broker()->sendResetLink($request->only('email'));
|
||||||
if ('passwords.throttled' === $result) {
|
if ('passwords.throttled' === $result) {
|
||||||
app('log')->error(sprintf('Cowardly refuse to send a password reset message to user #%d because the reset button has been throttled.', $user->id));
|
Log::error(sprintf('Cowardly refuse to send a password reset message to user #%d because the reset button has been throttled.', $user->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
// always send the same response to the user:
|
// always send the same response to the user:
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ class LoginController extends Controller
|
|||||||
*
|
*
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function showLoginForm(?Request $request = null)
|
public function showLoginForm(Request $request)
|
||||||
{
|
{
|
||||||
Log::channel('audit')->info('Show login form (1.1).');
|
Log::channel('audit')->info('Show login form (1.1).');
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class IndexController extends Controller
|
|||||||
public function index(?Carbon $start = null, ?Carbon $end = null)
|
public function index(?Carbon $start = null, ?Carbon $end = null)
|
||||||
{
|
{
|
||||||
$this->abRepository->cleanup();
|
$this->abRepository->cleanup();
|
||||||
app('log')->debug(sprintf('Start of IndexController::index("%s", "%s")', $start?->format('Y-m-d'), $end?->format('Y-m-d')));
|
Log::debug(sprintf('Start of IndexController::index("%s", "%s")', $start?->format('Y-m-d'), $end?->format('Y-m-d')));
|
||||||
|
|
||||||
// collect some basic vars:
|
// collect some basic vars:
|
||||||
$range = app('navigation')->getViewRange(true);
|
$range = app('navigation')->getViewRange(true);
|
||||||
@@ -199,12 +199,12 @@ class IndexController extends Controller
|
|||||||
// get all budgets, and paginate them into $budgets.
|
// get all budgets, and paginate them into $budgets.
|
||||||
$collection = $this->repository->getActiveBudgets();
|
$collection = $this->repository->getActiveBudgets();
|
||||||
$budgets = [];
|
$budgets = [];
|
||||||
app('log')->debug(sprintf('7) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('(getAllBudgets) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||||
|
|
||||||
// complement budget with budget limits in range, and expenses in currency X in range.
|
// complement budget with budget limits in range, and expenses in currency X in range.
|
||||||
/** @var Budget $current */
|
/** @var Budget $current */
|
||||||
foreach ($collection as $current) {
|
foreach ($collection as $current) {
|
||||||
app('log')->debug(sprintf('Working on budget #%d ("%s")', $current->id, $current->name));
|
Log::debug(sprintf('Working on budget #%d ("%s")', $current->id, $current->name));
|
||||||
$array = $current->toArray();
|
$array = $current->toArray();
|
||||||
$array['spent'] = [];
|
$array['spent'] = [];
|
||||||
$array['spent_total'] = [];
|
$array['spent_total'] = [];
|
||||||
@@ -215,7 +215,7 @@ class IndexController extends Controller
|
|||||||
|
|
||||||
/** @var BudgetLimit $limit */
|
/** @var BudgetLimit $limit */
|
||||||
foreach ($budgetLimits as $limit) {
|
foreach ($budgetLimits as $limit) {
|
||||||
app('log')->debug(sprintf('Working on budget limit #%d', $limit->id));
|
Log::debug(sprintf('Working on budget limit #%d', $limit->id));
|
||||||
$currency = $limit->transactionCurrency ?? $defaultCurrency;
|
$currency = $limit->transactionCurrency ?? $defaultCurrency;
|
||||||
$amount = app('steam')->bcround($limit->amount, $currency->decimal_places);
|
$amount = app('steam')->bcround($limit->amount, $currency->decimal_places);
|
||||||
$array['budgeted'][] = [
|
$array['budgeted'][] = [
|
||||||
@@ -225,14 +225,17 @@ class IndexController extends Controller
|
|||||||
'start_date' => $limit->start_date->isoFormat($this->monthAndDayFormat),
|
'start_date' => $limit->start_date->isoFormat($this->monthAndDayFormat),
|
||||||
'end_date' => $limit->end_date->isoFormat($this->monthAndDayFormat),
|
'end_date' => $limit->end_date->isoFormat($this->monthAndDayFormat),
|
||||||
'in_range' => $limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end),
|
'in_range' => $limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end),
|
||||||
|
'total_days' => $limit->start_date->diffInDays($limit->end_date) + 1,
|
||||||
'currency_id' => $currency->id,
|
'currency_id' => $currency->id,
|
||||||
'currency_symbol' => $currency->symbol,
|
'currency_symbol' => $currency->symbol,
|
||||||
'currency_name' => $currency->name,
|
'currency_name' => $currency->name,
|
||||||
'currency_decimal_places' => $currency->decimal_places,
|
'currency_decimal_places' => $currency->decimal_places,
|
||||||
];
|
];
|
||||||
app('log')->debug(sprintf('The amount budgeted for budget limit #%d is %s %s', $limit->id, $currency->code, $amount));
|
Log::debug(sprintf('The amount budgeted for budget limit #%d is %s %s', $limit->id, $currency->code, $amount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #10463
|
||||||
|
|
||||||
/** @var TransactionCurrency $currency */
|
/** @var TransactionCurrency $currency */
|
||||||
foreach ($currencies as $currency) {
|
foreach ($currencies as $currency) {
|
||||||
$spentArr = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$current]), $currency, false);
|
$spentArr = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$current]), $currency, false);
|
||||||
@@ -259,6 +262,8 @@ class IndexController extends Controller
|
|||||||
|
|
||||||
/** @var array $budget */
|
/** @var array $budget */
|
||||||
foreach ($budgets as $budget) {
|
foreach ($budgets as $budget) {
|
||||||
|
Log::debug(sprintf('Now working on budget #%d ("%s")', $budget['id'], $budget['name']));
|
||||||
|
|
||||||
/** @var array $spent */
|
/** @var array $spent */
|
||||||
foreach ($budget['spent'] as $spent) {
|
foreach ($budget['spent'] as $spent) {
|
||||||
$currencyId = $spent['currency_id'];
|
$currencyId = $spent['currency_id'];
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Controllers;
|
namespace FireflyIII\Http\Controllers;
|
||||||
|
|
||||||
use function Safe\realpath;
|
|
||||||
use function Safe\ini_get;
|
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Support\Facades\Amount;
|
use FireflyIII\Support\Facades\Amount;
|
||||||
use FireflyIII\Support\Facades\Steam;
|
use FireflyIII\Support\Facades\Steam;
|
||||||
@@ -38,6 +36,9 @@ use Illuminate\Support\Facades\Config;
|
|||||||
use Illuminate\Support\Facades\View;
|
use Illuminate\Support\Facades\View;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
use function Safe\realpath;
|
||||||
|
use function Safe\ini_get;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Controller.
|
* Class Controller.
|
||||||
*
|
*
|
||||||
@@ -78,12 +79,12 @@ abstract class Controller extends BaseController
|
|||||||
View::share('featuringWebhooks', true === config('firefly.feature_flags.webhooks') && true === config('firefly.allow_webhooks'));
|
View::share('featuringWebhooks', true === config('firefly.feature_flags.webhooks') && true === config('firefly.allow_webhooks'));
|
||||||
|
|
||||||
// share custom auth guard info.
|
// share custom auth guard info.
|
||||||
$authGuard = config('firefly.authentication_guard');
|
$authGuard = config('firefly.authentication_guard');
|
||||||
$logoutUrl = config('firefly.custom_logout_url');
|
$logoutUrl = config('firefly.custom_logout_url');
|
||||||
|
|
||||||
// overrule v2 layout back to v1.
|
// overrule v2 layout back to v1.
|
||||||
if ('true' === request()->get('force_default_layout') && 'v2' === config('view.layout')) {
|
if ('true' === request()->get('force_default_layout') && 'v2' === config('view.layout')) {
|
||||||
//config('view.layout','v1');
|
// config('view.layout','v1');
|
||||||
Config::set('view.layout', 'v1');
|
Config::set('view.layout', 'v1');
|
||||||
View::getFinder()->setPaths([realpath(base_path('resources/views'))]); // @phpstan-ignore-line
|
View::getFinder()->setPaths([realpath(base_path('resources/views'))]); // @phpstan-ignore-line
|
||||||
}
|
}
|
||||||
@@ -92,15 +93,15 @@ abstract class Controller extends BaseController
|
|||||||
View::share('logoutUrl', $logoutUrl);
|
View::share('logoutUrl', $logoutUrl);
|
||||||
|
|
||||||
// upload size
|
// upload size
|
||||||
$maxFileSize = Steam::phpBytes((string) ini_get('upload_max_filesize'));
|
$maxFileSize = Steam::phpBytes((string) ini_get('upload_max_filesize'));
|
||||||
$maxPostSize = Steam::phpBytes((string) ini_get('post_max_size'));
|
$maxPostSize = Steam::phpBytes((string) ini_get('post_max_size'));
|
||||||
$uploadSize = min($maxFileSize, $maxPostSize);
|
$uploadSize = min($maxFileSize, $maxPostSize);
|
||||||
View::share('uploadSize', $uploadSize);
|
View::share('uploadSize', $uploadSize);
|
||||||
|
|
||||||
// share is alpha, is beta
|
// share is alpha, is beta
|
||||||
$isAlpha = false;
|
$isAlpha = false;
|
||||||
$isBeta = false;
|
$isBeta = false;
|
||||||
$isDevelop = false;
|
$isDevelop = false;
|
||||||
if (str_contains((string) config('firefly.version'), 'alpha')) {
|
if (str_contains((string) config('firefly.version'), 'alpha')) {
|
||||||
$isAlpha = true;
|
$isAlpha = true;
|
||||||
}
|
}
|
||||||
@@ -118,7 +119,7 @@ abstract class Controller extends BaseController
|
|||||||
|
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next): mixed {
|
function ($request, $next): mixed {
|
||||||
$locale = Steam::getLocale();
|
$locale = Steam::getLocale();
|
||||||
// translations for specific strings:
|
// translations for specific strings:
|
||||||
$this->monthFormat = (string) trans('config.month_js', [], $locale);
|
$this->monthFormat = (string) trans('config.month_js', [], $locale);
|
||||||
$this->monthAndDayFormat = (string) trans('config.month_and_day_js', [], $locale);
|
$this->monthAndDayFormat = (string) trans('config.month_and_day_js', [], $locale);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Http\Controllers\Json;
|
namespace FireflyIII\Http\Controllers\Json;
|
||||||
|
|
||||||
|
use Deprecated;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Enums\AccountTypeEnum;
|
use FireflyIII\Enums\AccountTypeEnum;
|
||||||
use FireflyIII\Enums\TransactionTypeEnum;
|
use FireflyIII\Enums\TransactionTypeEnum;
|
||||||
@@ -46,9 +47,8 @@ class BoxController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deprecated method, no longer in use.
|
* Deprecated method, no longer in use.
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
|
#[Deprecated]
|
||||||
public function available(): JsonResponse
|
public function available(): JsonResponse
|
||||||
{
|
{
|
||||||
return response()->json([]);
|
return response()->json([]);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
|
|||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Contracts\View\Factory;
|
use Illuminate\Contracts\View\Factory;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,7 +76,6 @@ class ExecutionController extends Controller
|
|||||||
$accounts = implode(',', $request->get('accounts'));
|
$accounts = implode(',', $request->get('accounts'));
|
||||||
$startDate = new Carbon($request->get('start'));
|
$startDate = new Carbon($request->get('start'));
|
||||||
$endDate = new Carbon($request->get('end'));
|
$endDate = new Carbon($request->get('end'));
|
||||||
$rules = $this->ruleGroupRepository->getActiveRules($ruleGroup);
|
|
||||||
// create new rule engine:
|
// create new rule engine:
|
||||||
$newRuleEngine = app(RuleEngineInterface::class);
|
$newRuleEngine = app(RuleEngineInterface::class);
|
||||||
$newRuleEngine->setUser($user);
|
$newRuleEngine->setUser($user);
|
||||||
@@ -86,7 +86,9 @@ class ExecutionController extends Controller
|
|||||||
$newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]);
|
$newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]);
|
||||||
|
|
||||||
// set rules:
|
// set rules:
|
||||||
$newRuleEngine->setRules($rules);
|
// #10427, file rule group and not the set of rules.
|
||||||
|
$collection = new Collection([$ruleGroup]);
|
||||||
|
$newRuleEngine->setRuleGroups($collection);
|
||||||
$newRuleEngine->fire();
|
$newRuleEngine->fire();
|
||||||
|
|
||||||
// Tell the user that the job is queued
|
// Tell the user that the job is queued
|
||||||
|
|||||||
@@ -26,10 +26,12 @@ namespace FireflyIII\Http\Middleware;
|
|||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Exceptions\Handler;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Auth\AuthenticationException;
|
use Illuminate\Auth\AuthenticationException;
|
||||||
use Illuminate\Contracts\Auth\Factory as Auth;
|
use Illuminate\Contracts\Auth\Factory as Auth;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Authenticate
|
* Class Authenticate
|
||||||
@@ -84,6 +86,7 @@ class Authenticate
|
|||||||
if ($this->auth->check()) {
|
if ($this->auth->check()) {
|
||||||
// do an extra check on user object.
|
// do an extra check on user object.
|
||||||
/** @noinspection PhpUndefinedMethodInspection */
|
/** @noinspection PhpUndefinedMethodInspection */
|
||||||
|
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = $this->auth->authenticate();
|
$user = $this->auth->authenticate();
|
||||||
$this->validateBlockedUser($user, $guards);
|
$this->validateBlockedUser($user, $guards);
|
||||||
@@ -107,7 +110,14 @@ class Authenticate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new AuthenticationException('Unauthenticated.', $guards);
|
// this is a massive hack, but if the handler has the oauth exception
|
||||||
|
// at this point we can report its error instead of a generic one.
|
||||||
|
$message = 'Unauthenticated.';
|
||||||
|
if (Handler::$lastError instanceof OAuthServerException) {
|
||||||
|
$message = Handler::$lastError->getHint();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AuthenticationException($message, $guards);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Repositories\Budget;
|
namespace FireflyIII\Repositories\Budget;
|
||||||
|
|
||||||
|
use Deprecated;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Models\AvailableBudget;
|
use FireflyIII\Models\AvailableBudget;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
@@ -205,9 +206,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface, U
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Deprecated]
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public function setAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end, string $amount): AvailableBudget
|
public function setAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end, string $amount): AvailableBudget
|
||||||
{
|
{
|
||||||
/** @var null|AvailableBudget */
|
/** @var null|AvailableBudget */
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Repositories\Budget;
|
namespace FireflyIII\Repositories\Budget;
|
||||||
|
|
||||||
|
use Deprecated;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Enums\UserRoleEnum;
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\AvailableBudget;
|
use FireflyIII\Models\AvailableBudget;
|
||||||
@@ -66,9 +67,7 @@ interface AvailableBudgetRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function get(?Carbon $start = null, ?Carbon $end = null): Collection;
|
public function get(?Carbon $start = null, ?Carbon $end = null): Collection;
|
||||||
|
|
||||||
/**
|
#[Deprecated]
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public function getAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end): string;
|
public function getAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end): string;
|
||||||
|
|
||||||
public function getAvailableBudgetWithCurrency(Carbon $start, Carbon $end): array;
|
public function getAvailableBudgetWithCurrency(Carbon $start, Carbon $end): array;
|
||||||
@@ -90,9 +89,7 @@ interface AvailableBudgetRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function getByCurrencyDate(Carbon $start, Carbon $end, TransactionCurrency $currency): ?AvailableBudget;
|
public function getByCurrencyDate(Carbon $start, Carbon $end, TransactionCurrency $currency): ?AvailableBudget;
|
||||||
|
|
||||||
/**
|
#[Deprecated]
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public function setAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end, string $amount): AvailableBudget;
|
public function setAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end, string $amount): AvailableBudget;
|
||||||
|
|
||||||
public function store(array $data): ?AvailableBudget;
|
public function store(array $data): ?AvailableBudget;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Repositories\Budget;
|
namespace FireflyIII\Repositories\Budget;
|
||||||
|
|
||||||
|
use Deprecated;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Enums\UserRoleEnum;
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
@@ -44,9 +45,7 @@ use Illuminate\Support\Collection;
|
|||||||
*/
|
*/
|
||||||
interface NoBudgetRepositoryInterface
|
interface NoBudgetRepositoryInterface
|
||||||
{
|
{
|
||||||
/**
|
#[Deprecated]
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public function getNoBudgetPeriodReport(Collection $accounts, Carbon $start, Carbon $end): array;
|
public function getNoBudgetPeriodReport(Collection $accounts, Carbon $start, Carbon $end): array;
|
||||||
|
|
||||||
public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array;
|
public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Repositories\Budget;
|
namespace FireflyIII\Repositories\Budget;
|
||||||
|
|
||||||
|
use Deprecated;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Enums\TransactionTypeEnum;
|
use FireflyIII\Enums\TransactionTypeEnum;
|
||||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
@@ -74,9 +75,8 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
|||||||
/**
|
/**
|
||||||
* This method is being used to generate the budget overview in the year/multi-year report. Its used
|
* This method is being used to generate the budget overview in the year/multi-year report. Its used
|
||||||
* in both the year/multi-year budget overview AND in the accompanying chart.
|
* in both the year/multi-year budget overview AND in the accompanying chart.
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
|
#[Deprecated]
|
||||||
public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array
|
public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
$carbonFormat = app('navigation')->preferredCarbonFormat($start, $end);
|
$carbonFormat = app('navigation')->preferredCarbonFormat($start, $end);
|
||||||
@@ -204,7 +204,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
|
|||||||
?TransactionCurrency $currency = null,
|
?TransactionCurrency $currency = null,
|
||||||
bool $convertToNative = false
|
bool $convertToNative = false
|
||||||
): array {
|
): array {
|
||||||
Log::debug(sprintf('Start of %s(date, date, array, array, "%s", "%s").', __METHOD__, $currency?->code, var_export($convertToNative, true)));
|
Log::debug(sprintf('Start of %s(date, date, array, array, "%s", %s).', __METHOD__, $currency?->code, var_export($convertToNative, true)));
|
||||||
// this collector excludes all transfers TO liabilities (which are also withdrawals)
|
// this collector excludes all transfers TO liabilities (which are also withdrawals)
|
||||||
// because those expenses only become expenses once they move from the liability to the friend.
|
// because those expenses only become expenses once they move from the liability to the friend.
|
||||||
// 2024-12-24 disable the exclusion for now.
|
// 2024-12-24 disable the exclusion for now.
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Repositories\Budget;
|
namespace FireflyIII\Repositories\Budget;
|
||||||
|
|
||||||
|
use Deprecated;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Enums\UserRoleEnum;
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
@@ -51,9 +52,7 @@ interface OperationsRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function budgetedPerDay(Budget $budget): string;
|
public function budgetedPerDay(Budget $budget): string;
|
||||||
|
|
||||||
/**
|
#[Deprecated]
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array;
|
public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,6 +70,7 @@ interface OperationsRepositoryInterface
|
|||||||
Carbon $end,
|
Carbon $end,
|
||||||
?Collection $accounts = null,
|
?Collection $accounts = null,
|
||||||
?Collection $budgets = null,
|
?Collection $budgets = null,
|
||||||
?TransactionCurrency $currency = null
|
?TransactionCurrency $currency = null,
|
||||||
|
bool $convertToNative = false
|
||||||
): array;
|
): array;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte
|
|||||||
$amount = '' === $amount ? '0' : $amount;
|
$amount = '' === $amount ? '0' : $amount;
|
||||||
$sum = bcadd($sum, $amount);
|
$sum = bcadd($sum, $amount);
|
||||||
}
|
}
|
||||||
// Log::debug(sprintf('Current amount in piggy bank #%d ("%s") is %s', $piggyBank->id, $piggyBank->name, $sum));
|
Log::debug(sprintf('Current amount in piggy bank #%d ("%s") is %s', $piggyBank->id, $piggyBank->name, $sum));
|
||||||
|
|
||||||
return $sum;
|
return $sum;
|
||||||
}
|
}
|
||||||
@@ -444,7 +444,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte
|
|||||||
{
|
{
|
||||||
$piggyBank->piggyBankEvents()->delete();
|
$piggyBank->piggyBankEvents()->delete();
|
||||||
foreach ($piggyBank->accounts as $account) {
|
foreach ($piggyBank->accounts as $account) {
|
||||||
if (0 !== bccomp('0', $account->pivot->current_amount)) {
|
if (0 !== bccomp('0', (string) $account->pivot->current_amount)) {
|
||||||
event(new ChangedAmount($piggyBank, $account->pivot->current_amount, null, null));
|
event(new ChangedAmount($piggyBank, $account->pivot->current_amount, null, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -440,10 +440,12 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
|||||||
|
|
||||||
/** @var TransactionJournal $journal */
|
/** @var TransactionJournal $journal */
|
||||||
foreach ($group->transactionJournals as $journal) {
|
foreach ($group->transactionJournals as $journal) {
|
||||||
|
$names = sprintf('%s%s', $names, $journal->date->format('Y-m-d-H:i:s'));
|
||||||
|
|
||||||
/** @var Transaction $transaction */
|
/** @var Transaction $transaction */
|
||||||
foreach ($journal->transactions as $transaction) {
|
foreach ($journal->transactions as $transaction) {
|
||||||
if (-1 === bccomp('0', (string)$transaction->amount)) {
|
if (-1 === bccomp('0', (string)$transaction->amount)) {
|
||||||
$sum = bcadd($sum, $transaction->amount);
|
$sum = bcadd($sum, (string) $transaction->amount);
|
||||||
$names = sprintf('%s%s', $names, $transaction->account->name);
|
$names = sprintf('%s%s', $names, $transaction->account->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Services\Internal\Support;
|
namespace FireflyIII\Services\Internal\Support;
|
||||||
|
|
||||||
|
use Deprecated;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Enums\AccountTypeEnum;
|
use FireflyIII\Enums\AccountTypeEnum;
|
||||||
use FireflyIII\Exceptions\DuplicateTransactionException;
|
use FireflyIII\Exceptions\DuplicateTransactionException;
|
||||||
@@ -193,8 +194,8 @@ trait AccountServiceTrait
|
|||||||
/**
|
/**
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
* *
|
* *
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
|
#[Deprecated]
|
||||||
protected function createOBGroup(Account $account, array $data): TransactionGroup
|
protected function createOBGroup(Account $account, array $data): TransactionGroup
|
||||||
{
|
{
|
||||||
app('log')->debug('Now going to create an OB group.');
|
app('log')->debug('Now going to create an OB group.');
|
||||||
|
|||||||
@@ -825,7 +825,13 @@ class JournalUpdateService
|
|||||||
public function isCompareHashChanged(): bool
|
public function isCompareHashChanged(): bool
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||||
$compareHash = $this->transactionGroupRepository->getCompareHash($this->transactionGroup);
|
$compareHash = hash('sha256', sprintf('%s', Carbon::now()->getTimestamp()));
|
||||||
|
if (!$this->transactionGroup instanceof TransactionGroup) {
|
||||||
|
$compareHash = $this->transactionGroupRepository->getCompareHash($this->transactionJournal->transactionGroup);
|
||||||
|
}
|
||||||
|
if ($this->transactionGroup instanceof TransactionGroup) {
|
||||||
|
$this->transactionGroupRepository->getCompareHash($this->transactionGroup);
|
||||||
|
}
|
||||||
Log::debug(sprintf('Compare hash is "%s".', $compareHash));
|
Log::debug(sprintf('Compare hash is "%s".', $compareHash));
|
||||||
Log::debug(sprintf('Start compare hash is "%s".', $this->startCompareHash));
|
Log::debug(sprintf('Start compare hash is "%s".', $this->startCompareHash));
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Support;
|
namespace FireflyIII\Support;
|
||||||
|
|
||||||
|
use Deprecated;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
@@ -195,25 +196,19 @@ class Amount
|
|||||||
return $user->currencies()->orderBy('code', 'ASC')->get();
|
return $user->currencies()->orderBy('code', 'ASC')->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Deprecated]
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public function getDefaultCurrency(): TransactionCurrency
|
public function getDefaultCurrency(): TransactionCurrency
|
||||||
{
|
{
|
||||||
return $this->getNativeCurrency();
|
return $this->getNativeCurrency();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Deprecated(message: 'use getDefaultCurrencyByUserGroup instead')]
|
||||||
* @deprecated use getDefaultCurrencyByUserGroup instead
|
|
||||||
*/
|
|
||||||
public function getDefaultCurrencyByUser(User $user): TransactionCurrency
|
public function getDefaultCurrencyByUser(User $user): TransactionCurrency
|
||||||
{
|
{
|
||||||
return $this->getDefaultCurrencyByUserGroup($user->userGroup);
|
return $this->getDefaultCurrencyByUserGroup($user->userGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[Deprecated]
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public function getDefaultCurrencyByUserGroup(UserGroup $userGroup): TransactionCurrency
|
public function getDefaultCurrencyByUserGroup(UserGroup $userGroup): TransactionCurrency
|
||||||
{
|
{
|
||||||
return $this->getNativeCurrencyByUserGroup($userGroup);
|
return $this->getNativeCurrencyByUserGroup($userGroup);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Support\Authentication;
|
namespace FireflyIII\Support\Authentication;
|
||||||
|
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Support\Facades\Preferences;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Contracts\Auth\Authenticatable;
|
use Illuminate\Contracts\Auth\Authenticatable;
|
||||||
use Illuminate\Contracts\Auth\Guard;
|
use Illuminate\Contracts\Auth\Guard;
|
||||||
@@ -86,14 +87,14 @@ class RemoteUserGuard implements Guard
|
|||||||
|
|
||||||
if (null !== $header) {
|
if (null !== $header) {
|
||||||
$emailAddress = (string) (request()->server($header) ?? apache_request_headers()[$header] ?? null);
|
$emailAddress = (string) (request()->server($header) ?? apache_request_headers()[$header] ?? null);
|
||||||
$preference = app('preferences')->getForUser($retrievedUser, 'remote_guard_alt_email');
|
$preference = Preferences::getForUser($retrievedUser, 'remote_guard_alt_email');
|
||||||
|
|
||||||
if ('' !== $emailAddress && null === $preference && $emailAddress !== $userID) {
|
if ('' !== $emailAddress && null === $preference && $emailAddress !== $userID) {
|
||||||
app('preferences')->setForUser($retrievedUser, 'remote_guard_alt_email', $emailAddress);
|
Preferences::setForUser($retrievedUser, 'remote_guard_alt_email', $emailAddress);
|
||||||
}
|
}
|
||||||
// if the pref isn't null and the object returned isn't null, update the email address.
|
// if the pref isn't null and the object returned isn't null, update the email address.
|
||||||
if ('' !== $emailAddress && null !== $preference && $emailAddress !== $preference->data) {
|
if ('' !== $emailAddress && null !== $preference && $emailAddress !== $preference->data) {
|
||||||
app('preferences')->setForUser($retrievedUser, 'remote_guard_alt_email', $emailAddress);
|
Preferences::setForUser($retrievedUser, 'remote_guard_alt_email', $emailAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace FireflyIII\Support\Cronjobs;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Jobs\CreateAutoBudgetLimits;
|
use FireflyIII\Jobs\CreateAutoBudgetLimits;
|
||||||
use FireflyIII\Models\Configuration;
|
use FireflyIII\Models\Configuration;
|
||||||
|
use FireflyIII\Support\Facades\FireflyConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class AutoBudgetCronjob
|
* Class AutoBudgetCronjob
|
||||||
@@ -36,7 +37,7 @@ class AutoBudgetCronjob extends AbstractCronjob
|
|||||||
public function fire(): void
|
public function fire(): void
|
||||||
{
|
{
|
||||||
/** @var Configuration $config */
|
/** @var Configuration $config */
|
||||||
$config = app('fireflyconfig')->get('last_ab_job', 0);
|
$config = FireflyConfig::get('last_ab_job', 0);
|
||||||
$lastTime = (int) $config->data;
|
$lastTime = (int) $config->data;
|
||||||
$diff = Carbon::now()->getTimestamp() - $lastTime;
|
$diff = Carbon::now()->getTimestamp() - $lastTime;
|
||||||
$diffForHumans = today(config('app.timezone'))->diffForHumans(Carbon::createFromTimestamp($lastTime), null, true);
|
$diffForHumans = today(config('app.timezone'))->diffForHumans(Carbon::createFromTimestamp($lastTime), null, true);
|
||||||
@@ -78,7 +79,7 @@ class AutoBudgetCronjob extends AbstractCronjob
|
|||||||
$this->jobSucceeded = true;
|
$this->jobSucceeded = true;
|
||||||
$this->message = 'Auto-budget cron job fired successfully.';
|
$this->message = 'Auto-budget cron job fired successfully.';
|
||||||
|
|
||||||
app('fireflyconfig')->set('last_ab_job', (int) $this->date->format('U'));
|
FireflyConfig::set('last_ab_job', (int) $this->date->format('U'));
|
||||||
app('log')->info('Done with auto budget cron job task.');
|
app('log')->info('Done with auto budget cron job task.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ trait AugumentData
|
|||||||
{
|
{
|
||||||
/** @var AccountRepositoryInterface $repository */
|
/** @var AccountRepositoryInterface $repository */
|
||||||
$repository = app(AccountRepositoryInterface::class);
|
$repository = app(AccountRepositoryInterface::class);
|
||||||
$accounts = $repository->getAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::CASH->value]);
|
$accounts = $repository->getAccountsByType([AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::CASH->value]);
|
||||||
$grouped = $accounts->groupBy('id')->toArray();
|
$grouped = $accounts->groupBy('id')->toArray();
|
||||||
$return = [];
|
$return = [];
|
||||||
foreach ($accountIds as $combinedId) {
|
foreach ($accountIds as $combinedId) {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ trait PeriodOverview
|
|||||||
protected JournalRepositoryInterface $journalRepos;
|
protected JournalRepositoryInterface $journalRepos;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns "period entries", so nov-2015, dec-2015, etc etc (this depends on the users session range)
|
* This method returns "period entries", so nov-2015, dec-2015, etc. (this depends on the users session range)
|
||||||
* and for each period, the amount of money spent and earned. This is a complex operation which is cached for
|
* and for each period, the amount of money spent and earned. This is a complex operation which is cached for
|
||||||
* performance reasons.
|
* performance reasons.
|
||||||
*
|
*
|
||||||
@@ -97,18 +97,26 @@ trait PeriodOverview
|
|||||||
/** @var array $dates */
|
/** @var array $dates */
|
||||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||||
$entries = [];
|
$entries = [];
|
||||||
|
$spent = [];
|
||||||
|
$earned = [];
|
||||||
|
$transferredAway = [];
|
||||||
|
$transferredIn = [];
|
||||||
|
|
||||||
// run a custom query because doing this with the collector is MEGA slow.
|
// run a custom query because doing this with the collector is MEGA slow.
|
||||||
$transactions = $this->accountRepository->periodCollection($account, $start, $end);
|
$transactions = $this->accountRepository->periodCollection($account, $start, $end);
|
||||||
|
|
||||||
// loop dates
|
// loop dates
|
||||||
Log::debug(sprintf('Count of loops: %d', count($dates)));
|
Log::debug(sprintf('Count of loops: %d', count($dates)));
|
||||||
|
$loops = 0;
|
||||||
|
// stop after 10 loops for memory reasons.
|
||||||
foreach ($dates as $currentDate) {
|
foreach ($dates as $currentDate) {
|
||||||
$title = app('navigation')->periodShow($currentDate['start'], $currentDate['period']);
|
$title = app('navigation')->periodShow($currentDate['start'], $currentDate['period']);
|
||||||
[$transactions, $spent] = $this->filterTransactionsByType(TransactionTypeEnum::WITHDRAWAL, $transactions, $currentDate['start'], $currentDate['end']);
|
if ($loops < 10) {
|
||||||
[$transactions, $earned] = $this->filterTransactionsByType(TransactionTypeEnum::DEPOSIT, $transactions, $currentDate['start'], $currentDate['end']);
|
[$transactions, $spent] = $this->filterTransactionsByType(TransactionTypeEnum::WITHDRAWAL, $transactions, $currentDate['start'], $currentDate['end']);
|
||||||
[$transactions, $transferredAway] = $this->filterTransfers('away', $transactions, $currentDate['start'], $currentDate['end']);
|
[$transactions, $earned] = $this->filterTransactionsByType(TransactionTypeEnum::DEPOSIT, $transactions, $currentDate['start'], $currentDate['end']);
|
||||||
[$transactions, $transferredIn] = $this->filterTransfers('in', $transactions, $currentDate['start'], $currentDate['end']);
|
[$transactions, $transferredAway] = $this->filterTransfers('away', $transactions, $currentDate['start'], $currentDate['end']);
|
||||||
|
[$transactions, $transferredIn] = $this->filterTransfers('in', $transactions, $currentDate['start'], $currentDate['end']);
|
||||||
|
}
|
||||||
$entries[]
|
$entries[]
|
||||||
= [
|
= [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
@@ -119,6 +127,7 @@ trait PeriodOverview
|
|||||||
'transferred_away' => $this->groupByCurrency($transferredAway),
|
'transferred_away' => $this->groupByCurrency($transferredAway),
|
||||||
'transferred_in' => $this->groupByCurrency($transferredIn),
|
'transferred_in' => $this->groupByCurrency($transferredIn),
|
||||||
];
|
];
|
||||||
|
++$loops;
|
||||||
}
|
}
|
||||||
$cache->store($entries);
|
$cache->store($entries);
|
||||||
Timer::stop('account-period-total');
|
Timer::stop('account-period-total');
|
||||||
@@ -548,27 +557,29 @@ trait PeriodOverview
|
|||||||
/** @var array $dates */
|
/** @var array $dates */
|
||||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||||
$entries = [];
|
$entries = [];
|
||||||
|
$spent = [];
|
||||||
|
$earned = [];
|
||||||
|
$transferred = [];
|
||||||
// collect all journals in this period (regardless of type)
|
// collect all journals in this period (regardless of type)
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setTypes($types)->setRange($start, $end);
|
$collector->setTypes($types)->setRange($start, $end);
|
||||||
$genericSet = $collector->getExtractedJournals();
|
$genericSet = $collector->getExtractedJournals();
|
||||||
|
$loops = 0;
|
||||||
|
|
||||||
foreach ($dates as $currentDate) {
|
foreach ($dates as $currentDate) {
|
||||||
$spent = [];
|
|
||||||
$earned = [];
|
|
||||||
$transferred = [];
|
|
||||||
$title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
|
$title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
|
||||||
|
|
||||||
// set to correct array
|
if ($loops < 10) {
|
||||||
if ('expenses' === $transactionType || 'withdrawal' === $transactionType) {
|
// set to correct array
|
||||||
$spent = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
if ('expenses' === $transactionType || 'withdrawal' === $transactionType) {
|
||||||
}
|
$spent = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
||||||
if ('revenue' === $transactionType || 'deposit' === $transactionType) {
|
}
|
||||||
$earned = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
if ('revenue' === $transactionType || 'deposit' === $transactionType) {
|
||||||
}
|
$earned = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
||||||
if ('transfer' === $transactionType || 'transfers' === $transactionType) {
|
}
|
||||||
$transferred = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
if ('transfer' === $transactionType || 'transfers' === $transactionType) {
|
||||||
|
$transferred = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$entries[]
|
$entries[]
|
||||||
= [
|
= [
|
||||||
@@ -579,6 +590,7 @@ trait PeriodOverview
|
|||||||
'earned' => $this->groupByCurrency($earned),
|
'earned' => $this->groupByCurrency($earned),
|
||||||
'transferred' => $this->groupByCurrency($transferred),
|
'transferred' => $this->groupByCurrency($transferred),
|
||||||
];
|
];
|
||||||
|
++$loops;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $entries;
|
return $entries;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ use Illuminate\Contracts\Validation\Validator as ValidatorContract;
|
|||||||
use Illuminate\Routing\Route;
|
use Illuminate\Routing\Route;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Support\Facades\Route as RouteFacade;
|
use Illuminate\Support\Facades\Route as RouteFacade;
|
||||||
use Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
use function Safe\parse_url;
|
use function Safe\parse_url;
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
|||||||
private array $notes; // @phpstan-ignore-line
|
private array $notes; // @phpstan-ignore-line
|
||||||
private array $tags;
|
private array $tags;
|
||||||
private User $user;
|
private User $user;
|
||||||
private TransactionCurrency $nativeCurrency;
|
private readonly TransactionCurrency $nativeCurrency;
|
||||||
private UserGroup $userGroup;
|
private UserGroup $userGroup;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
|
|||||||
@@ -582,7 +582,7 @@ class Navigation
|
|||||||
*/
|
*/
|
||||||
public function preferredEndOfPeriod(Carbon $start, Carbon $end): string
|
public function preferredEndOfPeriod(Carbon $start, Carbon $end): string
|
||||||
{
|
{
|
||||||
if ((int) $start->diffInMonths($end, true) > 1) {
|
if ((int) $start->diffInMonths($end, true) > 1 && (int) $start->diffInMonths($end, true) <= 12) {
|
||||||
return 'endOfMonth';
|
return 'endOfMonth';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,7 +599,7 @@ class Navigation
|
|||||||
*/
|
*/
|
||||||
public function preferredRangeFormat(Carbon $start, Carbon $end): string
|
public function preferredRangeFormat(Carbon $start, Carbon $end): string
|
||||||
{
|
{
|
||||||
if ((int) $start->diffInMonths($end, true) > 1) {
|
if ((int) $start->diffInMonths($end, true) > 1 && (int) $start->diffInMonths($end, true) <= 12) {
|
||||||
return '1M';
|
return '1M';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,7 +616,7 @@ class Navigation
|
|||||||
*/
|
*/
|
||||||
public function preferredSqlFormat(Carbon $start, Carbon $end): string
|
public function preferredSqlFormat(Carbon $start, Carbon $end): string
|
||||||
{
|
{
|
||||||
if ((int) $start->diffInMonths($end, true) > 1) {
|
if ((int) $start->diffInMonths($end, true) > 1 && (int) $start->diffInMonths($end, true) <= 12) {
|
||||||
return '%Y-%m';
|
return '%Y-%m';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class TransactionSummarizer
|
|||||||
|
|
||||||
public function groupByCurrencyId(array $journals, string $method = 'negative', bool $includeForeign = true): array
|
public function groupByCurrencyId(array $journals, string $method = 'negative', bool $includeForeign = true): array
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('Now in groupByCurrencyId([%d journals], "%s")', count($journals), $method));
|
Log::debug(sprintf('Now in groupByCurrencyId([%d journals], "%s", %s)', count($journals), $method, var_export($includeForeign, true)));
|
||||||
$array = [];
|
$array = [];
|
||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
$field = 'amount';
|
$field = 'amount';
|
||||||
@@ -71,12 +71,12 @@ class TransactionSummarizer
|
|||||||
$foreignCurrencyDecimalPlaces = null;
|
$foreignCurrencyDecimalPlaces = null;
|
||||||
|
|
||||||
if ($this->convertToNative) {
|
if ($this->convertToNative) {
|
||||||
Log::debug('convertToNative is true.');
|
// Log::debug('convertToNative is true.');
|
||||||
// if convert to native, use the native amount yes or no?
|
// if convert to native, use the native amount yes or no?
|
||||||
$useNative = $this->default->id !== (int) $journal['currency_id'];
|
$useNative = $this->default->id !== (int) $journal['currency_id'];
|
||||||
$useForeign = $this->default->id === (int) $journal['foreign_currency_id'];
|
$useForeign = $this->default->id === (int) $journal['foreign_currency_id'];
|
||||||
if ($useNative) {
|
if ($useNative) {
|
||||||
Log::debug(sprintf('Journal #%d switches to native amount (original is %s)', $journal['transaction_journal_id'], $journal['currency_code']));
|
// Log::debug(sprintf('Journal #%d switches to native amount (original is %s)', $journal['transaction_journal_id'], $journal['currency_code']));
|
||||||
$field = 'native_amount';
|
$field = 'native_amount';
|
||||||
$currencyId = $this->default->id;
|
$currencyId = $this->default->id;
|
||||||
$currencyName = $this->default->name;
|
$currencyName = $this->default->name;
|
||||||
@@ -85,7 +85,7 @@ class TransactionSummarizer
|
|||||||
$currencyDecimalPlaces = $this->default->decimal_places;
|
$currencyDecimalPlaces = $this->default->decimal_places;
|
||||||
}
|
}
|
||||||
if ($useForeign) {
|
if ($useForeign) {
|
||||||
Log::debug(sprintf('Journal #%d switches to foreign amount (foreign is %s)', $journal['transaction_journal_id'], $journal['foreign_currency_code']));
|
// Log::debug(sprintf('Journal #%d switches to foreign amount (foreign is %s)', $journal['transaction_journal_id'], $journal['foreign_currency_code']));
|
||||||
$field = 'foreign_amount';
|
$field = 'foreign_amount';
|
||||||
$currencyId = (int) $journal['foreign_currency_id'];
|
$currencyId = (int) $journal['foreign_currency_id'];
|
||||||
$currencyName = $journal['foreign_currency_name'];
|
$currencyName = $journal['foreign_currency_name'];
|
||||||
@@ -95,7 +95,7 @@ class TransactionSummarizer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!$this->convertToNative) {
|
if (!$this->convertToNative) {
|
||||||
Log::debug('convertToNative is false.');
|
// Log::debug('convertToNative is false.');
|
||||||
// use foreign amount?
|
// use foreign amount?
|
||||||
$foreignCurrencyId = (int) $journal['foreign_currency_id'];
|
$foreignCurrencyId = (int) $journal['foreign_currency_id'];
|
||||||
if (0 !== $foreignCurrencyId) {
|
if (0 !== $foreignCurrencyId) {
|
||||||
|
|||||||
@@ -278,6 +278,8 @@ class Steam
|
|||||||
$carbonKey = $carbon->format('Y-m-d');
|
$carbonKey = $carbon->format('Y-m-d');
|
||||||
// make sure sum is a string:
|
// make sure sum is a string:
|
||||||
$sumOfDay = (string) ($entry->sum_of_day ?? '0');
|
$sumOfDay = (string) ($entry->sum_of_day ?? '0');
|
||||||
|
// #10426 make sure sum is not in scientific notation.
|
||||||
|
$sumOfDay = $this->floatalize($sumOfDay);
|
||||||
|
|
||||||
// find currency of this entry, does not have to exist.
|
// find currency of this entry, does not have to exist.
|
||||||
$currencies[$entry->transaction_currency_id] ??= TransactionCurrency::find($entry->transaction_currency_id);
|
$currencies[$entry->transaction_currency_id] ??= TransactionCurrency::find($entry->transaction_currency_id);
|
||||||
@@ -340,7 +342,7 @@ class Steam
|
|||||||
|
|
||||||
return $cache->get();
|
return $cache->get();
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
|
// Log::debug(sprintf('finalAccountBalance(#%d, %s)', $account->id, $date->format('Y-m-d H:i:s')));
|
||||||
if (null === $convertToNative) {
|
if (null === $convertToNative) {
|
||||||
$convertToNative = Amount::convertToNative($account->user);
|
$convertToNative = Amount::convertToNative($account->user);
|
||||||
}
|
}
|
||||||
@@ -399,7 +401,7 @@ class Steam
|
|||||||
// Log::debug(sprintf('Virtual balance makes the (native) total %s', $return['balance']));
|
// Log::debug(sprintf('Virtual balance makes the (native) total %s', $return['balance']));
|
||||||
}
|
}
|
||||||
$final = array_merge($return, $others);
|
$final = array_merge($return, $others);
|
||||||
Log::debug('Final balance is', $final);
|
// Log::debug('Final balance is', $final);
|
||||||
$cache->store($final);
|
$cache->store($final);
|
||||||
|
|
||||||
return $final;
|
return $final;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ use FireflyIII\Models\RuleAction;
|
|||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\TransactionRules\Traits\RefreshNotesTrait;
|
use FireflyIII\TransactionRules\Traits\RefreshNotesTrait;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SetDescription.
|
* Class SetDescription.
|
||||||
@@ -51,7 +52,12 @@ class SetDescription implements ActionInterface
|
|||||||
$after = $this->action->getValue($journal);
|
$after = $this->action->getValue($journal);
|
||||||
|
|
||||||
// replace newlines.
|
// replace newlines.
|
||||||
$after = str_replace(["\r", "\n", "\t", "\036", "\025"], '', $after);
|
$after = trim(str_replace(["\r", "\n", "\t", "\036", "\025"], '', $after));
|
||||||
|
|
||||||
|
if ('' === $after) {
|
||||||
|
Log::warning('Action resulted in an empty description, reset to default value.');
|
||||||
|
$after = '(no description)';
|
||||||
|
}
|
||||||
|
|
||||||
DB::table('transaction_journals')
|
DB::table('transaction_journals')
|
||||||
->where('id', '=', $journal['transaction_journal_id'])
|
->where('id', '=', $journal['transaction_journal_id'])
|
||||||
|
|||||||
@@ -64,13 +64,13 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
|
|
||||||
public function addOperator(array $operator): void
|
public function addOperator(array $operator): void
|
||||||
{
|
{
|
||||||
app('log')->debug('Add extra operator: ', $operator);
|
Log::debug('Add extra operator: ', $operator);
|
||||||
$this->operators[] = $operator;
|
$this->operators[] = $operator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function find(): Collection
|
public function find(): Collection
|
||||||
{
|
{
|
||||||
app('log')->debug('SearchRuleEngine::find()');
|
Log::debug('SearchRuleEngine::find()');
|
||||||
$collection = new Collection();
|
$collection = new Collection();
|
||||||
foreach ($this->rules as $rule) {
|
foreach ($this->rules as $rule) {
|
||||||
$found = new Collection();
|
$found = new Collection();
|
||||||
@@ -83,7 +83,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
$collection = $collection->merge($found);
|
$collection = $collection->merge($found);
|
||||||
}
|
}
|
||||||
$result = $collection->unique();
|
$result = $collection->unique();
|
||||||
app('log')->debug(sprintf('SearchRuleEngine::find() returns %d unique transactions.', $result->count()));
|
Log::debug(sprintf('SearchRuleEngine::find() returns %d unique transactions.', $result->count()));
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
*/
|
*/
|
||||||
private function findStrictRule(Rule $rule): Collection
|
private function findStrictRule(Rule $rule): Collection
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now in findStrictRule(#%d)', $rule->id ?? 0));
|
Log::debug(sprintf('Now in findStrictRule(#%d)', $rule->id ?? 0));
|
||||||
$searchArray = [];
|
$searchArray = [];
|
||||||
$triggers = [];
|
$triggers = [];
|
||||||
if ($this->refreshTriggers) {
|
if ($this->refreshTriggers) {
|
||||||
@@ -116,18 +116,18 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
// if the trigger needs no context, value is different:
|
// if the trigger needs no context, value is different:
|
||||||
$needsContext = (bool) (config(sprintf('search.operators.%s.needs_context', $contextSearch)) ?? true);
|
$needsContext = (bool) (config(sprintf('search.operators.%s.needs_context', $contextSearch)) ?? true);
|
||||||
if (false === $needsContext) {
|
if (false === $needsContext) {
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: add a rule trigger (no context): %s:true', $ruleTrigger->trigger_type));
|
Log::debug(sprintf('SearchRuleEngine:: add a rule trigger (no context): %s:true', $ruleTrigger->trigger_type));
|
||||||
$searchArray[$ruleTrigger->trigger_type][] = 'true';
|
$searchArray[$ruleTrigger->trigger_type][] = 'true';
|
||||||
}
|
}
|
||||||
if (true === $needsContext) {
|
if (true === $needsContext) {
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: add a rule trigger (context): %s:"%s"', $ruleTrigger->trigger_type, $ruleTrigger->trigger_value));
|
Log::debug(sprintf('SearchRuleEngine:: add a rule trigger (context): %s:"%s"', $ruleTrigger->trigger_type, $ruleTrigger->trigger_value));
|
||||||
$searchArray[$ruleTrigger->trigger_type][] = sprintf('"%s"', $ruleTrigger->trigger_value);
|
$searchArray[$ruleTrigger->trigger_type][] = sprintf('"%s"', $ruleTrigger->trigger_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add local operators:
|
// add local operators:
|
||||||
foreach ($this->operators as $operator) {
|
foreach ($this->operators as $operator) {
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value']));
|
Log::debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value']));
|
||||||
$searchArray[$operator['type']][] = sprintf('"%s"', $operator['value']);
|
$searchArray[$operator['type']][] = sprintf('"%s"', $operator['value']);
|
||||||
}
|
}
|
||||||
$date = today(config('app.timezone'));
|
$date = today(config('app.timezone'));
|
||||||
@@ -141,11 +141,11 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
$searchEngine->setPage(1);
|
$searchEngine->setPage(1);
|
||||||
$searchEngine->setLimit(31337);
|
$searchEngine->setLimit(31337);
|
||||||
$searchEngine->setDate($date);
|
$searchEngine->setDate($date);
|
||||||
app('log')->debug('Search array', $searchArray);
|
Log::debug('Search array', $searchArray);
|
||||||
foreach ($searchArray as $type => $searches) {
|
foreach ($searchArray as $type => $searches) {
|
||||||
foreach ($searches as $value) {
|
foreach ($searches as $value) {
|
||||||
$query = sprintf('%s:%s', $type, $value);
|
$query = sprintf('%s:%s', $type, $value);
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: add query "%s"', $query));
|
Log::debug(sprintf('SearchRuleEngine:: add query "%s"', $query));
|
||||||
$searchEngine->parseQuery($query);
|
$searchEngine->parseQuery($query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,33 +162,33 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
*/
|
*/
|
||||||
private function hasSpecificJournalTrigger(array $array): bool
|
private function hasSpecificJournalTrigger(array $array): bool
|
||||||
{
|
{
|
||||||
app('log')->debug('Now in hasSpecificJournalTrigger.');
|
Log::debug('Now in hasSpecificJournalTrigger.');
|
||||||
$journalTrigger = false;
|
$journalTrigger = false;
|
||||||
$dateTrigger = false;
|
$dateTrigger = false;
|
||||||
foreach ($array as $triggerName => $values) {
|
foreach ($array as $triggerName => $values) {
|
||||||
if ('journal_id' === $triggerName && is_array($values) && 1 === count($values)) {
|
if ('journal_id' === $triggerName && is_array($values) && 1 === count($values)) {
|
||||||
app('log')->debug('Found a journal_id trigger with 1 journal, true.');
|
Log::debug('Found a journal_id trigger with 1 journal, true.');
|
||||||
$journalTrigger = true;
|
$journalTrigger = true;
|
||||||
}
|
}
|
||||||
if (in_array($triggerName, ['date_is', 'date', 'on', 'date_before', 'before', 'date_after', 'after'], true)) {
|
if (in_array($triggerName, ['date_is', 'date', 'on', 'date_before', 'before', 'date_after', 'after'], true)) {
|
||||||
app('log')->debug('Found a date related trigger, set to true.');
|
Log::debug('Found a date related trigger, set to true.');
|
||||||
$dateTrigger = true;
|
$dateTrigger = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$result = $journalTrigger && $dateTrigger;
|
$result = $journalTrigger && $dateTrigger;
|
||||||
app('log')->debug(sprintf('Result of hasSpecificJournalTrigger is %s.', var_export($result, true)));
|
Log::debug(sprintf('Result of hasSpecificJournalTrigger is %s.', var_export($result, true)));
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setDateFromJournalTrigger(array $array): Carbon
|
private function setDateFromJournalTrigger(array $array): Carbon
|
||||||
{
|
{
|
||||||
app('log')->debug('Now in setDateFromJournalTrigger()');
|
Log::debug('Now in setDateFromJournalTrigger()');
|
||||||
$journalId = 0;
|
$journalId = 0;
|
||||||
foreach ($array as $triggerName => $values) {
|
foreach ($array as $triggerName => $values) {
|
||||||
if ('journal_id' === $triggerName && is_array($values) && 1 === count($values)) {
|
if ('journal_id' === $triggerName && is_array($values) && 1 === count($values)) {
|
||||||
$journalId = (int) trim($values[0] ?? '"0"', '"'); // follows format "123".
|
$journalId = (int) trim($values[0] ?? '"0"', '"'); // follows format "123".
|
||||||
app('log')->debug(sprintf('Found journal ID #%d', $journalId));
|
Log::debug(sprintf('Found journal ID #%d', $journalId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (0 !== $journalId) {
|
if (0 !== $journalId) {
|
||||||
@@ -197,12 +197,12 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
$journal = $repository->find($journalId);
|
$journal = $repository->find($journalId);
|
||||||
if (null !== $journal) {
|
if (null !== $journal) {
|
||||||
$date = $journal->date;
|
$date = $journal->date;
|
||||||
app('log')->debug(sprintf('Found journal #%d with date %s.', $journal->id, $journal->date->format('Y-m-d')));
|
Log::debug(sprintf('Found journal #%d with date %s.', $journal->id, $journal->date->format('Y-m-d')));
|
||||||
|
|
||||||
return $date;
|
return $date;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app('log')->debug('Found no journal, return default date.');
|
Log::debug('Found no journal, return default date.');
|
||||||
|
|
||||||
return today(config('app.timezone'));
|
return today(config('app.timezone'));
|
||||||
}
|
}
|
||||||
@@ -215,48 +215,48 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
|
|
||||||
private function findNonStrictRule(Rule $rule): Collection
|
private function findNonStrictRule(Rule $rule): Collection
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('findNonStrictRule(#%d)', $rule->id));
|
Log::debug(sprintf('findNonStrictRule(#%d)', $rule->id));
|
||||||
// start a search query for individual each trigger:
|
// start a search query for individual each trigger:
|
||||||
$total = new Collection();
|
$total = new Collection();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
$triggers = [];
|
$triggers = [];
|
||||||
if ($this->refreshTriggers) {
|
if ($this->refreshTriggers) {
|
||||||
app('log')->debug('Will refresh triggers.');
|
Log::debug('Will refresh triggers.');
|
||||||
$triggers = $rule->ruleTriggers()->orderBy('order', 'ASC')->get();
|
$triggers = $rule->ruleTriggers()->orderBy('order', 'ASC')->get();
|
||||||
}
|
}
|
||||||
if (!$this->refreshTriggers) {
|
if (!$this->refreshTriggers) {
|
||||||
app('log')->debug('Will not refresh triggers.');
|
Log::debug('Will not refresh triggers.');
|
||||||
$triggers = $rule->ruleTriggers;
|
$triggers = $rule->ruleTriggers;
|
||||||
}
|
}
|
||||||
app('log')->debug(sprintf('Will run %d trigger(s).', count($triggers)));
|
Log::debug(sprintf('Will run %d trigger(s).', count($triggers)));
|
||||||
|
|
||||||
/** @var RuleTrigger $ruleTrigger */
|
/** @var RuleTrigger $ruleTrigger */
|
||||||
foreach ($triggers as $ruleTrigger) {
|
foreach ($triggers as $ruleTrigger) {
|
||||||
app('log')->debug(sprintf('Now at rule trigger #%d: %s:"%s" (%s).', $ruleTrigger->id, $ruleTrigger->trigger_type, $ruleTrigger->trigger_value, var_export($ruleTrigger->stop_processing, true)));
|
Log::debug(sprintf('Now at rule trigger #%d: %s:"%s" (%s).', $ruleTrigger->id, $ruleTrigger->trigger_type, $ruleTrigger->trigger_value, var_export($ruleTrigger->stop_processing, true)));
|
||||||
if (false === $ruleTrigger->active) {
|
if (false === $ruleTrigger->active) {
|
||||||
app('log')->debug('Trigger is not active, continue.');
|
Log::debug('Trigger is not active, continue.');
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ('user_action' === $ruleTrigger->trigger_type) {
|
if ('user_action' === $ruleTrigger->trigger_type) {
|
||||||
app('log')->debug('Skip trigger type. continue.');
|
Log::debug('Skip trigger type. continue.');
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$searchArray = [];
|
$searchArray = [];
|
||||||
$needsContext = config(sprintf('search.operators.%s.needs_context', $ruleTrigger->trigger_type)) ?? true;
|
$needsContext = config(sprintf('search.operators.%s.needs_context', $ruleTrigger->trigger_type)) ?? true;
|
||||||
if (false === $needsContext) {
|
if (false === $needsContext) {
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: non strict, will search for: %s:true', $ruleTrigger->trigger_type));
|
Log::debug(sprintf('SearchRuleEngine:: non strict, will search for: %s:true', $ruleTrigger->trigger_type));
|
||||||
$searchArray[$ruleTrigger->trigger_type] = 'true';
|
$searchArray[$ruleTrigger->trigger_type] = 'true';
|
||||||
}
|
}
|
||||||
if (true === $needsContext) {
|
if (true === $needsContext) {
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: non strict, will search for: %s:"%s"', $ruleTrigger->trigger_type, $ruleTrigger->trigger_value));
|
Log::debug(sprintf('SearchRuleEngine:: non strict, will search for: %s:"%s"', $ruleTrigger->trigger_type, $ruleTrigger->trigger_value));
|
||||||
$searchArray[$ruleTrigger->trigger_type] = sprintf('"%s"', $ruleTrigger->trigger_value);
|
$searchArray[$ruleTrigger->trigger_type] = sprintf('"%s"', $ruleTrigger->trigger_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// then, add local operators as well:
|
// then, add local operators as well:
|
||||||
foreach ($this->operators as $operator) {
|
foreach ($this->operators as $operator) {
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value']));
|
Log::debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value']));
|
||||||
$searchArray[$operator['type']] = sprintf('"%s"', $operator['value']);
|
$searchArray[$operator['type']] = sprintf('"%s"', $operator['value']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,19 +272,19 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
|
|
||||||
$result = $searchEngine->searchTransactions();
|
$result = $searchEngine->searchTransactions();
|
||||||
$collection = $result->getCollection();
|
$collection = $result->getCollection();
|
||||||
app('log')->debug(sprintf('Found in this run, %d transactions', $collection->count()));
|
Log::debug(sprintf('Found in this run, %d transactions', $collection->count()));
|
||||||
$total = $total->merge($collection);
|
$total = $total->merge($collection);
|
||||||
app('log')->debug(sprintf('Total collection is now %d transactions', $total->count()));
|
Log::debug(sprintf('Total collection is now %d transactions', $total->count()));
|
||||||
++$count;
|
++$count;
|
||||||
// if trigger says stop processing, do so.
|
// if trigger says stop processing, do so.
|
||||||
if (true === $ruleTrigger->stop_processing && $result->count() > 0) {
|
if (true === $ruleTrigger->stop_processing && $result->count() > 0) {
|
||||||
app('log')->debug('The trigger says to stop processing, so stop processing other triggers.');
|
Log::debug('The trigger says to stop processing, so stop processing other triggers.');
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app('log')->debug(sprintf('Total collection is now %d transactions', $total->count()));
|
Log::debug(sprintf('Total collection is now %d transactions', $total->count()));
|
||||||
app('log')->debug(sprintf('Done running %d trigger(s)', $count));
|
Log::debug(sprintf('Done running %d trigger(s)', $count));
|
||||||
|
|
||||||
// make collection unique
|
// make collection unique
|
||||||
$unique = $total->unique(
|
$unique = $total->unique(
|
||||||
@@ -295,11 +295,11 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
return sprintf('%d%s', $group['id'], $str);
|
return sprintf('%d%s', $group['id'], $str);
|
||||||
// app('log')->debug(sprintf('Return key: %s ', $key));
|
// Log::debug(sprintf('Return key: %s ', $key));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: Found %d transactions using search engine.', $unique->count()));
|
Log::debug(sprintf('SearchRuleEngine:: Found %d transactions using search engine.', $unique->count()));
|
||||||
|
|
||||||
return $unique;
|
return $unique;
|
||||||
}
|
}
|
||||||
@@ -310,28 +310,28 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
public function fire(): void
|
public function fire(): void
|
||||||
{
|
{
|
||||||
$this->resultCount = [];
|
$this->resultCount = [];
|
||||||
app('log')->debug('SearchRuleEngine::fire()!');
|
Log::debug('SearchRuleEngine::fire()!');
|
||||||
|
|
||||||
// if rules and no rule groups, file each rule separately.
|
// if rules and no rule groups, file each rule separately.
|
||||||
if (0 !== $this->rules->count()) {
|
if (0 !== $this->rules->count()) {
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: found %d rule(s) to fire.', $this->rules->count()));
|
Log::debug(sprintf('SearchRuleEngine:: found %d rule(s) to fire.', $this->rules->count()));
|
||||||
|
|
||||||
/** @var Rule $rule */
|
/** @var Rule $rule */
|
||||||
foreach ($this->rules as $rule) {
|
foreach ($this->rules as $rule) {
|
||||||
$result = $this->fireRule($rule);
|
$result = $this->fireRule($rule);
|
||||||
if (true === $result && true === $rule->stop_processing) {
|
if (true === $result && true === $rule->stop_processing) {
|
||||||
app('log')->debug(sprintf('Rule #%d has triggered and executed, but calls to stop processing. Since not in the context of a group, do not stop.', $rule->id));
|
Log::debug(sprintf('Rule #%d has triggered and executed, but calls to stop processing. Since not in the context of a group, do not stop.', $rule->id));
|
||||||
}
|
}
|
||||||
if (false === $result && true === $rule->stop_processing) {
|
if (false === $result && true === $rule->stop_processing) {
|
||||||
app('log')->debug(sprintf('Rule #%d has triggered and changed nothing, but calls to stop processing. Do not stop.', $rule->id));
|
Log::debug(sprintf('Rule #%d has triggered and changed nothing, but calls to stop processing. Do not stop.', $rule->id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app('log')->debug('SearchRuleEngine:: done processing all rules!');
|
Log::debug('SearchRuleEngine:: done processing all rules!');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (0 !== $this->groups->count()) {
|
if (0 !== $this->groups->count()) {
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: found %d rule group(s) to fire.', $this->groups->count()));
|
Log::debug(sprintf('SearchRuleEngine:: found %d rule group(s) to fire.', $this->groups->count()));
|
||||||
|
|
||||||
// fire each group:
|
// fire each group:
|
||||||
/** @var RuleGroup $group */
|
/** @var RuleGroup $group */
|
||||||
@@ -339,7 +339,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
$this->fireGroup($group);
|
$this->fireGroup($group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app('log')->debug('SearchRuleEngine:: done processing all rules!');
|
Log::debug('SearchRuleEngine:: done processing all rules!');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -349,18 +349,18 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
*/
|
*/
|
||||||
private function fireRule(Rule $rule): bool
|
private function fireRule(Rule $rule): bool
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Now going to fire rule #%d', $rule->id));
|
Log::debug(sprintf('Now going to fire rule #%d', $rule->id));
|
||||||
if (false === $rule->active) {
|
if (false === $rule->active) {
|
||||||
app('log')->debug(sprintf('Rule #%d is not active!', $rule->id));
|
Log::debug(sprintf('Rule #%d is not active!', $rule->id));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (true === $rule->strict) {
|
if (true === $rule->strict) {
|
||||||
app('log')->debug(sprintf('Rule #%d is a strict rule.', $rule->id));
|
Log::debug(sprintf('Rule #%d is a strict rule.', $rule->id));
|
||||||
|
|
||||||
return $this->fireStrictRule($rule);
|
return $this->fireStrictRule($rule);
|
||||||
}
|
}
|
||||||
app('log')->debug(sprintf('Rule #%d is not strict rule.', $rule->id));
|
Log::debug(sprintf('Rule #%d is not strict rule.', $rule->id));
|
||||||
|
|
||||||
return $this->fireNonStrictRule($rule);
|
return $this->fireNonStrictRule($rule);
|
||||||
}
|
}
|
||||||
@@ -372,19 +372,19 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
*/
|
*/
|
||||||
private function fireStrictRule(Rule $rule): bool
|
private function fireStrictRule(Rule $rule): bool
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('SearchRuleEngine::fireStrictRule(%d)!', $rule->id));
|
Log::debug(sprintf('SearchRuleEngine::fireStrictRule(%d)!', $rule->id));
|
||||||
$collection = $this->findStrictRule($rule);
|
$collection = $this->findStrictRule($rule);
|
||||||
|
|
||||||
$this->processResults($rule, $collection);
|
$this->processResults($rule, $collection);
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: done processing strict rule #%d', $rule->id));
|
Log::debug(sprintf('SearchRuleEngine:: done processing strict rule #%d', $rule->id));
|
||||||
|
|
||||||
$result = $collection->count() > 0;
|
$result = $collection->count() > 0;
|
||||||
if (true === $result) {
|
if (true === $result) {
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: rule #%d was triggered (on %d transaction(s)).', $rule->id, $collection->count()));
|
Log::debug(sprintf('SearchRuleEngine:: rule #%d was triggered (on %d transaction(s)).', $rule->id, $collection->count()));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: rule #%d was not triggered (on %d transaction(s)).', $rule->id, $collection->count()));
|
Log::debug(sprintf('SearchRuleEngine:: rule #%d was not triggered (on %d transaction(s)).', $rule->id, $collection->count()));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -394,7 +394,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
*/
|
*/
|
||||||
private function processResults(Rule $rule, Collection $collection): void
|
private function processResults(Rule $rule, Collection $collection): void
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: Going to process %d results.', $collection->count()));
|
Log::debug(sprintf('SearchRuleEngine:: Going to process %d results.', $collection->count()));
|
||||||
|
|
||||||
/** @var array $group */
|
/** @var array $group */
|
||||||
foreach ($collection as $group) {
|
foreach ($collection as $group) {
|
||||||
@@ -407,7 +407,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
*/
|
*/
|
||||||
private function processTransactionGroup(Rule $rule, array $group): void
|
private function processTransactionGroup(Rule $rule, array $group): void
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction group #%d', $group['id']));
|
Log::debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction group #%d', $group['id']));
|
||||||
|
|
||||||
/** @var array $transaction */
|
/** @var array $transaction */
|
||||||
foreach ($group['transactions'] as $transaction) {
|
foreach ($group['transactions'] as $transaction) {
|
||||||
@@ -420,7 +420,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
*/
|
*/
|
||||||
private function processTransactionJournal(Rule $rule, array $transaction): void
|
private function processTransactionJournal(Rule $rule, array $transaction): void
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction journal #%d', $transaction['transaction_journal_id']));
|
Log::debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction journal #%d', $transaction['transaction_journal_id']));
|
||||||
$actions = $rule->ruleActions()->orderBy('order', 'ASC')->get();
|
$actions = $rule->ruleActions()->orderBy('order', 'ASC')->get();
|
||||||
|
|
||||||
/** @var RuleAction $ruleAction */
|
/** @var RuleAction $ruleAction */
|
||||||
@@ -440,14 +440,14 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
*/
|
*/
|
||||||
private function processRuleAction(RuleAction $ruleAction, array $transaction): bool
|
private function processRuleAction(RuleAction $ruleAction, array $transaction): bool
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Executing rule action "%s" with value "%s"', $ruleAction->action_type, $ruleAction->action_value));
|
Log::debug(sprintf('Executing rule action "%s" with value "%s"', $ruleAction->action_type, $ruleAction->action_value));
|
||||||
$transaction = $this->addNotes($transaction);
|
$transaction = $this->addNotes($transaction);
|
||||||
$actionClass = ActionFactory::getAction($ruleAction);
|
$actionClass = ActionFactory::getAction($ruleAction);
|
||||||
$result = $actionClass->actOnArray($transaction);
|
$result = $actionClass->actOnArray($transaction);
|
||||||
$journalId = $transaction['transaction_journal_id'] ?? 0;
|
$journalId = $transaction['transaction_journal_id'] ?? 0;
|
||||||
if (true === $result) {
|
if (true === $result) {
|
||||||
$this->resultCount[$journalId] = array_key_exists($journalId, $this->resultCount) ? $this->resultCount[$journalId]++ : 1;
|
$this->resultCount[$journalId] = array_key_exists($journalId, $this->resultCount) ? $this->resultCount[$journalId]++ : 1;
|
||||||
app('log')->debug(
|
Log::debug(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Action "%s" on journal #%d was executed, so count a result. Updated transaction journal count is now %d.',
|
'Action "%s" on journal #%d was executed, so count a result. Updated transaction journal count is now %d.',
|
||||||
$ruleAction->action_type,
|
$ruleAction->action_type,
|
||||||
@@ -457,17 +457,17 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (false === $result) {
|
if (false === $result) {
|
||||||
app('log')->debug(sprintf('Action "%s" reports NO changes were made.', $ruleAction->action_type));
|
Log::debug(sprintf('Action "%s" reports NO changes were made.', $ruleAction->action_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
// pick up from the action if it actually acted or not:
|
// pick up from the action if it actually acted or not:
|
||||||
if (true === $ruleAction->stop_processing && true === $result) {
|
if (true === $ruleAction->stop_processing && true === $result) {
|
||||||
app('log')->debug(sprintf('Rule action "%s" reports changes AND asks to break, so break!', $ruleAction->action_type));
|
Log::debug(sprintf('Rule action "%s" reports changes AND asks to break, so break!', $ruleAction->action_type));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (true === $ruleAction->stop_processing && false === $result) {
|
if (true === $ruleAction->stop_processing && false === $result) {
|
||||||
app('log')->debug(sprintf('Rule action "%s" reports NO changes AND asks to break, but we wont break!', $ruleAction->action_type));
|
Log::debug(sprintf('Rule action "%s" reports NO changes AND asks to break, but we wont break!', $ruleAction->action_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -492,11 +492,11 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
*/
|
*/
|
||||||
private function fireNonStrictRule(Rule $rule): bool
|
private function fireNonStrictRule(Rule $rule): bool
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('SearchRuleEngine::fireNonStrictRule(%d)!', $rule->id));
|
Log::debug(sprintf('SearchRuleEngine::fireNonStrictRule(%d)!', $rule->id));
|
||||||
$collection = $this->findNonStrictRule($rule);
|
$collection = $this->findNonStrictRule($rule);
|
||||||
|
|
||||||
$this->processResults($rule, $collection);
|
$this->processResults($rule, $collection);
|
||||||
app('log')->debug(sprintf('SearchRuleEngine:: done processing non-strict rule #%d', $rule->id));
|
Log::debug(sprintf('SearchRuleEngine:: done processing non-strict rule #%d', $rule->id));
|
||||||
|
|
||||||
return $collection->count() > 0;
|
return $collection->count() > 0;
|
||||||
}
|
}
|
||||||
@@ -506,14 +506,14 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
*/
|
*/
|
||||||
private function fireGroup(RuleGroup $group): void
|
private function fireGroup(RuleGroup $group): void
|
||||||
{
|
{
|
||||||
app('log')->debug(sprintf('Going to fire group #%d with %d rule(s)', $group->id, $group->rules->count()));
|
Log::debug(sprintf('Going to fire group #%d with %d rule(s)', $group->id, $group->rules->count()));
|
||||||
|
|
||||||
/** @var Rule $rule */
|
/** @var Rule $rule */
|
||||||
foreach ($group->rules as $rule) {
|
foreach ($group->rules as $rule) {
|
||||||
app('log')->debug(sprintf('Going to fire rule #%d from group #%d', $rule->id, $group->id));
|
Log::debug(sprintf('Going to fire rule #%d from group #%d', $rule->id, $group->id));
|
||||||
$result = $this->fireRule($rule);
|
$result = $this->fireRule($rule);
|
||||||
if (true === $result && true === $rule->stop_processing) {
|
if (true === $result && true === $rule->stop_processing) {
|
||||||
app('log')->debug(sprintf('The rule was triggered and rule->stop_processing = true, so group #%d will stop processing further rules.', $group->id));
|
Log::debug(sprintf('The rule was triggered and rule->stop_processing = true, so group #%d will stop processing further rules.', $group->id));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -535,10 +535,10 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
|
|
||||||
public function setRuleGroups(Collection $ruleGroups): void
|
public function setRuleGroups(Collection $ruleGroups): void
|
||||||
{
|
{
|
||||||
app('log')->debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
foreach ($ruleGroups as $group) {
|
foreach ($ruleGroups as $group) {
|
||||||
if ($group instanceof RuleGroup) {
|
if ($group instanceof RuleGroup) {
|
||||||
app('log')->debug(sprintf('Adding a rule group to the SearchRuleEngine: #%d ("%s")', $group->id, $group->title));
|
Log::debug(sprintf('Adding a rule group to the SearchRuleEngine: #%d ("%s")', $group->id, $group->title));
|
||||||
$this->groups->push($group);
|
$this->groups->push($group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -546,10 +546,10 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
|
|
||||||
public function setRules(Collection $rules): void
|
public function setRules(Collection $rules): void
|
||||||
{
|
{
|
||||||
app('log')->debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
foreach ($rules as $rule) {
|
foreach ($rules as $rule) {
|
||||||
if ($rule instanceof Rule) {
|
if ($rule instanceof Rule) {
|
||||||
app('log')->debug(sprintf('Adding a rule to the SearchRuleEngine: #%d ("%s")', $rule->id, $rule->title));
|
Log::debug(sprintf('Adding a rule to the SearchRuleEngine: #%d ("%s")', $rule->id, $rule->title));
|
||||||
$this->rules->push($rule);
|
$this->rules->push($rule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,8 +73,8 @@ class PiggyBankEventTransformer extends AbstractTransformer
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'id' => (string) $event->id,
|
'id' => (string) $event->id,
|
||||||
'created_at' => $event->created_at->toAtomString(),
|
'created_at' => $event->created_at?->toAtomString(),
|
||||||
'updated_at' => $event->updated_at->toAtomString(),
|
'updated_at' => $event->updated_at?->toAtomString(),
|
||||||
'amount' => app('steam')->bcround($event->amount, $currency->decimal_places),
|
'amount' => app('steam')->bcround($event->amount, $currency->decimal_places),
|
||||||
'currency_id' => (string) $currency->id,
|
'currency_id' => (string) $currency->id,
|
||||||
'currency_code' => $currency->code,
|
'currency_code' => $currency->code,
|
||||||
|
|||||||
19
app/User.php
19
app/User.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII;
|
namespace FireflyIII;
|
||||||
|
|
||||||
|
use Deprecated;
|
||||||
use FireflyIII\Enums\UserRoleEnum;
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Events\RequestedNewPassword;
|
use FireflyIII\Events\RequestedNewPassword;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
@@ -188,9 +189,8 @@ class User extends Authenticatable
|
|||||||
* Get the models LDAP domain.
|
* Get the models LDAP domain.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
|
#[Deprecated]
|
||||||
public function getLdapDomain()
|
public function getLdapDomain()
|
||||||
{
|
{
|
||||||
return $this->{$this->getLdapDomainColumn()};
|
return $this->{$this->getLdapDomainColumn()};
|
||||||
@@ -200,9 +200,8 @@ class User extends Authenticatable
|
|||||||
* Get the database column name of the domain.
|
* Get the database column name of the domain.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
|
#[Deprecated]
|
||||||
public function getLdapDomainColumn()
|
public function getLdapDomainColumn()
|
||||||
{
|
{
|
||||||
return 'domain';
|
return 'domain';
|
||||||
@@ -212,9 +211,8 @@ class User extends Authenticatable
|
|||||||
* Get the models LDAP GUID.
|
* Get the models LDAP GUID.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
|
#[Deprecated]
|
||||||
public function getLdapGuid()
|
public function getLdapGuid()
|
||||||
{
|
{
|
||||||
return $this->{$this->getLdapGuidColumn()};
|
return $this->{$this->getLdapGuidColumn()};
|
||||||
@@ -224,9 +222,8 @@ class User extends Authenticatable
|
|||||||
* Get the models LDAP GUID database column name.
|
* Get the models LDAP GUID database column name.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
|
#[Deprecated]
|
||||||
public function getLdapGuidColumn()
|
public function getLdapGuidColumn()
|
||||||
{
|
{
|
||||||
return 'objectguid';
|
return 'objectguid';
|
||||||
@@ -468,9 +465,8 @@ class User extends Authenticatable
|
|||||||
* Set the models LDAP domain.
|
* Set the models LDAP domain.
|
||||||
*
|
*
|
||||||
* @param string $domain
|
* @param string $domain
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
|
#[Deprecated]
|
||||||
public function setLdapDomain($domain): void
|
public function setLdapDomain($domain): void
|
||||||
{
|
{
|
||||||
$this->{$this->getLdapDomainColumn()} = $domain;
|
$this->{$this->getLdapDomainColumn()} = $domain;
|
||||||
@@ -480,9 +476,8 @@ class User extends Authenticatable
|
|||||||
* Set the models LDAP GUID.
|
* Set the models LDAP GUID.
|
||||||
*
|
*
|
||||||
* @param string $guid
|
* @param string $guid
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
|
#[Deprecated]
|
||||||
public function setLdapGuid($guid): void
|
public function setLdapGuid($guid): void
|
||||||
{
|
{
|
||||||
$this->{$this->getLdapGuidColumn()} = $guid;
|
$this->{$this->getLdapGuidColumn()} = $guid;
|
||||||
|
|||||||
71
changelog.md
71
changelog.md
@@ -3,6 +3,77 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## 6.2.20 - 2025-07-02
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- New query parser is now the default.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- [Issue 10517](https://github.com/firefly-iii/firefly-iii/issues/10517) (401 when trying to create personal access token with Remote user authentication) reported by @MaxPelly
|
||||||
|
- [Discussion 10530](https://github.com/orgs/firefly-iii/discussions/10530) (Find and delete transactions with empty descriptions) started by @umfk
|
||||||
|
- [Issue 10535](https://github.com/firefly-iii/firefly-iii/issues/10535) (Internal Firefly III Exception: Undefined array key "currency") reported by @MaelFr
|
||||||
|
|
||||||
|
## 6.2.19 - 2025-06-29
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Currency seeder adds "CNY" again, because it turns out "RMB" is not the official, ISO 4217 code for the Chinese Yuan.
|
||||||
|
- The "period overview" next to the transaction lists (withdrawals, deposits and transfers) is limited to 10 entries because it uses a lot of memory. I still have to fix this.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Support for ntfy, since the underlying library is no longer maintained. Will be replaced in the future.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Running balance calculation also triggers on edit.
|
||||||
|
- [Issue 10489](https://github.com/firefly-iii/firefly-iii/issues/10489) (Cannot create personal access token if using remote guard auth in latest version) reported by @Palomox
|
||||||
|
- [Issue 10493](https://github.com/firefly-iii/firefly-iii/issues/10493) (Reports First Graph Wrong) reported by @nicolopozzato
|
||||||
|
- [Issue 10499](https://github.com/firefly-iii/firefly-iii/issues/10499) (Password change results in error 500 (Class "Hash" not found)) reported by @willermo
|
||||||
|
- [Issue 10507](https://github.com/firefly-iii/firefly-iii/issues/10507) (Opening balance transactions includes in `has_no_category` filter) reported by @lompi
|
||||||
|
- [Issue 10510](https://github.com/firefly-iii/firefly-iii/issues/10510) (Liability accounts show as 'no name' on budget transaction report pie chart.) reported by @slackspace-io
|
||||||
|
|
||||||
|
## 6.2.18 - 2025-06-20
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Give more details about OAuth errors.
|
||||||
|
- Currency seeder adds "RMB" instead of "CNY" for Chinese Yuan.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- [Issue 10454](https://github.com/firefly-iii/firefly-iii/issues/10454) (Bulk edit individually give an error) reported by @Rick45
|
||||||
|
- [Issue 10470](https://github.com/firefly-iii/firefly-iii/issues/10470) (API endpoint `/api/v1/chart/account/overview` throws error) reported by @dreautall
|
||||||
|
- Remove some leftover debug info
|
||||||
|
|
||||||
|
## 6.2.17 - 2025-06-12
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Firefly III will trim account numbers with spaces for better matching during imports
|
||||||
|
- Running balance is only updated when amounts or accounts change.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Transactions can't be linked to a piggy bank twice.
|
||||||
|
- [Issue 10229](https://github.com/firefly-iii/firefly-iii/issues/10229) (Please show transaction ID in the Meta information) reported by @srikakulamts
|
||||||
|
- [Issue 10382](https://github.com/firefly-iii/firefly-iii/issues/10382) (Have a link to search page on mobile layout) reported by @sergeolkhovik
|
||||||
|
- [Issue 10399](https://github.com/firefly-iii/firefly-iii/issues/10399) (Can not apply rules to future dates) reported by @sanderr
|
||||||
|
- [Issue 10403](https://github.com/firefly-iii/firefly-iii/issues/10403) (Piggy banks over multiple accounts are too restrictive) reported by @sanderr
|
||||||
|
- [Issue 10413](https://github.com/firefly-iii/firefly-iii/issues/10413) (Piggy Bank math seems broken, deductions are not registered, Saved so far 0 but balance is positive) reported by @Skiri-ki
|
||||||
|
- [Issue 10419](https://github.com/firefly-iii/firefly-iii/issues/10419) (Add quarters to report view to prefill date ranges) reported by @othmar52
|
||||||
|
- [Issue 10426](https://github.com/firefly-iii/firefly-iii/issues/10426) (bcadd(): Argument #1 ($num1) is not well-formed) reported by @grgar
|
||||||
|
- [Discussion 10427](https://github.com/orgs/firefly-iii/discussions/10427) ("Stop processing" doesn't seem to work? (6.2.12)) started by @rarosalion
|
||||||
|
- [Issue 10432](https://github.com/firefly-iii/firefly-iii/issues/10432) (Error during upgrade 6.1.25 → 6.2.16: $piggyBank->account is null) reported by @Digi92
|
||||||
|
- [Issue 10433](https://github.com/firefly-iii/firefly-iii/issues/10433) (500 error when using forgot password link (running in Docker)) reported by @jegelandsdal
|
||||||
|
- [Issue 10441](https://github.com/firefly-iii/firefly-iii/issues/10441) (Missing spent per day info on mismatching budget limit periods) reported by @Kaotic3
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
- Transactions now contain balance before/after.
|
||||||
|
|
||||||
## 6.2.16 - 2025-xx-xx
|
## 6.2.16 - 2025-xx-xx
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
371
composer.lock
generated
371
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -78,7 +78,7 @@ return [
|
|||||||
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
|
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
|
||||||
// see cer.php for exchange rates feature flag.
|
// see cer.php for exchange rates feature flag.
|
||||||
],
|
],
|
||||||
'version' => 'develop/2025-06-04',
|
'version' => 'develop/2025-07-02',
|
||||||
'api_version' => '2.1.0', // field is no longer used.
|
'api_version' => '2.1.0', // field is no longer used.
|
||||||
'db_version' => 25,
|
'db_version' => 25,
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ return [
|
|||||||
'channels' => [
|
'channels' => [
|
||||||
'email' => ['enabled' => true, 'ui_configurable' => 0],
|
'email' => ['enabled' => true, 'ui_configurable' => 0],
|
||||||
'slack' => ['enabled' => true, 'ui_configurable' => 1],
|
'slack' => ['enabled' => true, 'ui_configurable' => 1],
|
||||||
'ntfy' => ['enabled' => false, 'ui_configurable' => 1],
|
// 'ntfy' => ['enabled' => false, 'ui_configurable' => 1],
|
||||||
'pushover' => ['enabled' => true, 'ui_configurable' => 1],
|
'pushover' => ['enabled' => true, 'ui_configurable' => 1],
|
||||||
// 'gotify' => ['enabled' => false, 'ui_configurable' => 0],
|
// 'gotify' => ['enabled' => false, 'ui_configurable' => 0],
|
||||||
// 'pushbullet' => ['enabled' => false, 'ui_configurable' => 0],
|
// 'pushbullet' => ['enabled' => false, 'ui_configurable' => 0],
|
||||||
|
|||||||
@@ -260,8 +260,6 @@ return [
|
|||||||
'destination_balance_lt' => ['alias' => false, 'needs_context' => true],
|
'destination_balance_lt' => ['alias' => false, 'needs_context' => true],
|
||||||
'destination_balance_is' => ['alias' => false, 'needs_context' => true],
|
'destination_balance_is' => ['alias' => false, 'needs_context' => true],
|
||||||
],
|
],
|
||||||
/**
|
// Which query parser to use - 'new' or 'legacy'
|
||||||
* Which query parser to use - 'new' or 'legacy'
|
|
||||||
*/
|
|
||||||
'query_parser' => env('QUERY_PARSER_IMPLEMENTATION', 'legacy'),
|
'query_parser' => env('QUERY_PARSER_IMPLEMENTATION', 'legacy'),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ class TransactionCurrencySeeder extends Seeder
|
|||||||
// asian currencies
|
// asian currencies
|
||||||
$currencies[] = ['code' => 'JPY', 'name' => 'Japanese yen', 'symbol' => '¥', 'decimal_places' => 0];
|
$currencies[] = ['code' => 'JPY', 'name' => 'Japanese yen', 'symbol' => '¥', 'decimal_places' => 0];
|
||||||
$currencies[] = ['code' => 'CNY', 'name' => 'Chinese yuan', 'symbol' => '¥', 'decimal_places' => 2];
|
$currencies[] = ['code' => 'CNY', 'name' => 'Chinese yuan', 'symbol' => '¥', 'decimal_places' => 2];
|
||||||
|
// $currencies[] = ['code' => 'RMB', 'name' => 'Chinese yuan', 'symbol' => '¥', 'decimal_places' => 2];
|
||||||
$currencies[] = ['code' => 'RUB', 'name' => 'Russian ruble', 'symbol' => '₽', 'decimal_places' => 2];
|
$currencies[] = ['code' => 'RUB', 'name' => 'Russian ruble', 'symbol' => '₽', 'decimal_places' => 2];
|
||||||
$currencies[] = ['code' => 'INR', 'name' => 'Indian rupee', 'symbol' => '₹', 'decimal_places' => 2];
|
$currencies[] = ['code' => 'INR', 'name' => 'Indian rupee', 'symbol' => '₹', 'decimal_places' => 2];
|
||||||
|
|
||||||
|
|||||||
783
package-lock.json
generated
783
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"firefly": {
|
"firefly": {
|
||||||
"administrations_page_title": "Financial administrations",
|
"administrations_page_title": "Administracions financeres",
|
||||||
"administrations_index_menu": "Financial administrations",
|
"administrations_index_menu": "Administracions financeres",
|
||||||
"expires_at": "Expires at",
|
"expires_at": "Caduca a les",
|
||||||
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
|
"temp_administrations_introduction": "Firefly III aviat podr\u00e0 gestionar diverses administracions financeres. Ara mateix, nom\u00e9s en teniu una. Podeu definir el t\u00edtol d'aquesta administraci\u00f3 i la seva moneda nativa. Aix\u00f2 substitueix la configuraci\u00f3 anterior on definiu la vostra \"moneda predeterminada\". Aquesta configuraci\u00f3 ara est\u00e0 vinculada a l'administraci\u00f3 financera i pot ser diferent per a cada administraci\u00f3.",
|
||||||
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
|
"administration_currency_form_help": "It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.",
|
||||||
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",
|
"administrations_page_edit_sub_title_js": "Edita l'administraci\u00f3 financera \"{title}\"",
|
||||||
"table": "Taula",
|
"table": "Taula",
|
||||||
"welcome_back": "Qu\u00e8 est\u00e0 passant?",
|
"welcome_back": "Qu\u00e8 est\u00e0 passant?",
|
||||||
"flash_error": "Error!",
|
"flash_error": "Error!",
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
"split": "Dividir",
|
"split": "Dividir",
|
||||||
"single_split": "Divisi\u00f3",
|
"single_split": "Divisi\u00f3",
|
||||||
"not_enough_currencies": "Not enough currencies",
|
"not_enough_currencies": "Not enough currencies",
|
||||||
"not_enough_currencies_enabled": "If you have just one currency enabled, there is no need to add exchange rates.",
|
"not_enough_currencies_enabled": "Si tens nom\u00e9s una divisa habilitada, no cal afegir tipus de canvi.",
|
||||||
"transaction_stored_link": "La <a href=\"transactions\/show\/{ID}\">Transacci\u00f3 #{ID} (\"{title}\")<\/a> s'ha desat.",
|
"transaction_stored_link": "La <a href=\"transactions\/show\/{ID}\">Transacci\u00f3 #{ID} (\"{title}\")<\/a> s'ha desat.",
|
||||||
"webhook_stored_link": "S'ha desat <a href=\"webhooks\/show\/{ID}\">el Webook #{ID} (\"{title}\")<\/a> correctament.",
|
"webhook_stored_link": "S'ha desat <a href=\"webhooks\/show\/{ID}\">el Webook #{ID} (\"{title}\")<\/a> correctament.",
|
||||||
"webhook_updated_link": "S'ha actualitzat el <a href=\"webhooks\/show\/{ID}\">Webook #{ID}<\/a> (\"{title}\").",
|
"webhook_updated_link": "S'ha actualitzat el <a href=\"webhooks\/show\/{ID}\">Webook #{ID}<\/a> (\"{title}\").",
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"apply_rules_checkbox": "Aplicar regles",
|
"apply_rules_checkbox": "Aplicar regles",
|
||||||
"fire_webhooks_checkbox": "Disparar webhooks",
|
"fire_webhooks_checkbox": "Disparar webhooks",
|
||||||
"no_budget_pointer": "Sembla que encara no tens cap pressupost. N'hauries de crear alguns a la p\u00e0gina de <a href=\"budgets\">pressuposts<\/a>. Els pressupostos et poden ajudar a fer el seguiment de les teves despeses.",
|
"no_budget_pointer": "Sembla que encara no tens cap pressupost. N'hauries de crear alguns a la p\u00e0gina de <a href=\"budgets\">pressuposts<\/a>. Els pressupostos et poden ajudar a fer el seguiment de les teves despeses.",
|
||||||
"no_bill_pointer": "You seem to have no subscription yet. You should create some on the <a href=\"subscriptions\">subscription<\/a>-page. Subscriptions can help you keep track of expenses.",
|
"no_bill_pointer": "Sembla que encara no tens cap subscripci\u00f3. N'hauries de crear alguns a la p\u00e0gina de <a href=\"subscriptions\">subscripcions<\/a>. Les subscripcions et poden ajudar a fer el seguiment de les teves despeses.",
|
||||||
"source_account": "Compte d'origen",
|
"source_account": "Compte d'origen",
|
||||||
"hidden_fields_preferences": "Pots habilitar m\u00e9s opcions de transacci\u00f3 a la <a href=\"preferences\">configuraci\u00f3<\/a>.",
|
"hidden_fields_preferences": "Pots habilitar m\u00e9s opcions de transacci\u00f3 a la <a href=\"preferences\">configuraci\u00f3<\/a>.",
|
||||||
"destination_account": "Compte de dest\u00ed",
|
"destination_account": "Compte de dest\u00ed",
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
"is_reconciled_fields_dropped": "Because this transaction is reconciled, you will not be able to update the accounts, nor the amount(s) unless you remove the reconciliation flag.",
|
"is_reconciled_fields_dropped": "Because this transaction is reconciled, you will not be able to update the accounts, nor the amount(s) unless you remove the reconciliation flag.",
|
||||||
"tags": "Etiquetes",
|
"tags": "Etiquetes",
|
||||||
"no_budget": "(cap pressupost)",
|
"no_budget": "(cap pressupost)",
|
||||||
"no_bill": "(no subscription)",
|
"no_bill": "(cap subscripci\u00f3)",
|
||||||
"category": "Categoria",
|
"category": "Categoria",
|
||||||
"attachments": "Adjunts",
|
"attachments": "Adjunts",
|
||||||
"notes": "Notes",
|
"notes": "Notes",
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
"destination_account_reconciliation": "No pots editar el compte de dest\u00ed d'una transacci\u00f3 de reconciliaci\u00f3.",
|
"destination_account_reconciliation": "No pots editar el compte de dest\u00ed d'una transacci\u00f3 de reconciliaci\u00f3.",
|
||||||
"source_account_reconciliation": "No pots editar el compte d'origen d'una transacci\u00f3 de consolidaci\u00f3.",
|
"source_account_reconciliation": "No pots editar el compte d'origen d'una transacci\u00f3 de consolidaci\u00f3.",
|
||||||
"budget": "Pressupost",
|
"budget": "Pressupost",
|
||||||
"bill": "Subscription",
|
"bill": "Subscripci\u00f3",
|
||||||
"you_create_withdrawal": "Est\u00e0s creant una retirada.",
|
"you_create_withdrawal": "Est\u00e0s creant una retirada.",
|
||||||
"you_create_transfer": "Est\u00e0s creant una transfer\u00e8ncia.",
|
"you_create_transfer": "Est\u00e0s creant una transfer\u00e8ncia.",
|
||||||
"you_create_deposit": "Est\u00e0s creant un ingr\u00e9s.",
|
"you_create_deposit": "Est\u00e0s creant un ingr\u00e9s.",
|
||||||
@@ -140,21 +140,21 @@
|
|||||||
"response": "Resposta",
|
"response": "Resposta",
|
||||||
"visit_webhook_url": "Visitar l'URL del webhook",
|
"visit_webhook_url": "Visitar l'URL del webhook",
|
||||||
"reset_webhook_secret": "Reiniciar el secret del webhook",
|
"reset_webhook_secret": "Reiniciar el secret del webhook",
|
||||||
"header_exchange_rates": "Exchange rates",
|
"header_exchange_rates": "Tipus de canvi",
|
||||||
"exchange_rates_intro": "Firefly III supports downloading and using exchange rates. Read more about this in <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">the documentation<\/a>.",
|
"exchange_rates_intro": "Firefly III supports downloading and using exchange rates. Read more about this in <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">the documentation<\/a>.",
|
||||||
"exchange_rates_from_to": "Between {from} and {to} (and the other way around)",
|
"exchange_rates_from_to": "Entre {from} i {to} (i a la inversa)",
|
||||||
"exchange_rates_intro_rates": "Firefly III uses the following exchange rates. The inverse is automatically calculated when it is not provided. If no exchange rate exists for the date of the transaction, Firefly III will go back in time to find one. If none are present, the rate \"1\" will be used.",
|
"exchange_rates_intro_rates": "Firefly III uses the following exchange rates. The inverse is automatically calculated when it is not provided. If no exchange rate exists for the date of the transaction, Firefly III will go back in time to find one. If none are present, the rate \"1\" will be used.",
|
||||||
"header_exchange_rates_rates": "Exchange rates",
|
"header_exchange_rates_rates": "Tipus de canvi",
|
||||||
"header_exchange_rates_table": "Table with exchange rates",
|
"header_exchange_rates_table": "Taula amb els tipus de canvi",
|
||||||
"help_rate_form": "On this day, how many {to} will you get for one {from}?",
|
"help_rate_form": "El dia d'avui, quants {to} obtindr\u00e0s amb un {from}?",
|
||||||
"add_new_rate": "Add a new exchange rate",
|
"add_new_rate": "Afegeix un nou tipus de canvi",
|
||||||
"save_new_rate": "Save new rate"
|
"save_new_rate": "Desa nou tipus"
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
"url": "URL",
|
"url": "URL",
|
||||||
"active": "Actiu",
|
"active": "Actiu",
|
||||||
"interest_date": "Data d'inter\u00e8s",
|
"interest_date": "Data d'inter\u00e8s",
|
||||||
"administration_currency": "Native currency",
|
"administration_currency": "Moneda nativa",
|
||||||
"title": "T\u00edtol",
|
"title": "T\u00edtol",
|
||||||
"date": "Data",
|
"date": "Data",
|
||||||
"book_date": "Data de registre",
|
"book_date": "Data de registre",
|
||||||
@@ -169,12 +169,12 @@
|
|||||||
"webhook_delivery": "Lliurament",
|
"webhook_delivery": "Lliurament",
|
||||||
"from_currency_to_currency": "{from} → {to}",
|
"from_currency_to_currency": "{from} → {to}",
|
||||||
"to_currency_from_currency": "{to} → {from}",
|
"to_currency_from_currency": "{to} → {from}",
|
||||||
"rate": "Rate"
|
"rate": "Taxa"
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
"title": "T\u00edtol",
|
"title": "T\u00edtol",
|
||||||
"active": "Est\u00e0 actiu?",
|
"active": "Est\u00e0 actiu?",
|
||||||
"native_currency": "Native currency",
|
"native_currency": "Moneda nativa",
|
||||||
"trigger": "Activador",
|
"trigger": "Activador",
|
||||||
"response": "Resposta",
|
"response": "Resposta",
|
||||||
"delivery": "Lliurament",
|
"delivery": "Lliurament",
|
||||||
|
|||||||
@@ -112,7 +112,7 @@
|
|||||||
"webhook_trigger_DESTROY_TRANSACTION": "After transaction delete",
|
"webhook_trigger_DESTROY_TRANSACTION": "After transaction delete",
|
||||||
"webhook_response_TRANSACTIONS": "Transaction details",
|
"webhook_response_TRANSACTIONS": "Transaction details",
|
||||||
"webhook_response_ACCOUNTS": "Account details",
|
"webhook_response_ACCOUNTS": "Account details",
|
||||||
"webhook_response_none_NONE": "No details",
|
"webhook_response_none_NONE": "Tidak ada detil",
|
||||||
"webhook_delivery_JSON": "JSON",
|
"webhook_delivery_JSON": "JSON",
|
||||||
"actions": "Tindakan",
|
"actions": "Tindakan",
|
||||||
"meta_data": "Data meta",
|
"meta_data": "Data meta",
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
"edit_webhook_js": "Edit webhook \"{title}\"",
|
"edit_webhook_js": "Edit webhook \"{title}\"",
|
||||||
"webhook_was_triggered": "The webhook was triggered on the indicated transaction. Please wait for results to appear.",
|
"webhook_was_triggered": "The webhook was triggered on the indicated transaction. Please wait for results to appear.",
|
||||||
"view_message": "View message",
|
"view_message": "View message",
|
||||||
"view_attempts": "View failed attempts",
|
"view_attempts": "Lihat upaya yang gagal",
|
||||||
"message_content_title": "Webhook message content",
|
"message_content_title": "Webhook message content",
|
||||||
"message_content_help": "This is the content of the message that was sent (or tried) using this webhook.",
|
"message_content_help": "This is the content of the message that was sent (or tried) using this webhook.",
|
||||||
"attempt_content_title": "Webhook attempts",
|
"attempt_content_title": "Webhook attempts",
|
||||||
@@ -137,7 +137,7 @@
|
|||||||
"no_attempts": "There are no unsuccessful attempts. That's a good thing!",
|
"no_attempts": "There are no unsuccessful attempts. That's a good thing!",
|
||||||
"webhook_attempt_at": "Attempt at {moment}",
|
"webhook_attempt_at": "Attempt at {moment}",
|
||||||
"logs": "Log",
|
"logs": "Log",
|
||||||
"response": "Response",
|
"response": "Tanggapan",
|
||||||
"visit_webhook_url": "Visit webhook URL",
|
"visit_webhook_url": "Visit webhook URL",
|
||||||
"reset_webhook_secret": "Reset webhook secret",
|
"reset_webhook_secret": "Reset webhook secret",
|
||||||
"header_exchange_rates": "Exchange rates",
|
"header_exchange_rates": "Exchange rates",
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
"apply_rules_checkbox": "Apply rules",
|
"apply_rules_checkbox": "Apply rules",
|
||||||
"fire_webhooks_checkbox": "Fire webhooks",
|
"fire_webhooks_checkbox": "Fire webhooks",
|
||||||
"no_budget_pointer": "Hen\u00fcz b\u00fct\u00e7eniz yok gibi g\u00f6r\u00fcn\u00fcyor. <a href=\"budgets\">b\u00fct\u00e7eler<\/a> sayfas\u0131nda biraz olu\u015fturmal\u0131s\u0131n\u0131z. B\u00fct\u00e7eler, giderleri takip etmenize yard\u0131mc\u0131 olabilir.",
|
"no_budget_pointer": "Hen\u00fcz b\u00fct\u00e7eniz yok gibi g\u00f6r\u00fcn\u00fcyor. <a href=\"budgets\">b\u00fct\u00e7eler<\/a> sayfas\u0131nda biraz olu\u015fturmal\u0131s\u0131n\u0131z. B\u00fct\u00e7eler, giderleri takip etmenize yard\u0131mc\u0131 olabilir.",
|
||||||
"no_bill_pointer": "You seem to have no subscription yet. You should create some on the <a href=\"subscriptions\">subscription<\/a>-page. Subscriptions can help you keep track of expenses.",
|
"no_bill_pointer": "Hen\u00fcz aboneli\u011finiz yok gibi g\u00f6r\u00fcn\u00fcyor. <a href=\"subscriptions\">Abonelik<\/a> sayfas\u0131nda bir abonelik olu\u015fturmal\u0131s\u0131n\u0131z. Abonelikler, harcamalar\u0131n\u0131z\u0131 takip etmenize yard\u0131mc\u0131 olabilir.",
|
||||||
"source_account": "Kaynak hesap",
|
"source_account": "Kaynak hesap",
|
||||||
"hidden_fields_preferences": "You can enable more transaction options in your <a href=\"preferences\">preferences<\/a>.",
|
"hidden_fields_preferences": "You can enable more transaction options in your <a href=\"preferences\">preferences<\/a>.",
|
||||||
"destination_account": "Hedef hesap",
|
"destination_account": "Hedef hesap",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"firefly": {
|
"firefly": {
|
||||||
"administrations_page_title": "\u8d22\u52a1\u7ba1\u7406",
|
"administrations_page_title": "\u8d22\u52a1\u7ba1\u7406",
|
||||||
"administrations_index_menu": "\u8d22\u52a1\u7ba1\u7406",
|
"administrations_index_menu": "\u8d22\u52a1\u7ba1\u7406",
|
||||||
"expires_at": "Expires at",
|
"expires_at": "\u8fc7\u671f\u4e8e",
|
||||||
"temp_administrations_introduction": "Firefly III \u4e0d\u4e45\u5c06\u80fd\u591f\u7ba1\u7406\u591a\u4e2a\u8d22\u52a1\u7ba1\u7406\u3002 \u73b0\u5728\uff0c\u4f60\u53ea\u80fd\u6709\u4e00\u4e2a\u8d22\u52a1\u7ba1\u7406\u3002\u4f60\u53ef\u4ee5\u8bbe\u7f6e\u8fd9\u4e2a\u8d22\u52a1\u7ba1\u7406\u7684\u6807\u9898\u53ca\u5176\u5f53\u5730\u8d27\u5e01\u3002 \u8fd9\u5c06\u53d6\u4ee3\u60a8\u5148\u524d\u8bbe\u7f6e\u7684\u201c\u9ed8\u8ba4\u8d27\u5e01\u201d\u3002 \u8fd9\u79cd\u8bbe\u7f6e\u73b0\u5728\u4e0e\u8d22\u52a1\u7ba1\u7406\u6302\u94a9\uff0c\u6bcf\u4e2a\u7ba1\u7406\u53ef\u4ee5\u6709\u4e0d\u540c\u7684\u8bbe\u7f6e\u3002",
|
"temp_administrations_introduction": "Firefly III \u4e0d\u4e45\u5c06\u80fd\u591f\u7ba1\u7406\u591a\u4e2a\u8d22\u52a1\u7ba1\u7406\u3002 \u73b0\u5728\uff0c\u4f60\u53ea\u80fd\u6709\u4e00\u4e2a\u8d22\u52a1\u7ba1\u7406\u3002\u4f60\u53ef\u4ee5\u8bbe\u7f6e\u8fd9\u4e2a\u8d22\u52a1\u7ba1\u7406\u7684\u6807\u9898\u53ca\u5176\u5f53\u5730\u8d27\u5e01\u3002 \u8fd9\u5c06\u53d6\u4ee3\u60a8\u5148\u524d\u8bbe\u7f6e\u7684\u201c\u9ed8\u8ba4\u8d27\u5e01\u201d\u3002 \u8fd9\u79cd\u8bbe\u7f6e\u73b0\u5728\u4e0e\u8d22\u52a1\u7ba1\u7406\u6302\u94a9\uff0c\u6bcf\u4e2a\u7ba1\u7406\u53ef\u4ee5\u6709\u4e0d\u540c\u7684\u8bbe\u7f6e\u3002",
|
||||||
"administration_currency_form_help": "\u5982\u679c\u60a8\u66f4\u6539\u672c\u5730\u8d27\u5e01\uff0c\u9875\u9762\u52a0\u8f7d\u53ef\u80fd\u9700\u8981\u5f88\u957f\u65f6\u95f4\uff0c\u56e0\u4e3a\u4ea4\u6613\u53ef\u80fd\u9700\u8981\u8f6c\u6362\u4e3a\u60a8\u7684(\u65b0)\u672c\u5730\u8d27\u5e01\u3002",
|
"administration_currency_form_help": "\u5982\u679c\u60a8\u66f4\u6539\u672c\u5730\u8d27\u5e01\uff0c\u9875\u9762\u52a0\u8f7d\u53ef\u80fd\u9700\u8981\u5f88\u957f\u65f6\u95f4\uff0c\u56e0\u4e3a\u4ea4\u6613\u53ef\u80fd\u9700\u8981\u8f6c\u6362\u4e3a\u60a8\u7684(\u65b0)\u672c\u5730\u8d27\u5e01\u3002",
|
||||||
"administrations_page_edit_sub_title_js": "\u7f16\u8f91\u8d22\u52a1\u7ba1\u7406{title}",
|
"administrations_page_edit_sub_title_js": "\u7f16\u8f91\u8d22\u52a1\u7ba1\u7406{title}",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -339,6 +339,7 @@
|
|||||||
{% if spentInfo.currency_id == budgetLimit.currency_id and budgetLimit.in_range %}
|
{% if spentInfo.currency_id == budgetLimit.currency_id and budgetLimit.in_range %}
|
||||||
{# the code below is used for budget limits INSIDE the current view range. #}
|
{# the code below is used for budget limits INSIDE the current view range. #}
|
||||||
{% set countLimit = countLimit + 1 %}
|
{% set countLimit = countLimit + 1 %}
|
||||||
|
|
||||||
<span class="left_span" data-currency="{{ spentInfo.currency_id }}" data-limit="{{ budgetLimit.id }}"
|
<span class="left_span" data-currency="{{ spentInfo.currency_id }}" data-limit="{{ budgetLimit.id }}"
|
||||||
data-value="{{ spentInfo.spent + budgetLimit.amount }}" class="amount_left">
|
data-value="{{ spentInfo.spent + budgetLimit.amount }}" class="amount_left">
|
||||||
{# the amount left is automatically calculated. #}
|
{# the amount left is automatically calculated. #}
|
||||||
@@ -356,7 +357,9 @@
|
|||||||
<br/>
|
<br/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if countLimit == 0 %}
|
{% if countLimit == 0 %}
|
||||||
|
|
||||||
{# this code is used for budget limits OUTSIDE the current view range. #}
|
{# this code is used for budget limits OUTSIDE the current view range. #}
|
||||||
<span class="left_span" data-id="{{ budget.id }}" data-currency="{{ spentInfo.currency_id }}" data-limit="0"
|
<span class="left_span" data-id="{{ budget.id }}" data-currency="{{ spentInfo.currency_id }}" data-limit="0"
|
||||||
class="amount_left" data-value="{{ spentInfo.spent }}">
|
class="amount_left" data-value="{{ spentInfo.spent }}">
|
||||||
@@ -377,6 +380,10 @@
|
|||||||
({{ formatAmountBySymbol(budgetLimit.amount / activeDaysLeft, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})
|
({{ formatAmountBySymbol(budgetLimit.amount / activeDaysLeft, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if not budgetLimit.in_range %}
|
||||||
|
{# For issue #10441, add per day if the budget limit is out of range. #}
|
||||||
|
({{ formatAmountBySymbol(budgetLimit.amount / budgetLimit.total_days, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})
|
||||||
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
<br/>
|
<br/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<label for="{{ options.id }}" class="col-sm-4 control-label">{{ label }}</label>
|
<label for="{{ options.id }}" class="col-sm-4 control-label">{{ label }}</label>
|
||||||
|
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
{{ Html.multiselect(name~"[]", list, selected).id(options.id).class('form-control').attribute('autocomplete','off').attribute('spellcheck','false').attribute('placeholder', options.placeholder) }}
|
{{ Html.multiselect(name~"[]", list, selected).id(options.id).attribute('size',12).class('form-control').attribute('autocomplete','off').attribute('spellcheck','false').attribute('placeholder', options.placeholder) }}
|
||||||
{% include 'form.help' %}
|
{% include 'form.help' %}
|
||||||
{% include 'form.feedback' %}
|
{% include 'form.feedback' %}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,13 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li class="{{ activeRouteStrict('search.index') }} visible-xs hidden-sm hidden-md hidden-lg">
|
||||||
|
<a href="{{ route('search.index') }}">
|
||||||
|
<em class="fa fa-search fa-fw"></em>
|
||||||
|
<span>{{ 'search'|_ }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="header text-uppercase">{{ 'financial_control'|_ }}</li>
|
<li class="header text-uppercase">{{ 'financial_control'|_ }}</li>
|
||||||
|
|
||||||
<li class="{{ activeRoutePartial('budgets') }}" id="budget-menu">
|
<li class="{{ activeRoutePartial('budgets') }}" id="budget-menu">
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user