Compare commits

..

59 Commits

Author SHA1 Message Date
James Cole
3bc98bee20 Merge branch 'release/v6.0.16' 2023-06-27 15:02:06 +02:00
James Cole
f6302bc29b Update meta data for new release. 2023-06-27 15:01:42 +02:00
James Cole
43aa1704a9 Slight refactor in CSS fix. 2023-06-27 14:08:21 +02:00
James Cole
14fe82e361 fix: #7655 2023-06-26 06:10:16 +02:00
James Cole
33317c15a2 Merge branch 'develop' of https://github.com/firefly-iii/firefly-iii into develop 2023-06-26 06:09:10 +02:00
James Cole
ff1b56c5ef chore: update php cs fixer 2023-06-26 06:08:33 +02:00
James Cole
25e2063d70 Merge pull request #7690 from firefly-iii/dependabot/composer/develop/doctrine/dbal-3.6.4
chore(deps): bump doctrine/dbal from 3.6.3 to 3.6.4
2023-06-26 05:59:15 +02:00
James Cole
1d36c74934 Merge pull request #7689 from firefly-iii/dependabot/composer/develop/phpstan/phpstan-1.10.21
chore(deps-dev): bump phpstan/phpstan from 1.10.20 to 1.10.21
2023-06-26 05:59:06 +02:00
James Cole
aebe7908f0 Merge pull request #7687 from MateusBMP/develop
Low contrast ratio on .skin-firefly-iii .btn-info color with dark theme
2023-06-26 05:58:34 +02:00
dependabot[bot]
3e2b881296 chore(deps): bump doctrine/dbal from 3.6.3 to 3.6.4
Bumps [doctrine/dbal](https://github.com/doctrine/dbal) from 3.6.3 to 3.6.4.
- [Release notes](https://github.com/doctrine/dbal/releases)
- [Commits](https://github.com/doctrine/dbal/compare/3.6.3...3.6.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-26 03:56:30 +00:00
dependabot[bot]
c670a6991d chore(deps-dev): bump phpstan/phpstan from 1.10.20 to 1.10.21
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.20 to 1.10.21.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.20...1.10.21)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-26 03:56:24 +00:00
Mateus Pereira
f76a7d59e0 Updating .btn-info color to #fff (issue #7686) 2023-06-25 19:43:09 -03:00
James Cole
3d8bf3ec9b Fix #7683 2023-06-25 06:24:08 +02:00
Sander Dorigo
55e4479454 fix #7683 2023-06-24 21:00:05 +02:00
Sander Dorigo
436fe9fea4 Improve transaction validation 2023-06-24 08:27:28 +02:00
Sander Dorigo
63a7a4b03b New version 2023-06-23 11:07:50 +02:00
Sander Dorigo
0cab974048 Extended IBAN validation 2023-06-23 10:57:26 +02:00
James Cole
5fdcf37d06 Merge tag 'v6.0.15' into develop
v6.0.15
2023-06-21 13:13:11 +02:00
James Cole
4663fb2f12 Merge branch 'release/v6.0.15' 2023-06-21 13:13:10 +02:00
James Cole
e844ab592d Update meta data for release v6.0.15 2023-06-21 13:11:08 +02:00
James Cole
3dcb35710b chore: reformat code. 2023-06-21 12:34:58 +02:00
James Cole
8d87abde64 Fix https://github.com/firefly-iii/firefly-iii/issues/7678 2023-06-21 09:58:37 +02:00
James Cole
2b78485a61 Cleanup edit thing 2023-06-21 07:39:00 +02:00
James Cole
9d057b853f Rule edit form: rule group would always select the top one. 2023-06-21 07:30:08 +02:00
James Cole
bd269eaadf Merge tag 'v6.0.14' into develop
v6.0.14
2023-06-21 07:15:29 +02:00
James Cole
7096c65f50 Merge branch 'release/v6.0.14' 2023-06-21 07:15:28 +02:00
James Cole
1462b0de69 Update meta data for release 6.0.14 2023-06-21 06:40:41 +02:00
James Cole
86a1f170c4 Catch uneven amounts 2023-06-21 06:07:35 +02:00
James Cole
40389fb6d5 fix #7649 2023-06-21 06:06:06 +02:00
James Cole
36021d84cf Fix attachment overview 2023-06-21 06:04:26 +02:00
James Cole
1278f92355 Fix audit log entries and fix #7677 2023-06-21 05:55:57 +02:00
James Cole
573f9adb49 Merge pull request #7676 from timendum/master
Rule ConvertToDeposit: fix missing parameter
2023-06-20 20:03:57 +02:00
Timendum
431c99c27b Rule ConvertToDeposit: fix missing parameter 2023-06-20 15:31:49 +00:00
James Cole
77cc558931 chore: code cleanup 2023-06-20 07:20:26 +02:00
James Cole
42043de34f fix: replace console messages with unified command. 2023-06-20 07:16:56 +02:00
James Cole
f2b2c2109f Merge pull request #7668 from firefly-iii/dependabot/composer/develop/predis/predis-2.2.0 2023-06-19 07:15:54 +02:00
dependabot[bot]
7fe29ad983 Bump predis/predis from 2.1.2 to 2.2.0
Bumps [predis/predis](https://github.com/predis/predis) from 2.1.2 to 2.2.0.
- [Release notes](https://github.com/predis/predis/releases)
- [Changelog](https://github.com/predis/predis/blob/v2.x/CHANGELOG.md)
- [Commits](https://github.com/predis/predis/compare/v2.1.2...v2.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 05:13:33 +00:00
James Cole
07d9bcfb9d Merge pull request #7671 from firefly-iii/dependabot/composer/develop/phpstan/phpstan-1.10.19 2023-06-19 07:07:51 +02:00
James Cole
fdd235e4cb Merge pull request #7670 from firefly-iii/dependabot/composer/develop/nunomaduro/larastan-2.6.3 2023-06-19 07:07:42 +02:00
James Cole
2646acadb8 Merge pull request #7669 from firefly-iii/dependabot/composer/develop/fakerphp/faker-1.23.0 2023-06-19 07:07:33 +02:00
James Cole
5ef646b810 Merge pull request #7667 from firefly-iii/dependabot/composer/develop/nunomaduro/collision-7.6.0 2023-06-19 07:07:15 +02:00
dependabot[bot]
e8bdb5ef38 Bump phpstan/phpstan from 1.10.18 to 1.10.19
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.18 to 1.10.19.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.18...1.10.19)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 03:56:57 +00:00
dependabot[bot]
7a851c2cc6 Bump nunomaduro/larastan from 2.6.2 to 2.6.3
Bumps [nunomaduro/larastan](https://github.com/nunomaduro/larastan) from 2.6.2 to 2.6.3.
- [Release notes](https://github.com/nunomaduro/larastan/releases)
- [Changelog](https://github.com/nunomaduro/larastan/blob/master/RELEASE.md)
- [Commits](https://github.com/nunomaduro/larastan/compare/v2.6.2...v2.6.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 03:56:49 +00:00
dependabot[bot]
624784e54e Bump fakerphp/faker from 1.22.0 to 1.23.0
Bumps [fakerphp/faker](https://github.com/FakerPHP/Faker) from 1.22.0 to 1.23.0.
- [Release notes](https://github.com/FakerPHP/Faker/releases)
- [Changelog](https://github.com/FakerPHP/Faker/blob/main/CHANGELOG.md)
- [Commits](https://github.com/FakerPHP/Faker/compare/v1.22.0...v1.23.0)

---
updated-dependencies:
- dependency-name: fakerphp/faker
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 03:56:38 +00:00
dependabot[bot]
20eb2ebe58 Bump nunomaduro/collision from 7.5.2 to 7.6.0
Bumps [nunomaduro/collision](https://github.com/nunomaduro/collision) from 7.5.2 to 7.6.0.
- [Changelog](https://github.com/nunomaduro/collision/blob/v7.x/CHANGELOG.md)
- [Commits](https://github.com/nunomaduro/collision/compare/v7.5.2...v7.6.0)

---
updated-dependencies:
- dependency-name: nunomaduro/collision
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 03:56:28 +00:00
James Cole
25f8acb417 Chore: use of else in accountform 2023-06-18 06:26:50 +02:00
James Cole
f75e6430b1 Fix: nullpointer in billrepository. 2023-06-18 06:26:38 +02:00
James Cole
e72a483c49 Merge pull request #7656 from firefly-iii/fix-7609
Fix #7609
2023-06-14 18:45:14 +02:00
James Cole
68934858ce Fix #7609 2023-06-14 18:44:54 +02:00
James Cole
c08b5177d9 Merge pull request #7647 from firefly-iii/account-validation
Fix account validation
2023-06-12 20:25:08 +02:00
James Cole
fe8635f1ce Fix account validation 2023-06-12 20:24:45 +02:00
James Cole
e96d28b981 Merge pull request #7645 from firefly-iii/fix-7642
Fix #7642
2023-06-12 06:31:25 +02:00
James Cole
784cc3d52d Fix #7642 2023-06-12 06:31:03 +02:00
James Cole
2ab3fb3a71 Merge pull request #7644 from firefly-iii/fix-7630
Fix #7630
2023-06-12 06:24:46 +02:00
James Cole
ff765d4687 Fix #7630 2023-06-12 06:24:30 +02:00
James Cole
f6e778e1d4 Merge branch 'release/v6.0.13' 2023-06-11 18:19:07 +02:00
James Cole
ed36604050 Merge tag 'v6.0.13' into develop
v6.0.13
2023-06-11 18:19:07 +02:00
James Cole
cbf8c6e80d Release v6.0.13 fixes an issue with the authentication controllers. 2023-06-11 18:18:46 +02:00
James Cole
f11db0de61 Merge tag 'v6.0.12' into develop
v6.0.12
2023-06-11 16:34:31 +02:00
978 changed files with 27550 additions and 20672 deletions

View File

@@ -51,8 +51,8 @@ services:
# Looks for unused imports from other namespaces. # Looks for unused imports from other namespaces.
Nette\CodingStandard\Sniffs\Namespaces\UnusedUsesSniff: Nette\CodingStandard\Sniffs\Namespaces\UnusedUsesSniff:
searchAnnotations: yes searchAnnotations: yes
ignoredAnnotationNames: ['@testCase'] ignoredAnnotationNames: [ '@testCase' ]
ignoredAnnotations: ['@internal'] ignoredAnnotations: [ '@internal' ]
# Language Construct (should be placed before some other fixers) # Language Construct (should be placed before some other fixers)
@@ -134,7 +134,7 @@ services:
# There MUST NOT be more than one property declared per statement. # There MUST NOT be more than one property declared per statement.
PhpCsFixer\Fixer\ClassNotation\SingleClassElementPerStatementFixer: PhpCsFixer\Fixer\ClassNotation\SingleClassElementPerStatementFixer:
elements: ['property'] elements: [ 'property' ]
# Methods - https://nette.org/en/coding-standard#toc-methods # Methods - https://nette.org/en/coding-standard#toc-methods
@@ -224,7 +224,7 @@ services:
PhpCsFixer\Fixer\Phpdoc\PhpdocTrimFixer: ~ PhpCsFixer\Fixer\Phpdoc\PhpdocTrimFixer: ~
# Single-line comments comments with only one line of actual content should use the `//` syntax. # Single-line comments comments with only one line of actual content should use the `//` syntax.
PhpCsFixer\Fixer\Comment\SingleLineCommentStyleFixer: PhpCsFixer\Fixer\Comment\SingleLineCommentStyleFixer:
comment_types: ['hash'] comment_types: [ 'hash' ]
# Require comments with single-line content to be written as one-liners # Require comments with single-line content to be written as one-liners
SlevomatCodingStandard\Sniffs\Commenting\RequireOneLinePropertyDocCommentSniff: ~ SlevomatCodingStandard\Sniffs\Commenting\RequireOneLinePropertyDocCommentSniff: ~
@@ -243,7 +243,7 @@ services:
PhpCsFixer\Fixer\Operator\TernaryToNullCoalescingFixer: ~ PhpCsFixer\Fixer\Operator\TernaryToNullCoalescingFixer: ~
Nette\CodingStandard\Fixer\ClassNotation\ClassAndTraitVisibilityRequiredFixer: Nette\CodingStandard\Fixer\ClassNotation\ClassAndTraitVisibilityRequiredFixer:
elements: ['const', 'property', 'method'] elements: [ 'const', 'property', 'method' ]
# short list() syntax [] # short list() syntax []
PhpCsFixer\Fixer\ListNotation\ListSyntaxFixer: PhpCsFixer\Fixer\ListNotation\ListSyntaxFixer:

View File

@@ -1 +1,2 @@
vendor vendor
.php-cs-fixer.cache

View File

@@ -22,12 +22,12 @@
$current = __DIR__; $current = __DIR__;
$paths = [ $paths = [
$current.'/../../app', $current . '/../../app',
$current.'/../../config', $current . '/../../config',
$current.'/../../database', $current . '/../../database',
$current.'/../../routes', $current . '/../../routes',
$current.'/../../tests', $current . '/../../tests',
$current.'/../../resources/lang', $current . '/../../resources/lang',
]; ];
$finder = PhpCsFixer\Finder::create() $finder = PhpCsFixer\Finder::create()
@@ -40,5 +40,5 @@ return $config->setRules([
'declare_strict_types' => true, 'declare_strict_types' => true,
'strict_param' => true, 'strict_param' => true,
'array_syntax' => ['syntax' => 'short'], 'array_syntax' => ['syntax' => 'short'],
]) ])
->setFinder($finder); ->setFinder($finder);

View File

@@ -379,16 +379,16 @@
}, },
{ {
"name": "friendsofphp/php-cs-fixer", "name": "friendsofphp/php-cs-fixer",
"version": "v3.17.0", "version": "v3.19.2",
"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": "3f0ed862f22386c55a767461ef5083bddceeed79" "reference": "210dd89560edb27a8e0d5086b734ac5b5fd4e0e4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/3f0ed862f22386c55a767461ef5083bddceeed79", "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/210dd89560edb27a8e0d5086b734ac5b5fd4e0e4",
"reference": "3f0ed862f22386c55a767461ef5083bddceeed79", "reference": "210dd89560edb27a8e0d5086b734ac5b5fd4e0e4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -463,7 +463,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.17.0" "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.19.2"
}, },
"funding": [ "funding": [
{ {
@@ -471,7 +471,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-05-22T19:59:32+00:00" "time": "2023-06-25T16:42:58+00:00"
}, },
{ {
"name": "psr/cache", "name": "psr/cache",
@@ -1057,16 +1057,16 @@
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
"version": "v6.3.0", "version": "v6.3.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/filesystem.git", "url": "https://github.com/symfony/filesystem.git",
"reference": "97b698e1d77d356304def77a8d0cd73090b359ea" "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/97b698e1d77d356304def77a8d0cd73090b359ea", "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
"reference": "97b698e1d77d356304def77a8d0cd73090b359ea", "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1100,7 +1100,7 @@
"description": "Provides basic utilities for the filesystem", "description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/filesystem/tree/v6.3.0" "source": "https://github.com/symfony/filesystem/tree/v6.3.1"
}, },
"funding": [ "funding": [
{ {
@@ -1116,7 +1116,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-05-30T17:12:32+00:00" "time": "2023-06-01T08:30:39+00:00"
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",

View File

@@ -30,12 +30,9 @@ SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# clean up php code # clean up php code
cd $SCRIPT_DIR/php-cs-fixer cd $SCRIPT_DIR/php-cs-fixer
composer update composer update --quiet
rm -f .php-cs-fixer.cache rm -f .php-cs-fixer.cache
echo 'Removed cache...'
echo 'Running...'
PHP_CS_FIXER_IGNORE_ENV=true ./vendor/bin/php-cs-fixer fix --config $SCRIPT_DIR/php-cs-fixer/.php-cs-fixer.php --allow-risky=yes PHP_CS_FIXER_IGNORE_ENV=true ./vendor/bin/php-cs-fixer fix --config $SCRIPT_DIR/php-cs-fixer/.php-cs-fixer.php --allow-risky=yes
echo 'Done!'
cd $SCRIPT_DIR/.. cd $SCRIPT_DIR/..
exit 0 exit 0

37
.ci/phpmd.sh Normal file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/env bash
#
# phpmd.sh
# Copyright (c) 2023 james@firefly-iii.org
#
# This file is part of Firefly III (https://github.com/firefly-iii).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
cd $SCRIPT_DIR/phpmd
composer update --quiet
./vendor/bin/phpmd \
$SCRIPT_DIR/../app text phpmd.xml \
--exclude $SCRIPT_DIR/../app/resources/** \
--exclude $SCRIPT_DIR/../app/frontend/** \
--exclude $SCRIPT_DIR/../app/public/** \
--exclude $SCRIPT_DIR/../app/vendor/** \
cd $SCRIPT_DIR/..
exit 0

1
.ci/phpmd/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
vendor

5
.ci/phpmd/composer.json Normal file
View File

@@ -0,0 +1,5 @@
{
"require-dev": {
"phpmd/phpmd": "^2.13"
}
}

1012
.ci/phpmd/composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

52
.ci/phpmd/phpmd.xml Normal file
View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="pcsg-generated-ruleset"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>Bla bla</description>
<!--
Commando vanuit firefly directory:
phpmd database,app,tests html /gdrive-all/development/phpmd/phpmd.xml > public/report.html
-->
<!-- Import the entire controversial code rule set -->
<rule ref="rulesets/controversial.xml">
<exclude name="CamelCasePropertyName" />
</rule>
<!-- clean code -->
<rule ref="rulesets/codesize.xml" />
<rule ref="rulesets/design.xml" />
<rule ref="rulesets/naming.xml" />
<rule ref="rulesets/unusedcode.xml" />
<rule ref="rulesets/codesize.xml/CyclomaticComplexity">
<properties>
<property name="reportLevel" value="5"/>
</properties>
</rule>
<rule ref="rulesets/codesize.xml/NPathComplexity">
<properties>
<property name="minimum" value="128"/>
</properties>
</rule>
<rule ref="rulesets/codesize.xml/ExcessiveMethodLength">
<properties>
<property name="minimum" value="40"/>
</properties>
</rule>
<rule ref="rulesets/codesize.xml/ExcessiveParameterList">
<properties>
<property name="minimum" value="5"/>
</properties>
</rule>
<!-- include clean code manually -->
<rule ref="rulesets/cleancode.xml/BooleanArgumentFlag" />
<rule ref="rulesets/cleancode.xml/ElseExpression" />
<!-- no this one -->
<!--<rule ref="rulesets/cleancode.xml/StaticAccess" />-->
</ruleset>

View File

@@ -59,3 +59,5 @@ fi
# restore .env file # restore .env file
mv $SCRIPT_DIR/../.env.backup $SCRIPT_DIR/../.env mv $SCRIPT_DIR/../.env.backup $SCRIPT_DIR/../.env
cd $SCRIPT_DIR/..

View File

@@ -16,6 +16,7 @@ ja_JP
ko_KR ko_KR
nb_NO nb_NO
nl_NL nl_NL
nn_NO
pl_PL pl_PL
pt_BR pt_BR
pt_PT pt_PT

View File

@@ -143,6 +143,7 @@ MAIL_FROM=changeme@example.com
MAIL_USERNAME=null MAIL_USERNAME=null
MAIL_PASSWORD=null MAIL_PASSWORD=null
MAIL_ENCRYPTION=null MAIL_ENCRYPTION=null
MAIL_SENDMAIL_COMMAND=
# Other mail drivers: # Other mail drivers:
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE # If you use Docker or similar, you can set these variables from a file by appending them with _FILE

View File

@@ -2,7 +2,10 @@
## Our Pledge ## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making
participation in our project and our community a harassment-free experience for everyone, regardless of age, body size,
disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race,
religion, or sexual identity and orientation.
## Our Standards ## Our Standards
@@ -24,23 +27,35 @@ Examples of unacceptable behavior by participants include:
## Our Responsibilities ## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take
appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits,
issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any
contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope ## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the
project or its community. Examples of representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed representative at an online or offline
event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement ## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at james@firefly-iii.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at
james@firefly-iii.org. The project team will review and investigate all complaints, and will respond in a way that it
deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the
reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent
repercussions as determined by other members of the project's leadership.
## Attribution ## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available
at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org [homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/ [version]: http://contributor-covenant.org/version/1/4/

View File

@@ -5,7 +5,7 @@ updates:
- package-ecosystem: "composer" - package-ecosystem: "composer"
directory: "/" # Location of package manifests directory: "/" # Location of package manifests
target-branch: develop target-branch: develop
labels: ["bug"] labels: [ "bug" ]
versioning-strategy: increase versioning-strategy: increase
schedule: schedule:
interval: "weekly" interval: "weekly"
@@ -14,7 +14,7 @@ updates:
- package-ecosystem: "npm" - package-ecosystem: "npm"
directory: "/" directory: "/"
target-branch: develop target-branch: develop
labels: ["bug"] labels: [ "bug" ]
versioning-strategy: increase versioning-strategy: increase
schedule: schedule:
interval: "weekly" interval: "weekly"
@@ -22,7 +22,7 @@ updates:
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"
directory: "/" directory: "/"
target-branch: develop target-branch: develop
labels: ["bug"] labels: [ "bug" ]
versioning-strategy: increase versioning-strategy: increase
schedule: schedule:
interval: "weekly" interval: "weekly"

View File

@@ -2,9 +2,11 @@
Sometimes bugs reported to Firefly III are configuration and system problems on the user's side. Sometimes bugs reported to Firefly III are configuration and system problems on the user's side.
If you run into any of the following problems, there's a good chance it's not a Firefly III issue, but a configuration issue. If you run into any of the following problems, there's a good chance it's not a Firefly III issue, but a configuration
issue.
- ⚠️ Firefly III can't connect to the database when starting or the password is wrong, even though you're sure it's correct. - ⚠️ Firefly III can't connect to the database when starting or the password is wrong, even though you're sure it's
correct.
- ⚠️ Errors about a missing `APP_KEY` or other encryption/hash problems - ⚠️ Errors about a missing `APP_KEY` or other encryption/hash problems
- ⚠️ You can't login due to `419` errors (page expired) - ⚠️ You can't login due to `419` errors (page expired)
- ⚠️ Any `500` error when starting Firefly III - ⚠️ Any `500` error when starting Firefly III
@@ -13,4 +15,6 @@ If you run into any of the following problems, there's a good chance it's not a
- ⚠️ Firefly III does not work behind your reverse proxy - ⚠️ Firefly III does not work behind your reverse proxy
- ⚠️ You can't connect to the Data Importer due to 404's or authentication issues. - ⚠️ You can't connect to the Data Importer due to 404's or authentication issues.
If you run into an issue like this, please start a [discussion](https://github.com/firefly-iii/firefly-iii/discussions) or chat on [Gitter.im](https://gitter.im/firefly-iii/firefly-iii). There's a good chance it's not a bug but something we can fix rather quickly :+1: If you run into an issue like this, please start a [discussion](https://github.com/firefly-iii/firefly-iii/discussions)
or chat on [Gitter.im](https://gitter.im/firefly-iii/firefly-iii). There's a good chance it's not a bug but something we
can fix rather quickly :+1:

6
.github/support.md vendored
View File

@@ -9,7 +9,8 @@ First of all: thank you for reporting a bug instead of ditching the tool altoget
1. Open bugs will have open issues, so search for one first. 1. Open bugs will have open issues, so search for one first.
2. If your feature request is already there, vote on it with :+1: or :-1: reactions. 2. If your feature request is already there, vote on it with :+1: or :-1: reactions.
3. Do NOT hijack old issues with the bug you found, open your own issue. 3. Do NOT hijack old issues with the bug you found, open your own issue.
4. If relevant, take the time and see if the [demo site](https://demo.firefly-iii.org/) is also suffering from your issue. 4. If relevant, take the time and see if the [demo site](https://demo.firefly-iii.org/) is also suffering from your
issue.
5. If relevant, read the [documentation](https://docs.firefly-iii.org/). 5. If relevant, read the [documentation](https://docs.firefly-iii.org/).
Please follow these guidelines when opening new issues: Please follow these guidelines when opening new issues:
@@ -25,7 +26,8 @@ Only then [create a new issue](https://github.com/firefly-iii/firefly-iii/issues
## Issue closure and abandonment policy ## Issue closure and abandonment policy
- Issues can be converted into discussions if it's not a bug or feature request. - Issues can be converted into discussions if it's not a bug or feature request.
- Features that won't be implemented will be labelled "wontfix". [This isn't personal](https://docs.firefly-iii.org/firefly-iii/about-firefly-iii/what-its-not/). - Features that won't be implemented will be labelled "
wontfix". [This isn't personal](https://docs.firefly-iii.org/firefly-iii/about-firefly-iii/what-its-not/).
- Issues can be closed if they're duplicates of other issues. - Issues can be closed if they're duplicates of other issues.
- Issues can be closed if the answer is in the FAQ. - Issues can be closed if the answer is in the FAQ.
- Issues will be closed automatically after 14 days. - Issues will be closed automatically after 14 days.

View File

@@ -7,8 +7,7 @@ jobs:
auto_comment: auto_comment:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- - uses: aws-actions/closed-issue-message@v1
uses: aws-actions/closed-issue-message@v1
with: with:
message: | message: |
Hi there! This is an automatic reply. `Share and enjoy` Hi there! This is an automatic reply. `Share and enjoy`

View File

@@ -1,5 +1,5 @@
name: 'Dependency Review' name: 'Dependency Review'
on: [pull_request] on: [ pull_request ]
permissions: permissions:
contents: read contents: read

View File

@@ -74,42 +74,6 @@ abstract class Controller extends BaseController
); );
} }
/**
* Method to help build URL's.
*
* @return string
*/
final protected function buildParams(): string
{
$return = '?';
$params = [];
foreach ($this->parameters as $key => $value) {
if ('page' === $key) {
continue;
}
if ($value instanceof Carbon) {
$params[$key] = $value->format('Y-m-d');
continue;
}
$params[$key] = $value;
}
return $return.http_build_query($params);
}
/**
* @return Manager
*/
final protected function getManager(): Manager
{
// create some objects:
$manager = new Manager();
$baseUrl = request()->getSchemeAndHttpHost().'/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
return $manager;
}
/** /**
* Method to grab all parameters from the URL. * Method to grab all parameters from the URL.
* *
@@ -144,7 +108,7 @@ abstract class Controller extends BaseController
if (null !== $date) { if (null !== $date) {
try { try {
$obj = Carbon::parse($date); $obj = Carbon::parse($date);
} catch (InvalidDateException|InvalidFormatException $e) { } catch (InvalidDateException | InvalidFormatException $e) {
// don't care // don't care
app('log')->warning( app('log')->warning(
sprintf( sprintf(
@@ -211,4 +175,40 @@ abstract class Controller extends BaseController
return $bag; return $bag;
} }
/**
* Method to help build URL's.
*
* @return string
*/
final protected function buildParams(): string
{
$return = '?';
$params = [];
foreach ($this->parameters as $key => $value) {
if ('page' === $key) {
continue;
}
if ($value instanceof Carbon) {
$params[$key] = $value->format('Y-m-d');
continue;
}
$params[$key] = $value;
}
return $return . http_build_query($params);
}
/**
* @return Manager
*/
final protected function getManager(): Manager
{
// create some objects:
$manager = new Manager();
$baseUrl = request()->getSchemeAndHttpHost() . '/api/v1';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
return $manager;
}
} }

View File

@@ -201,6 +201,91 @@ class DestroyController extends Controller
return response()->json([], 204); return response()->json([], 204);
} }
/**
*
*/
private function destroyBudgets(): void
{
/** @var AvailableBudgetRepositoryInterface $abRepository */
$abRepository = app(AvailableBudgetRepositoryInterface::class);
$abRepository->destroyAll();
/** @var BudgetLimitRepositoryInterface $blRepository */
$blRepository = app(BudgetLimitRepositoryInterface::class);
$blRepository->destroyAll();
/** @var BudgetRepositoryInterface $budgetRepository */
$budgetRepository = app(BudgetRepositoryInterface::class);
$budgetRepository->destroyAll();
}
/**
*
*/
private function destroyBills(): void
{
/** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyPiggyBanks(): void
{
/** @var PiggyBankRepositoryInterface $repository */
$repository = app(PiggyBankRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyRules(): void
{
/** @var RuleGroupRepositoryInterface $repository */
$repository = app(RuleGroupRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyRecurringTransactions(): void
{
/** @var RecurringRepositoryInterface $repository */
$repository = app(RecurringRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyCategories(): void
{
/** @var CategoryRepositoryInterface $categoryRepos */
$categoryRepos = app(CategoryRepositoryInterface::class);
$categoryRepos->destroyAll();
}
/**
*
*/
private function destroyTags(): void
{
/** @var TagRepositoryInterface $tagRepository */
$tagRepository = app(TagRepositoryInterface::class);
$tagRepository->destroyAll();
}
private function destroyObjectGroups(): void
{
/** @var ObjectGroupRepositoryInterface $repository */
$repository = app(ObjectGroupRepositoryInterface::class);
$repository->deleteAll();
}
/** /**
* @param array $types * @param array $types
*/ */
@@ -226,91 +311,6 @@ class DestroyController extends Controller
} }
} }
/**
*
*/
private function destroyBills(): void
{
/** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyBudgets(): void
{
/** @var AvailableBudgetRepositoryInterface $abRepository */
$abRepository = app(AvailableBudgetRepositoryInterface::class);
$abRepository->destroyAll();
/** @var BudgetLimitRepositoryInterface $blRepository */
$blRepository = app(BudgetLimitRepositoryInterface::class);
$blRepository->destroyAll();
/** @var BudgetRepositoryInterface $budgetRepository */
$budgetRepository = app(BudgetRepositoryInterface::class);
$budgetRepository->destroyAll();
}
/**
*
*/
private function destroyCategories(): void
{
/** @var CategoryRepositoryInterface $categoryRepos */
$categoryRepos = app(CategoryRepositoryInterface::class);
$categoryRepos->destroyAll();
}
private function destroyObjectGroups(): void
{
/** @var ObjectGroupRepositoryInterface $repository */
$repository = app(ObjectGroupRepositoryInterface::class);
$repository->deleteAll();
}
/**
*
*/
private function destroyPiggyBanks(): void
{
/** @var PiggyBankRepositoryInterface $repository */
$repository = app(PiggyBankRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyRecurringTransactions(): void
{
/** @var RecurringRepositoryInterface $repository */
$repository = app(RecurringRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyRules(): void
{
/** @var RuleGroupRepositoryInterface $repository */
$repository = app(RuleGroupRepositoryInterface::class);
$repository->destroyAll();
}
/**
*
*/
private function destroyTags(): void
{
/** @var TagRepositoryInterface $tagRepository */
$tagRepository = app(TagRepositoryInterface::class);
$tagRepository->destroyAll();
}
/** /**
* @param array $types * @param array $types
*/ */

View File

@@ -69,6 +69,34 @@ class ExportController extends Controller
return $this->returnExport('accounts'); return $this->returnExport('accounts');
} }
/**
* @param string $key
*
* @return LaravelResponse
* @throws FireflyException
*/
private function returnExport(string $key): LaravelResponse
{
$date = date('Y-m-d-H-i-s');
$fileName = sprintf('%s-export-%s.csv', $date, $key);
$data = $this->exporter->export();
/** @var LaravelResponse $response */
$response = response($data[$key]);
$response
->header('Content-Description', 'File Transfer')
->header('Content-Type', 'application/octet-stream')
->header('Content-Disposition', 'attachment; filename=' . $fileName)
->header('Content-Transfer-Encoding', 'binary')
->header('Connection', 'Keep-Alive')
->header('Expires', '0')
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
->header('Pragma', 'public')
->header('Content-Length', (string)strlen($data[$key]));
return $response;
}
/** /**
* This endpoint is documented at: * This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/exportBills * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/exportBills
@@ -200,32 +228,4 @@ class ExportController extends Controller
return $this->returnExport('transactions'); return $this->returnExport('transactions');
} }
/**
* @param string $key
*
* @return LaravelResponse
* @throws FireflyException
*/
private function returnExport(string $key): LaravelResponse
{
$date = date('Y-m-d-H-i-s');
$fileName = sprintf('%s-export-%s.csv', $date, $key);
$data = $this->exporter->export();
/** @var LaravelResponse $response */
$response = response($data[$key]);
$response
->header('Content-Description', 'File Transfer')
->header('Content-Type', 'application/octet-stream')
->header('Content-Disposition', 'attachment; filename='.$fileName)
->header('Content-Transfer-Encoding', 'binary')
->header('Connection', 'Keep-Alive')
->header('Expires', '0')
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
->header('Pragma', 'public')
->header('Content-Length', (string)strlen($data[$key]));
return $response;
}
} }

View File

@@ -89,7 +89,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.accounts.attachments', [$account->id]).$this->buildParams()); $paginator->setPath(route('api.v1.accounts.attachments', [$account->id]) . $this->buildParams());
/** @var AttachmentTransformer $transformer */ /** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class); $transformer = app(AttachmentTransformer::class);
@@ -125,7 +125,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.accounts.piggy-banks', [$account->id]).$this->buildParams()); $paginator->setPath(route('api.v1.accounts.piggy-banks', [$account->id]) . $this->buildParams());
/** @var PiggyBankTransformer $transformer */ /** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class); $transformer = app(PiggyBankTransformer::class);
@@ -177,7 +177,7 @@ class ListController extends Controller
} }
$paginator = $collector->getPaginatedGroups(); $paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.accounts.transactions', [$account->id]).$this->buildParams()); $paginator->setPath(route('api.v1.accounts.transactions', [$account->id]) . $this->buildParams());
$groups = $paginator->getCollection(); $groups = $paginator->getCollection();
/** @var TransactionGroupTransformer $transformer */ /** @var TransactionGroupTransformer $transformer */

View File

@@ -98,7 +98,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.accounts.index').$this->buildParams()); $paginator->setPath(route('api.v1.accounts.index') . $this->buildParams());
/** @var AccountTransformer $transformer */ /** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class); $transformer = app(AccountTransformer::class);

View File

@@ -75,7 +75,7 @@ class UpdateController extends Controller
{ {
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);
$manager = $this->getManager(); $manager = $this->getManager();
$account->refresh(); $account->refresh();

View File

@@ -96,7 +96,7 @@ class ShowController extends Controller
$response $response
->header('Content-Description', 'File Transfer') ->header('Content-Description', 'File Transfer')
->header('Content-Type', 'application/octet-stream') ->header('Content-Type', 'application/octet-stream')
->header('Content-Disposition', 'attachment; filename='.$quoted) ->header('Content-Disposition', 'attachment; filename=' . $quoted)
->header('Content-Transfer-Encoding', 'binary') ->header('Content-Transfer-Encoding', 'binary')
->header('Connection', 'Keep-Alive') ->header('Connection', 'Keep-Alive')
->header('Expires', '0') ->header('Expires', '0')
@@ -132,7 +132,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.attachments.index').$this->buildParams()); $paginator->setPath(route('api.v1.attachments.index') . $this->buildParams());
/** @var AttachmentTransformer $transformer */ /** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class); $transformer = app(AttachmentTransformer::class);

View File

@@ -88,7 +88,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.available-budgets.index').$this->buildParams()); $paginator->setPath(route('api.v1.available-budgets.index') . $this->buildParams());
/** @var AvailableBudgetTransformer $transformer */ /** @var AvailableBudgetTransformer $transformer */
$transformer = app(AvailableBudgetTransformer::class); $transformer = app(AvailableBudgetTransformer::class);

View File

@@ -88,7 +88,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.bills.attachments', [$bill->id]).$this->buildParams()); $paginator->setPath(route('api.v1.bills.attachments', [$bill->id]) . $this->buildParams());
/** @var AttachmentTransformer $transformer */ /** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class); $transformer = app(AttachmentTransformer::class);
@@ -125,7 +125,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.bills.rules', [$bill->id]).$this->buildParams()); $paginator->setPath(route('api.v1.bills.rules', [$bill->id]) . $this->buildParams());
/** @var RuleTransformer $transformer */ /** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class); $transformer = app(RuleTransformer::class);
@@ -184,7 +184,7 @@ class ListController extends Controller
// get paginator. // get paginator.
$paginator = $collector->getPaginatedGroups(); $paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.bills.transactions', [$bill->id]).$this->buildParams()); $paginator->setPath(route('api.v1.bills.transactions', [$bill->id]) . $this->buildParams());
$transactions = $paginator->getCollection(); $transactions = $paginator->getCollection();
/** @var TransactionGroupTransformer $transformer */ /** @var TransactionGroupTransformer $transformer */

View File

@@ -90,7 +90,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budgets.attachments', [$budget->id]).$this->buildParams()); $paginator->setPath(route('api.v1.budgets.attachments', [$budget->id]) . $this->buildParams());
/** @var AttachmentTransformer $transformer */ /** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class); $transformer = app(AttachmentTransformer::class);
@@ -122,7 +122,7 @@ class ListController extends Controller
$count = $collection->count(); $count = $collection->count();
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budgets.budget-limits', [$budget->id]).$this->buildParams()); $paginator->setPath(route('api.v1.budgets.budget-limits', [$budget->id]) . $this->buildParams());
/** @var BudgetLimitTransformer $transformer */ /** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class); $transformer = app(BudgetLimitTransformer::class);
@@ -186,7 +186,7 @@ class ListController extends Controller
} }
$paginator = $collector->getPaginatedGroups(); $paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.budgets.transactions', [$budget->id]).$this->buildParams()); $paginator->setPath(route('api.v1.budgets.transactions', [$budget->id]) . $this->buildParams());
$transactions = $paginator->getCollection(); $transactions = $paginator->getCollection();
/** @var TransactionGroupTransformer $transformer */ /** @var TransactionGroupTransformer $transformer */
@@ -249,7 +249,7 @@ class ListController extends Controller
} }
$paginator = $collector->getPaginatedGroups(); $paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.budgets.without-budget').$this->buildParams()); $paginator->setPath(route('api.v1.budgets.without-budget') . $this->buildParams());
$transactions = $paginator->getCollection(); $transactions = $paginator->getCollection();
/** @var TransactionGroupTransformer $transformer */ /** @var TransactionGroupTransformer $transformer */

View File

@@ -86,7 +86,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($budgets, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($budgets, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budgets.index').$this->buildParams()); $paginator->setPath(route('api.v1.budgets.index') . $this->buildParams());
/** @var BudgetTransformer $transformer */ /** @var BudgetTransformer $transformer */
$transformer = app(BudgetTransformer::class); $transformer = app(BudgetTransformer::class);

View File

@@ -109,7 +109,7 @@ class ListController extends Controller
$collector->setRange($budgetLimit->start_date, $budgetLimit->end_date); $collector->setRange($budgetLimit->start_date, $budgetLimit->end_date);
$collector->setTypes($types); $collector->setTypes($types);
$paginator = $collector->getPaginatedGroups(); $paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.budgets.limits.transactions', [$budget->id, $budgetLimit->id]).$this->buildParams()); $paginator->setPath(route('api.v1.budgets.limits.transactions', [$budget->id, $budgetLimit->id]) . $this->buildParams());
$transactions = $paginator->getCollection(); $transactions = $paginator->getCollection();
/** @var TransactionGroupTransformer $transformer */ /** @var TransactionGroupTransformer $transformer */

View File

@@ -90,7 +90,7 @@ class ShowController extends Controller
$count = $collection->count(); $count = $collection->count();
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budgets.limits.index', [$budget->id]).$this->buildParams()); $paginator->setPath(route('api.v1.budgets.limits.index', [$budget->id]) . $this->buildParams());
/** @var BudgetLimitTransformer $transformer */ /** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class); $transformer = app(BudgetLimitTransformer::class);
@@ -122,7 +122,7 @@ class ShowController extends Controller
$count = $collection->count(); $count = $collection->count();
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budget-limits.index').$this->buildParams()); $paginator->setPath(route('api.v1.budget-limits.index') . $this->buildParams());
/** @var BudgetLimitTransformer $transformer */ /** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class); $transformer = app(BudgetLimitTransformer::class);

View File

@@ -85,7 +85,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.categories.attachments', [$category->id]).$this->buildParams()); $paginator->setPath(route('api.v1.categories.attachments', [$category->id]) . $this->buildParams());
/** @var AttachmentTransformer $transformer */ /** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class); $transformer = app(AttachmentTransformer::class);
@@ -143,7 +143,7 @@ class ListController extends Controller
} }
$paginator = $collector->getPaginatedGroups(); $paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.categories.transactions', [$category->id]).$this->buildParams()); $paginator->setPath(route('api.v1.categories.transactions', [$category->id]) . $this->buildParams());
$transactions = $paginator->getCollection(); $transactions = $paginator->getCollection();
/** @var TransactionGroupTransformer $transformer */ /** @var TransactionGroupTransformer $transformer */

View File

@@ -82,7 +82,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($categories, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($categories, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.categories.index').$this->buildParams()); $paginator->setPath(route('api.v1.categories.index') . $this->buildParams());
/** @var CategoryTransformer $transformer */ /** @var CategoryTransformer $transformer */
$transformer = app(CategoryTransformer::class); $transformer = app(CategoryTransformer::class);

View File

@@ -85,7 +85,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.bills', [$objectGroup->id]).$this->buildParams()); $paginator->setPath(route('api.v1.currencies.bills', [$objectGroup->id]) . $this->buildParams());
/** @var BillTransformer $transformer */ /** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class); $transformer = app(BillTransformer::class);
@@ -123,7 +123,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.object-groups.piggy-banks', [$objectGroup->id]).$this->buildParams()); $paginator->setPath(route('api.v1.object-groups.piggy-banks', [$objectGroup->id]) . $this->buildParams());
/** @var PiggyBankTransformer $transformer */ /** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class); $transformer = app(PiggyBankTransformer::class);

View File

@@ -88,7 +88,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($objectGroups, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($objectGroups, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.object-groups.index').$this->buildParams()); $paginator->setPath(route('api.v1.object-groups.index') . $this->buildParams());
/** @var ObjectGroupTransformer $transformer */ /** @var ObjectGroupTransformer $transformer */
$transformer = app(ObjectGroupTransformer::class); $transformer = app(ObjectGroupTransformer::class);

View File

@@ -79,7 +79,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.piggy-banks.attachments', [$piggyBank->id]).$this->buildParams()); $paginator->setPath(route('api.v1.piggy-banks.attachments', [$piggyBank->id]) . $this->buildParams());
/** @var AttachmentTransformer $transformer */ /** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class); $transformer = app(AttachmentTransformer::class);
@@ -114,7 +114,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.piggy-banks.events', [$piggyBank->id]).$this->buildParams()); $paginator->setPath(route('api.v1.piggy-banks.events', [$piggyBank->id]) . $this->buildParams());
/** @var PiggyBankEventTransformer $transformer */ /** @var PiggyBankEventTransformer $transformer */
$transformer = app(PiggyBankEventTransformer::class); $transformer = app(PiggyBankEventTransformer::class);

View File

@@ -81,7 +81,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.piggy-banks.index').$this->buildParams()); $paginator->setPath(route('api.v1.piggy-banks.index') . $this->buildParams());
/** @var PiggyBankTransformer $transformer */ /** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class); $transformer = app(PiggyBankTransformer::class);

View File

@@ -109,7 +109,7 @@ class ListController extends Controller
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); $collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
} }
$paginator = $collector->getPaginatedGroups(); $paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.transactions.index').$this->buildParams()); $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
$transactions = $paginator->getCollection(); $transactions = $paginator->getCollection();
/** @var TransactionGroupTransformer $transformer */ /** @var TransactionGroupTransformer $transformer */

View File

@@ -82,7 +82,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.recurrences.index').$this->buildParams()); $paginator->setPath(route('api.v1.recurrences.index') . $this->buildParams());
/** @var RecurrenceTransformer $transformer */ /** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class); $transformer = app(RecurrenceTransformer::class);

View File

@@ -86,7 +86,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.rules.index').$this->buildParams()); $paginator->setPath(route('api.v1.rules.index') . $this->buildParams());
/** @var RuleTransformer $transformer */ /** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class); $transformer = app(RuleTransformer::class);

View File

@@ -96,12 +96,13 @@ class TriggerController extends Controller
$ruleEngine->addOperator(['type' => 'account_id', 'value' => implode(',', $parameters['accounts'])]); $ruleEngine->addOperator(['type' => 'account_id', 'value' => implode(',', $parameters['accounts'])]);
} }
// file the rule(s) // file the rule(s)
$transactions = $ruleEngine->find(); $transactions = $ruleEngine->find();
$count = $transactions->count(); $count = $transactions->count();
$paginator = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.rules.test', [$rule->id]).$this->buildParams()); $paginator->setPath(route('api.v1.rules.test', [$rule->id]) . $this->buildParams());
// resulting list is presented as JSON thing. // resulting list is presented as JSON thing.
$manager = $this->getManager(); $manager = $this->getManager();
@@ -149,6 +150,7 @@ class TriggerController extends Controller
$ruleEngine->addOperator(['type' => 'account_id', 'value' => implode(',', $parameters['accounts'])]); $ruleEngine->addOperator(['type' => 'account_id', 'value' => implode(',', $parameters['accounts'])]);
} }
// fire the rule(s) // fire the rule(s)
$ruleEngine->fire(); $ruleEngine->fire();

View File

@@ -84,7 +84,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.rule-groups.rules', [$group->id]).$this->buildParams()); $paginator->setPath(route('api.v1.rule-groups.rules', [$group->id]) . $this->buildParams());
/** @var RuleTransformer $transformer */ /** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class); $transformer = app(RuleTransformer::class);

View File

@@ -84,7 +84,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($ruleGroups, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($ruleGroups, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.rule-groups.index').$this->buildParams()); $paginator->setPath(route('api.v1.rule-groups.index') . $this->buildParams());
/** @var RuleGroupTransformer $transformer */ /** @var RuleGroupTransformer $transformer */
$transformer = app(RuleGroupTransformer::class); $transformer = app(RuleGroupTransformer::class);

View File

@@ -108,7 +108,7 @@ class TriggerController extends Controller
$count = $transactions->count(); $count = $transactions->count();
$paginator = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.rule-groups.test', [$group->id]).$this->buildParams()); $paginator->setPath(route('api.v1.rule-groups.test', [$group->id]) . $this->buildParams());
// resulting list is presented as JSON thing. // resulting list is presented as JSON thing.
$manager = $this->getManager(); $manager = $this->getManager();

View File

@@ -88,7 +88,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.tags.attachments', [$tag->id]).$this->buildParams()); $paginator->setPath(route('api.v1.tags.attachments', [$tag->id]) . $this->buildParams());
/** @var AttachmentTransformer $transformer */ /** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class); $transformer = app(AttachmentTransformer::class);
@@ -143,7 +143,7 @@ class ListController extends Controller
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); $collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
} }
$paginator = $collector->getPaginatedGroups(); $paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.tags.transactions', [$tag->id]).$this->buildParams()); $paginator->setPath(route('api.v1.tags.transactions', [$tag->id]) . $this->buildParams());
$transactions = $paginator->getCollection(); $transactions = $paginator->getCollection();
/** @var TransactionGroupTransformer $transformer */ /** @var TransactionGroupTransformer $transformer */

View File

@@ -85,7 +85,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.tags.index').$this->buildParams()); $paginator->setPath(route('api.v1.tags.index') . $this->buildParams());
/** @var TagTransformer $transformer */ /** @var TagTransformer $transformer */
$transformer = app(TagTransformer::class); $transformer = app(TagTransformer::class);

View File

@@ -89,7 +89,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.transactions.attachments', [$transactionGroup->id]).$this->buildParams()); $paginator->setPath(route('api.v1.transactions.attachments', [$transactionGroup->id]) . $this->buildParams());
/** @var AttachmentTransformer $transformer */ /** @var AttachmentTransformer $transformer */
$transformer = app(AttachmentTransformer::class); $transformer = app(AttachmentTransformer::class);
@@ -122,7 +122,7 @@ class ListController extends Controller
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.transactions.piggy-bank-events', [$transactionGroup->id]).$this->buildParams()); $paginator->setPath(route('api.v1.transactions.piggy-bank-events', [$transactionGroup->id]) . $this->buildParams());
/** @var PiggyBankEventTransformer $transformer */ /** @var PiggyBankEventTransformer $transformer */
$transformer = app(PiggyBankEventTransformer::class); $transformer = app(PiggyBankEventTransformer::class);
@@ -158,7 +158,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($journalLinks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($journalLinks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.transaction-journals.transaction-links', [$transactionJournal->id]).$this->buildParams()); $paginator->setPath(route('api.v1.transaction-journals.transaction-links', [$transactionJournal->id]) . $this->buildParams());
/** @var TransactionLinkTransformer $transformer */ /** @var TransactionLinkTransformer $transformer */
$transformer = app(TransactionLinkTransformer::class); $transformer = app(TransactionLinkTransformer::class);

View File

@@ -84,7 +84,7 @@ class ShowController extends Controller
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); $collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
} }
$paginator = $collector->getPaginatedGroups(); $paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.transactions.index').$this->buildParams()); $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
$transactions = $paginator->getCollection(); $transactions = $paginator->getCollection();
/** @var TransactionGroupTransformer $transformer */ /** @var TransactionGroupTransformer $transformer */
@@ -97,6 +97,21 @@ class ShowController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
} }
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/transactions/getTransactionByJournal
*
* Show a single transaction, by transaction journal.
*
* @param TransactionJournal $transactionJournal
*
* @return JsonResponse
*/
public function showJournal(TransactionJournal $transactionJournal): JsonResponse
{
return $this->show($transactionJournal->transactionGroup);
}
/** /**
* This endpoint is documented at: * This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/transactions/getTransaction * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/transactions/getTransaction
@@ -133,19 +148,4 @@ class ShowController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
} }
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/transactions/getTransactionByJournal
*
* Show a single transaction, by transaction journal.
*
* @param TransactionJournal $transactionJournal
*
* @return JsonResponse
*/
public function showJournal(TransactionJournal $transactionJournal): JsonResponse
{
return $this->show($transactionJournal->transactionGroup);
}
} }

View File

@@ -127,7 +127,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.accounts', [$currency->code]).$this->buildParams()); $paginator->setPath(route('api.v1.currencies.accounts', [$currency->code]) . $this->buildParams());
/** @var AccountTransformer $transformer */ /** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class); $transformer = app(AccountTransformer::class);
@@ -164,7 +164,7 @@ class ListController extends Controller
$availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.available-budgets', [$currency->code]).$this->buildParams()); $paginator->setPath(route('api.v1.currencies.available-budgets', [$currency->code]) . $this->buildParams());
/** @var AvailableBudgetTransformer $transformer */ /** @var AvailableBudgetTransformer $transformer */
$transformer = app(AvailableBudgetTransformer::class); $transformer = app(AvailableBudgetTransformer::class);
@@ -207,7 +207,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.bills', [$currency->code]).$this->buildParams()); $paginator->setPath(route('api.v1.currencies.bills', [$currency->code]) . $this->buildParams());
/** @var BillTransformer $transformer */ /** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class); $transformer = app(BillTransformer::class);
@@ -241,7 +241,7 @@ class ListController extends Controller
$count = $collection->count(); $count = $collection->count();
$budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.budget-limits', [$currency->code]).$this->buildParams()); $paginator->setPath(route('api.v1.currencies.budget-limits', [$currency->code]) . $this->buildParams());
/** @var BudgetLimitTransformer $transformer */ /** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class); $transformer = app(BudgetLimitTransformer::class);
@@ -293,7 +293,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.recurrences', [$currency->code]).$this->buildParams()); $paginator->setPath(route('api.v1.currencies.recurrences', [$currency->code]) . $this->buildParams());
/** @var RecurrenceTransformer $transformer */ /** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class); $transformer = app(RecurrenceTransformer::class);
@@ -344,7 +344,7 @@ class ListController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.rules.index').$this->buildParams()); $paginator->setPath(route('api.v1.rules.index') . $this->buildParams());
/** @var RuleTransformer $transformer */ /** @var RuleTransformer $transformer */
$transformer = app(RuleTransformer::class); $transformer = app(RuleTransformer::class);
@@ -400,7 +400,7 @@ class ListController extends Controller
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); $collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
} }
$paginator = $collector->getPaginatedGroups(); $paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.currencies.transactions', [$currency->code]).$this->buildParams()); $paginator->setPath(route('api.v1.currencies.transactions', [$currency->code]) . $this->buildParams());
$transactions = $paginator->getCollection(); $transactions = $paginator->getCollection();
/** @var TransactionGroupTransformer $transformer */ /** @var TransactionGroupTransformer $transformer */

View File

@@ -84,7 +84,7 @@ class ShowController extends Controller
// slice them: // slice them:
$currencies = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $currencies = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($currencies, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($currencies, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.index').$this->buildParams()); $paginator->setPath(route('api.v1.currencies.index') . $this->buildParams());
$manager = $this->getManager(); $manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency); $this->parameters->set('defaultCurrency', $defaultCurrency);

View File

@@ -97,35 +97,6 @@ class UpdateController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
} }
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/enableCurrency
*
* Enable a currency.
*
* @param TransactionCurrency $currency
*
* @return JsonResponse
* @throws FireflyException
* @throws JsonException
*/
public function enable(TransactionCurrency $currency): JsonResponse
{
$this->repository->enable($currency);
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency);
/** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($currency, $transformer, 'currencies');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
/** /**
* This endpoint is documented at: * This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/defaultCurrency * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/defaultCurrency
@@ -157,6 +128,35 @@ class UpdateController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
} }
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/enableCurrency
*
* Enable a currency.
*
* @param TransactionCurrency $currency
*
* @return JsonResponse
* @throws FireflyException
* @throws JsonException
*/
public function enable(TransactionCurrency $currency): JsonResponse
{
$this->repository->enable($currency);
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency);
/** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($currency, $transformer, 'currencies');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
}
/** /**
* This endpoint is documented at: * This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/updateCurrency * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/updateCurrency

View File

@@ -92,7 +92,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($journalLinks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($journalLinks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.transaction-links.index').$this->buildParams()); $paginator->setPath(route('api.v1.transaction-links.index') . $this->buildParams());
/** @var TransactionLinkTransformer $transformer */ /** @var TransactionLinkTransformer $transformer */
$transformer = app(TransactionLinkTransformer::class); $transformer = app(TransactionLinkTransformer::class);

View File

@@ -110,7 +110,7 @@ class ListController extends Controller
$collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); $collector->setRange($this->parameters->get('start'), $this->parameters->get('end'));
} }
$paginator = $collector->getPaginatedGroups(); $paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.transactions.index').$this->buildParams()); $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams());
$transactions = $paginator->getCollection(); $transactions = $paginator->getCollection();
/** @var TransactionGroupTransformer $transformer */ /** @var TransactionGroupTransformer $transformer */

View File

@@ -87,7 +87,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($linkTypes, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($linkTypes, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.link-types.index').$this->buildParams()); $paginator->setPath(route('api.v1.link-types.index') . $this->buildParams());
/** @var LinkTypeTransformer $transformer */ /** @var LinkTypeTransformer $transformer */
$transformer = app(LinkTypeTransformer::class); $transformer = app(LinkTypeTransformer::class);

View File

@@ -33,7 +33,6 @@ 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 Illuminate\Support\Facades\Log;
use JsonException;
use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Collection as FractalCollection;
@@ -66,7 +65,7 @@ class AccountController extends Controller
* *
* @return JsonResponse|Response * @return JsonResponse|Response
*/ */
public function search(Request $request): JsonResponse|Response public function search(Request $request): JsonResponse | Response
{ {
Log::debug('Now in account search()'); Log::debug('Now in account search()');
$manager = $this->getManager(); $manager = $this->getManager();

View File

@@ -60,7 +60,7 @@ class TransactionController extends Controller
$searcher->setLimit($pageSize); $searcher->setLimit($pageSize);
$groups = $searcher->searchTransactions(); $groups = $searcher->searchTransactions();
$parameters = ['search' => $fullQuery]; $parameters = ['search' => $fullQuery];
$url = route('api.v1.search.transactions').'?'.http_build_query($parameters); $url = route('api.v1.search.transactions') . '?' . http_build_query($parameters);
$groups->setPath($url); $groups->setPath($url);
$transactions = $groups->getCollection(); $transactions = $groups->getCollection();

View File

@@ -121,30 +121,6 @@ class BasicController extends Controller
return response()->json($return); return response()->json($return);
} }
/**
* Check if date is outside session range.
*
* @param Carbon $date
*
* @param Carbon $start
* @param Carbon $end
*
* @return bool
*/
protected function notInDateRange(Carbon $date, Carbon $start, Carbon $end): bool // Validate a preference
{
$result = false;
if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) {
$result = true;
}
// start and end in the past? use $end
if ($start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date)) {
$result = true;
}
return $result;
}
/** /**
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
@@ -220,8 +196,8 @@ class BasicController extends Controller
'currency_decimal_places' => $currency->decimal_places, 'currency_decimal_places' => $currency->decimal_places,
'value_parsed' => app('amount')->formatAnything($currency, $sums[$currencyId] ?? '0', false), 'value_parsed' => app('amount')->formatAnything($currency, $sums[$currencyId] ?? '0', false),
'local_icon' => 'balance-scale', 'local_icon' => 'balance-scale',
'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false). 'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false) .
' + '.app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false), ' + ' . app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false),
]; ];
$return[] = [ $return[] = [
'key' => sprintf('spent-in-%s', $currency->code), 'key' => sprintf('spent-in-%s', $currency->code),
@@ -422,4 +398,28 @@ class BasicController extends Controller
return $return; return $return;
} }
/**
* Check if date is outside session range.
*
* @param Carbon $date
*
* @param Carbon $start
* @param Carbon $end
*
* @return bool
*/
protected function notInDateRange(Carbon $date, Carbon $start, Carbon $end): bool // Validate a preference
{
$result = false;
if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) {
$result = true;
}
// start and end in the past? use $end
if ($start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date)) {
$result = true;
}
return $result;
}
} }

View File

@@ -94,6 +94,42 @@ class ConfigurationController extends Controller
return response()->json($return); return response()->json($return);
} }
/**
* Get all config values.
*
* @return array
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
private function getDynamicConfiguration(): array
{
$isDemoSite = app('fireflyconfig')->get('is_demo_site');
$updateCheck = app('fireflyconfig')->get('permission_update_check');
$lastCheck = app('fireflyconfig')->get('last_update_check');
$singleUser = app('fireflyconfig')->get('single_user_mode');
return [
'is_demo_site' => $isDemoSite?->data,
'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data,
'last_update_check' => null === $lastCheck ? null : (int)$lastCheck->data,
'single_user_mode' => $singleUser?->data,
];
}
/**
* @return array
*/
private function getStaticConfiguration(): array
{
$list = EitherConfigKey::$static;
$return = [];
foreach ($list as $key) {
$return[$key] = config($key);
}
return $return;
}
/** /**
* This endpoint is documented at: * This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/configuration/getSingleConfiguration * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/configuration/getSingleConfiguration
@@ -164,40 +200,4 @@ class ConfigurationController extends Controller
return response()->json(['data' => $data])->header('Content-Type', self::CONTENT_TYPE); return response()->json(['data' => $data])->header('Content-Type', self::CONTENT_TYPE);
} }
/**
* Get all config values.
*
* @return array
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
private function getDynamicConfiguration(): array
{
$isDemoSite = app('fireflyconfig')->get('is_demo_site');
$updateCheck = app('fireflyconfig')->get('permission_update_check');
$lastCheck = app('fireflyconfig')->get('last_update_check');
$singleUser = app('fireflyconfig')->get('single_user_mode');
return [
'is_demo_site' => $isDemoSite?->data,
'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data,
'last_update_check' => null === $lastCheck ? null : (int)$lastCheck->data,
'single_user_mode' => $singleUser?->data,
];
}
/**
* @return array
*/
private function getStaticConfiguration(): array
{
$list = EitherConfigKey::$static;
$return = [];
foreach ($list as $key) {
$return[$key] = config($key);
}
return $return;
}
} }

View File

@@ -111,7 +111,7 @@ class UserController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($users, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($users, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.users.index').$this->buildParams()); $paginator->setPath(route('api.v1.users.index') . $this->buildParams());
// make resource // make resource
/** @var UserTransformer $transformer */ /** @var UserTransformer $transformer */

View File

@@ -63,7 +63,7 @@ class PreferencesController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($preferences, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($preferences, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.preferences.index').$this->buildParams()); $paginator->setPath(route('api.v1.preferences.index') . $this->buildParams());
/** @var PreferenceTransformer $transformer */ /** @var PreferenceTransformer $transformer */
$transformer = app(PreferenceTransformer::class); $transformer = app(PreferenceTransformer::class);

View File

@@ -83,7 +83,7 @@ class AttemptController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($attempts, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($attempts, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.webhooks.attempts.index', [$webhook->id, $message->id]).$this->buildParams()); $paginator->setPath(route('api.v1.webhooks.attempts.index', [$webhook->id, $message->id]) . $this->buildParams());
/** @var WebhookAttemptTransformer $transformer */ /** @var WebhookAttemptTransformer $transformer */
$transformer = app(WebhookAttemptTransformer::class); $transformer = app(WebhookAttemptTransformer::class);

View File

@@ -75,7 +75,7 @@ class MessageController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($messages, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($messages, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.webhooks.messages.index', [$webhook->id]).$this->buildParams()); $paginator->setPath(route('api.v1.webhooks.messages.index', [$webhook->id]) . $this->buildParams());
/** @var WebhookMessageTransformer $transformer */ /** @var WebhookMessageTransformer $transformer */
$transformer = app(WebhookMessageTransformer::class); $transformer = app(WebhookMessageTransformer::class);

View File

@@ -80,7 +80,7 @@ class ShowController extends Controller
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($webhooks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($webhooks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.webhooks.index').$this->buildParams()); $paginator->setPath(route('api.v1.webhooks.index') . $this->buildParams());
/** @var WebhookTransformer $transformer */ /** @var WebhookTransformer $transformer */
$transformer = app(WebhookTransformer::class); $transformer = app(WebhookTransformer::class);

View File

@@ -52,8 +52,8 @@ class DestroyRequest extends FormRequest
*/ */
public function rules(): array public function rules(): array
{ {
$valid = 'budgets,bills,piggy_banks,rules,recurring,categories,tags,object_groups'. $valid = 'budgets,bills,piggy_banks,rules,recurring,categories,tags,object_groups' .
',accounts,asset_accounts,expense_accounts,revenue_accounts,liabilities,transactions,withdrawals,deposits,transfers'. ',accounts,asset_accounts,expense_accounts,revenue_accounts,liabilities,transactions,withdrawals,deposits,transfers' .
',not_assets_liabilities'; ',not_assets_liabilities';
return [ return [

View File

@@ -82,6 +82,28 @@ class GenericRequest extends FormRequest
return $return; return $return;
} }
/**
*
*/
private function parseAccounts(): void
{
if (0 !== $this->accounts->count()) {
return;
}
$repository = app(AccountRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('accounts');
if (is_array($array)) {
foreach ($array as $accountId) {
$accountId = (int)$accountId;
$account = $repository->find($accountId);
if (null !== $account) {
$this->accounts->push($account);
}
}
}
}
/** /**
* @return Collection * @return Collection
*/ */
@@ -92,6 +114,28 @@ class GenericRequest extends FormRequest
return $this->bills; return $this->bills;
} }
/**
*
*/
private function parseBills(): void
{
if (0 !== $this->bills->count()) {
return;
}
$repository = app(BillRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('bills');
if (is_array($array)) {
foreach ($array as $billId) {
$billId = (int)$billId;
$bill = $repository->find($billId);
if (null !== $bill) {
$this->bills->push($bill);
}
}
}
}
/** /**
* @return Collection * @return Collection
*/ */
@@ -102,6 +146,28 @@ class GenericRequest extends FormRequest
return $this->budgets; return $this->budgets;
} }
/**
*
*/
private function parseBudgets(): void
{
if (0 !== $this->budgets->count()) {
return;
}
$repository = app(BudgetRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('budgets');
if (is_array($array)) {
foreach ($array as $budgetId) {
$budgetId = (int)$budgetId;
$budget = $repository->find($budgetId);
if (null !== $budget) {
$this->budgets->push($budget);
}
}
}
}
/** /**
* @return Collection * @return Collection
*/ */
@@ -112,6 +178,28 @@ class GenericRequest extends FormRequest
return $this->categories; return $this->categories;
} }
/**
*
*/
private function parseCategories(): void
{
if (0 !== $this->categories->count()) {
return;
}
$repository = app(CategoryRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('categories');
if (is_array($array)) {
foreach ($array as $categoryId) {
$categoryId = (int)$categoryId;
$category = $repository->find($categoryId);
if (null !== $category) {
$this->categories->push($category);
}
}
}
}
/** /**
* @return Carbon * @return Carbon
*/ */
@@ -180,114 +268,6 @@ class GenericRequest extends FormRequest
return $this->tags; return $this->tags;
} }
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
// this is cheating, but it works to initialize the collections.
$this->accounts = new Collection();
$this->budgets = new Collection();
$this->categories = new Collection();
$this->bills = new Collection();
$this->tags = new Collection();
return [
'start' => 'required|date',
'end' => 'required|date|after_or_equal:start',
];
}
/**
*
*/
private function parseAccounts(): void
{
if (0 !== $this->accounts->count()) {
return;
}
$repository = app(AccountRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('accounts');
if (is_array($array)) {
foreach ($array as $accountId) {
$accountId = (int)$accountId;
$account = $repository->find($accountId);
if (null !== $account) {
$this->accounts->push($account);
}
}
}
}
/**
*
*/
private function parseBills(): void
{
if (0 !== $this->bills->count()) {
return;
}
$repository = app(BillRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('bills');
if (is_array($array)) {
foreach ($array as $billId) {
$billId = (int)$billId;
$bill = $repository->find($billId);
if (null !== $bill) {
$this->bills->push($bill);
}
}
}
}
/**
*
*/
private function parseBudgets(): void
{
if (0 !== $this->budgets->count()) {
return;
}
$repository = app(BudgetRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('budgets');
if (is_array($array)) {
foreach ($array as $budgetId) {
$budgetId = (int)$budgetId;
$budget = $repository->find($budgetId);
if (null !== $budget) {
$this->budgets->push($budget);
}
}
}
}
/**
*
*/
private function parseCategories(): void
{
if (0 !== $this->categories->count()) {
return;
}
$repository = app(CategoryRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('categories');
if (is_array($array)) {
foreach ($array as $categoryId) {
$categoryId = (int)$categoryId;
$category = $repository->find($categoryId);
if (null !== $category) {
$this->categories->push($category);
}
}
}
}
/** /**
* *
*/ */
@@ -309,4 +289,24 @@ class GenericRequest extends FormRequest
} }
} }
} }
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
// this is cheating, but it works to initialize the collections.
$this->accounts = new Collection();
$this->budgets = new Collection();
$this->categories = new Collection();
$this->bills = new Collection();
$this->tags = new Collection();
return [
'start' => 'required|date',
'end' => 'required|date|after_or_equal:start',
];
}
} }

View File

@@ -104,7 +104,7 @@ class StoreRequest extends FormRequest
$type = $this->convertString('type'); $type = $this->convertString('type');
$rules = [ $rules = [
'name' => 'required|max:1024|min:1|uniqueAccountForUser', 'name' => 'required|max:1024|min:1|uniqueAccountForUser',
'type' => 'required|max:1024|min:1|'.sprintf('in:%s', $types), 'type' => 'required|max:1024|min:1|' . sprintf('in:%s', $types),
'iban' => ['iban', 'nullable', new UniqueIban(null, $type)], 'iban' => ['iban', 'nullable', new UniqueIban(null, $type)],
'bic' => 'bic|nullable', 'bic' => 'bic|nullable',
'account_number' => ['between:1,255', 'nullable', new UniqueAccountNumber(null, $type)], 'account_number' => ['between:1,255', 'nullable', new UniqueAccountNumber(null, $type)],

View File

@@ -109,7 +109,7 @@ class UpdateRequest extends FormRequest
'include_net_worth' => [new IsBoolean()], 'include_net_worth' => [new IsBoolean()],
'account_role' => sprintf('in:%s|nullable|required_if:type,asset', $accountRoles), 'account_role' => sprintf('in:%s|nullable|required_if:type,asset', $accountRoles),
'credit_card_type' => sprintf('in:%s|nullable|required_if:account_role,ccAsset', $ccPaymentTypes), 'credit_card_type' => sprintf('in:%s|nullable|required_if:account_role,ccAsset', $ccPaymentTypes),
'monthly_payment_date' => 'date'.'|nullable|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull', 'monthly_payment_date' => 'date' . '|nullable|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull',
'liability_type' => 'required_if:type,liability|in:loan,debt,mortgage', 'liability_type' => 'required_if:type,liability|in:loan,debt,mortgage',
'liability_direction' => 'required_if:type,liability|in:credit,debit', 'liability_direction' => 'required_if:type,liability|in:credit,debit',
'interest' => 'required_if:type,liability|between:0,100|numeric', 'interest' => 'required_if:type,liability|between:0,100|numeric',

View File

@@ -74,7 +74,7 @@ class UpdateRequest extends FormRequest
$piggyBank = $this->route()->parameter('piggyBank'); $piggyBank = $this->route()->parameter('piggyBank');
return [ return [
'name' => 'between:1,255|uniquePiggyBankForUser:'.$piggyBank->id, 'name' => 'between:1,255|uniquePiggyBankForUser:' . $piggyBank->id,
'current_amount' => ['numeric', 'gte:0', new LessThanPiggyTarget()], 'current_amount' => ['numeric', 'gte:0', new LessThanPiggyTarget()],
'target_amount' => 'numeric|gte:0', 'target_amount' => 'numeric|gte:0',
'start_date' => 'date|nullable', 'start_date' => 'date|nullable',

View File

@@ -73,6 +73,65 @@ class StoreRequest extends FormRequest
]; ];
} }
/**
* 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.
*
* @return array
*/
private function getTransactionData(): array
{
$return = [];
// transaction data:
/** @var array|null $transactions */
$transactions = $this->get('transactions');
if (null === $transactions) {
return [];
}
/** @var array $transaction */
foreach ($transactions as $transaction) {
$return[] = $this->getSingleTransactionData($transaction);
}
return $return;
}
/**
* Returns the repetition data as it is found in the submitted data.
*
* @return array
*/
private function getRepetitionData(): array
{
$return = [];
// repetition data:
/** @var array|null $repetitions */
$repetitions = $this->get('repetitions');
if (null === $repetitions) {
return [];
}
/** @var array $repetition */
foreach ($repetitions as $repetition) {
$current = [];
if (array_key_exists('type', $repetition)) {
$current['type'] = $repetition['type'];
}
if (array_key_exists('moment', $repetition)) {
$current['moment'] = $repetition['moment'];
}
if (array_key_exists('skip', $repetition)) {
$current['skip'] = (int)$repetition['skip'];
}
if (array_key_exists('weekend', $repetition)) {
$current['weekend'] = (int)$repetition['weekend'];
}
$return[] = $current;
}
return $return;
}
/** /**
* The rules that the incoming request must be matched against. * The rules that the incoming request must be matched against.
* *
@@ -139,63 +198,4 @@ class StoreRequest extends FormRequest
} }
); );
} }
/**
* Returns the repetition data as it is found in the submitted data.
*
* @return array
*/
private function getRepetitionData(): array
{
$return = [];
// repetition data:
/** @var array|null $repetitions */
$repetitions = $this->get('repetitions');
if (null === $repetitions) {
return [];
}
/** @var array $repetition */
foreach ($repetitions as $repetition) {
$current = [];
if (array_key_exists('type', $repetition)) {
$current['type'] = $repetition['type'];
}
if (array_key_exists('moment', $repetition)) {
$current['moment'] = $repetition['moment'];
}
if (array_key_exists('skip', $repetition)) {
$current['skip'] = (int)$repetition['skip'];
}
if (array_key_exists('weekend', $repetition)) {
$current['weekend'] = (int)$repetition['weekend'];
}
$return[] = $current;
}
return $return;
}
/**
* 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.
*
* @return array
*/
private function getTransactionData(): array
{
$return = [];
// transaction data:
/** @var array|null $transactions */
$transactions = $this->get('transactions');
if (null === $transactions) {
return [];
}
/** @var array $transaction */
foreach ($transactions as $transaction) {
$return[] = $this->getSingleTransactionData($transaction);
}
return $return;
}
} }

View File

@@ -80,6 +80,70 @@ class UpdateRequest extends FormRequest
return $return; return $return;
} }
/**
* Returns the repetition data as it is found in the submitted data.
*
* @return array|null
*/
private function getRepetitionData(): ?array
{
$return = [];
// repetition data:
/** @var array|null $repetitions */
$repetitions = $this->get('repetitions');
if (null === $repetitions) {
return null;
}
/** @var array $repetition */
foreach ($repetitions as $repetition) {
$current = [];
if (array_key_exists('type', $repetition)) {
$current['type'] = $repetition['type'];
}
if (array_key_exists('moment', $repetition)) {
$current['moment'] = (string)$repetition['moment'];
}
if (array_key_exists('skip', $repetition)) {
$current['skip'] = (int)$repetition['skip'];
}
if (array_key_exists('weekend', $repetition)) {
$current['weekend'] = (int)$repetition['weekend'];
}
$return[] = $current;
}
if (0 === count($return)) {
return null;
}
return $return;
}
/**
* 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.
*
* @return array|null
*/
private function getTransactionData(): ?array
{
$return = [];
// transaction data:
/** @var array|null $transactions */
$transactions = $this->get('transactions');
if (null === $transactions) {
return null;
}
/** @var array $transaction */
foreach ($transactions as $transaction) {
$return[] = $this->getSingleTransactionData($transaction);
}
return $return;
}
/** /**
* The rules that the incoming request must be matched against. * The rules that the incoming request must be matched against.
* *
@@ -154,68 +218,4 @@ class UpdateRequest extends FormRequest
); );
} }
/**
* Returns the repetition data as it is found in the submitted data.
*
* @return array|null
*/
private function getRepetitionData(): ?array
{
$return = [];
// repetition data:
/** @var array|null $repetitions */
$repetitions = $this->get('repetitions');
if (null === $repetitions) {
return null;
}
/** @var array $repetition */
foreach ($repetitions as $repetition) {
$current = [];
if (array_key_exists('type', $repetition)) {
$current['type'] = $repetition['type'];
}
if (array_key_exists('moment', $repetition)) {
$current['moment'] = (string)$repetition['moment'];
}
if (array_key_exists('skip', $repetition)) {
$current['skip'] = (int)$repetition['skip'];
}
if (array_key_exists('weekend', $repetition)) {
$current['weekend'] = (int)$repetition['weekend'];
}
$return[] = $current;
}
if (0 === count($return)) {
return null;
}
return $return;
}
/**
* 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.
*
* @return array|null
*/
private function getTransactionData(): ?array
{
$return = [];
// transaction data:
/** @var array|null $transactions */
$transactions = $this->get('transactions');
if (null === $transactions) {
return null;
}
/** @var array $transaction */
foreach ($transactions as $transaction) {
$return[] = $this->getSingleTransactionData($transaction);
}
return $return;
}
} }

View File

@@ -67,6 +67,48 @@ class StoreRequest extends FormRequest
return $data; return $data;
} }
/**
* @return array
*/
private function getRuleTriggers(): array
{
$triggers = $this->get('triggers');
$return = [];
if (is_array($triggers)) {
foreach ($triggers as $trigger) {
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'true')),
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
];
}
}
return $return;
}
/**
* @return array
*/
private function getRuleActions(): array
{
$actions = $this->get('actions');
$return = [];
if (is_array($actions)) {
foreach ($actions as $action) {
$return[] = [
'type' => $action['type'],
'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'true')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
];
}
}
return $return;
}
/** /**
* The rules that the incoming request must be matched against. * The rules that the incoming request must be matched against.
* *
@@ -87,12 +129,12 @@ class StoreRequest extends FormRequest
'rule_group_id' => 'belongsToUser:rule_groups|required_without:rule_group_title', 'rule_group_id' => 'belongsToUser:rule_groups|required_without:rule_group_title',
'rule_group_title' => 'nullable|between:1,255|required_without:rule_group_id|belongsToUser:rule_groups,title', 'rule_group_title' => 'nullable|between:1,255|required_without:rule_group_id|belongsToUser:rule_groups,title',
'trigger' => 'required|in:store-journal,update-journal', 'trigger' => 'required|in:store-journal,update-journal',
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers), 'triggers.*.type' => 'required|in:' . implode(',', $validTriggers),
'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue|max:1024', 'triggers.*.value' => 'required_if:actions.*.type,' . $contextTriggers . '|min:1|ruleTriggerValue|max:1024',
'triggers.*.stop_processing' => [new IsBoolean()], 'triggers.*.stop_processing' => [new IsBoolean()],
'triggers.*.active' => [new IsBoolean()], 'triggers.*.active' => [new IsBoolean()],
'actions.*.type' => 'required|in:'.implode(',', $validActions), 'actions.*.type' => 'required|in:' . implode(',', $validActions),
'actions.*.value' => 'required_if:actions.*.type,'.$contextActions.'|ruleActionValue', 'actions.*.value' => 'required_if:actions.*.type,' . $contextActions . '|ruleActionValue',
'actions.*.stop_processing' => [new IsBoolean()], 'actions.*.stop_processing' => [new IsBoolean()],
'actions.*.active' => [new IsBoolean()], 'actions.*.active' => [new IsBoolean()],
'strict' => [new IsBoolean()], 'strict' => [new IsBoolean()],
@@ -120,6 +162,21 @@ class StoreRequest extends FormRequest
); );
} }
/**
* Adds an error to the validator when there are no triggers in the array of data.
*
* @param Validator $validator
*/
protected function atLeastOneTrigger(Validator $validator): void
{
$data = $validator->getData();
$triggers = $data['triggers'] ?? [];
// need at least one trigger
if (!is_countable($triggers) || 0 === count($triggers)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger'));
}
}
/** /**
* Adds an error to the validator when there are no repetitions in the array of data. * Adds an error to the validator when there are no repetitions in the array of data.
* *
@@ -135,35 +192,6 @@ class StoreRequest extends FormRequest
} }
} }
/**
* Adds an error to the validator when there are no ACTIVE actions in the array of data.
*
* @param Validator $validator
*/
protected function atLeastOneActiveAction(Validator $validator): void
{
$data = $validator->getData();
$actions = $data['actions'] ?? [];
// need at least one trigger
if (!is_countable($actions) || 0 === count($actions)) {
return;
}
$allInactive = true;
$inactiveIndex = 0;
foreach ($actions as $index => $action) {
$active = array_key_exists('active', $action) ? $action['active'] : true; // assume true
if (true === $active) {
$allInactive = false;
}
if (false === $active) {
$inactiveIndex = $index;
}
}
if (true === $allInactive) {
$validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
}
}
/** /**
* Adds an error to the validator when there are no ACTIVE triggers in the array of data. * Adds an error to the validator when there are no ACTIVE triggers in the array of data.
* *
@@ -194,59 +222,31 @@ class StoreRequest extends FormRequest
} }
/** /**
* Adds an error to the validator when there are no triggers in the array of data. * Adds an error to the validator when there are no ACTIVE actions in the array of data.
* *
* @param Validator $validator * @param Validator $validator
*/ */
protected function atLeastOneTrigger(Validator $validator): void protected function atLeastOneActiveAction(Validator $validator): void
{ {
$data = $validator->getData(); $data = $validator->getData();
$triggers = $data['triggers'] ?? []; $actions = $data['actions'] ?? [];
// need at least one trigger // need at least one trigger
if (!is_countable($triggers) || 0 === count($triggers)) { if (!is_countable($actions) || 0 === count($actions)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_trigger')); return;
}
$allInactive = true;
$inactiveIndex = 0;
foreach ($actions as $index => $action) {
$active = array_key_exists('active', $action) ? $action['active'] : true; // assume true
if (true === $active) {
$allInactive = false;
}
if (false === $active) {
$inactiveIndex = $index;
} }
} }
if (true === $allInactive) {
/** $validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
* @return array
*/
private function getRuleActions(): array
{
$actions = $this->get('actions');
$return = [];
if (is_array($actions)) {
foreach ($actions as $action) {
$return[] = [
'type' => $action['type'],
'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'true')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
];
} }
} }
return $return;
}
/**
* @return array
*/
private function getRuleTriggers(): array
{
$triggers = $this->get('triggers');
$return = [];
if (is_array($triggers)) {
foreach ($triggers as $trigger) {
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'true')),
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
];
}
}
return $return;
}
} }

View File

@@ -52,24 +52,11 @@ class TestRequest extends FormRequest
} }
/** /**
* @return array * @return int
*/ */
public function rules(): array private function getPage(): int
{ {
return [ return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page');
'start' => 'date',
'end' => 'date|after_or_equal:start',
'accounts' => '',
'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts',
];
}
/**
* @return array
*/
private function getAccounts(): array
{
return $this->get('accounts');
} }
/** /**
@@ -83,10 +70,23 @@ class TestRequest extends FormRequest
} }
/** /**
* @return int * @return array
*/ */
private function getPage(): int private function getAccounts(): array
{ {
return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page'); return $this->get('accounts');
}
/**
* @return array
*/
public function rules(): array
{
return [
'start' => 'date',
'end' => 'date|after_or_equal:start',
'accounts' => '',
'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts',
];
} }
} }

View File

@@ -50,16 +50,13 @@ class TriggerRequest extends FormRequest
} }
/** /**
* @return array * @param string $field
*
* @return Carbon|null
*/ */
public function rules(): array private function getDate(string $field): ?Carbon
{ {
return [ return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($this->query($field), 0, 10));
'start' => 'date',
'end' => 'date|after_or_equal:start',
'accounts' => '',
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
];
} }
/** /**
@@ -71,12 +68,15 @@ class TriggerRequest extends FormRequest
} }
/** /**
* @param string $field * @return array
*
* @return Carbon|null
*/ */
private function getDate(string $field): ?Carbon public function rules(): array
{ {
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($this->query($field), 0, 10)); return [
'start' => 'date',
'end' => 'date|after_or_equal:start',
'accounts' => '',
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
];
} }
} }

View File

@@ -73,6 +73,56 @@ class UpdateRequest extends FormRequest
return $return; return $return;
} }
/**
* @return array|null
*/
private function getRuleTriggers(): ?array
{
if (!$this->has('triggers')) {
return null;
}
$triggers = $this->get('triggers');
$return = [];
if (is_array($triggers)) {
foreach ($triggers as $trigger) {
$active = array_key_exists('active', $trigger) ? $trigger['active'] : true;
$stopProcessing = array_key_exists('stop_processing', $trigger) ? $trigger['stop_processing'] : false;
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'active' => $active,
'stop_processing' => $stopProcessing,
];
}
}
return $return;
}
/**
* @return array|null
*/
private function getRuleActions(): ?array
{
if (!$this->has('actions')) {
return null;
}
$actions = $this->get('actions');
$return = [];
if (is_array($actions)) {
foreach ($actions as $action) {
$return[] = [
'type' => $action['type'],
'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
];
}
}
return $return;
}
/** /**
* The rules that the incoming request must be matched against. * The rules that the incoming request must be matched against.
* *
@@ -96,12 +146,12 @@ class UpdateRequest extends FormRequest
'rule_group_id' => 'belongsToUser:rule_groups', 'rule_group_id' => 'belongsToUser:rule_groups',
'rule_group_title' => 'nullable|between:1,255|belongsToUser:rule_groups,title', 'rule_group_title' => 'nullable|between:1,255|belongsToUser:rule_groups,title',
'trigger' => 'in:store-journal,update-journal', 'trigger' => 'in:store-journal,update-journal',
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers), 'triggers.*.type' => 'required|in:' . implode(',', $validTriggers),
'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue|max:1024', 'triggers.*.value' => 'required_if:actions.*.type,' . $contextTriggers . '|min:1|ruleTriggerValue|max:1024',
'triggers.*.stop_processing' => [new IsBoolean()], 'triggers.*.stop_processing' => [new IsBoolean()],
'triggers.*.active' => [new IsBoolean()], 'triggers.*.active' => [new IsBoolean()],
'actions.*.type' => 'required|in:'.implode(',', $validActions), 'actions.*.type' => 'required|in:' . implode(',', $validActions),
'actions.*.value' => 'required_if:actions.*.type,'.$contextActions.'|ruleActionValue', 'actions.*.value' => 'required_if:actions.*.type,' . $contextActions . '|ruleActionValue',
'actions.*.stop_processing' => [new IsBoolean()], 'actions.*.stop_processing' => [new IsBoolean()],
'actions.*.active' => [new IsBoolean()], 'actions.*.active' => [new IsBoolean()],
'strict' => [new IsBoolean()], 'strict' => [new IsBoolean()],
@@ -130,21 +180,6 @@ class UpdateRequest extends FormRequest
); );
} }
/**
* Adds an error to the validator when there are no repetitions in the array of data.
*
* @param Validator $validator
*/
protected function atLeastOneAction(Validator $validator): void
{
$data = $validator->getData();
$actions = $data['actions'] ?? null;
// need at least one action
if (is_array($actions) && 0 === count($actions)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
}
}
/** /**
* Adds an error to the validator when there are no repetitions in the array of data. * Adds an error to the validator when there are no repetitions in the array of data.
* *
@@ -160,36 +195,6 @@ class UpdateRequest extends FormRequest
} }
} }
/**
* Adds an error to the validator when there are no repetitions in the array of data.
*
* @param Validator $validator
*/
protected function atLeastOneValidAction(Validator $validator): void
{
$data = $validator->getData();
$actions = $data['actions'] ?? [];
$allInactive = true;
$inactiveIndex = 0;
// need at least one action
if (is_array($actions) && 0 === count($actions)) {
return;
}
foreach ($actions as $index => $action) {
$active = array_key_exists('active', $action) ? $action['active'] : true; // assume true
if (true === $active) {
$allInactive = false;
}
if (false === $active) {
$inactiveIndex = $index;
}
}
if (true === $allInactive) {
$validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
}
}
/** /**
* Adds an error to the validator when there are no repetitions in the array of data. * Adds an error to the validator when there are no repetitions in the array of data.
* *
@@ -220,52 +225,47 @@ class UpdateRequest extends FormRequest
} }
/** /**
* @return array|null * Adds an error to the validator when there are no repetitions in the array of data.
*
* @param Validator $validator
*/ */
private function getRuleActions(): ?array protected function atLeastOneAction(Validator $validator): void
{ {
if (!$this->has('actions')) { $data = $validator->getData();
return null; $actions = $data['actions'] ?? null;
// need at least one action
if (is_array($actions) && 0 === count($actions)) {
$validator->errors()->add('title', (string)trans('validation.at_least_one_action'));
} }
$actions = $this->get('actions');
$return = [];
if (is_array($actions)) {
foreach ($actions as $action) {
$return[] = [
'type' => $action['type'],
'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
];
}
}
return $return;
} }
/** /**
* @return array|null * Adds an error to the validator when there are no repetitions in the array of data.
*
* @param Validator $validator
*/ */
private function getRuleTriggers(): ?array protected function atLeastOneValidAction(Validator $validator): void
{ {
if (!$this->has('triggers')) { $data = $validator->getData();
return null; $actions = $data['actions'] ?? [];
} $allInactive = true;
$triggers = $this->get('triggers'); $inactiveIndex = 0;
$return = []; // need at least one action
if (is_array($triggers)) { if (is_array($actions) && 0 === count($actions)) {
foreach ($triggers as $trigger) { return;
$active = array_key_exists('active', $trigger) ? $trigger['active'] : true;
$stopProcessing = array_key_exists('stop_processing', $trigger) ? $trigger['stop_processing'] : false;
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'active' => $active,
'stop_processing' => $stopProcessing,
];
}
} }
return $return; foreach ($actions as $index => $action) {
$active = array_key_exists('active', $action) ? $action['active'] : true; // assume true
if (true === $active) {
$allInactive = false;
}
if (false === $active) {
$inactiveIndex = $index;
}
}
if (true === $allInactive) {
$validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
}
} }
} }

View File

@@ -50,16 +50,13 @@ class TestRequest extends FormRequest
} }
/** /**
* @return array * @param string $field
*
* @return Carbon|null
*/ */
public function rules(): array private function getDate(string $field): ?Carbon
{ {
return [ return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
'start' => 'date',
'end' => 'date|after_or_equal:start',
'accounts' => '',
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
];
} }
/** /**
@@ -71,12 +68,15 @@ class TestRequest extends FormRequest
} }
/** /**
* @param string $field * @return array
*
* @return Carbon|null
*/ */
private function getDate(string $field): ?Carbon public function rules(): array
{ {
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field)); return [
'start' => 'date',
'end' => 'date|after_or_equal:start',
'accounts' => '',
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
];
} }
} }

View File

@@ -50,14 +50,13 @@ class TriggerRequest extends FormRequest
} }
/** /**
* @return array * @param string $field
*
* @return Carbon|null
*/ */
public function rules(): array private function getDate(string $field): ?Carbon
{ {
return [ return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
'start' => 'date',
'end' => 'date|after_or_equal:start',
];
} }
/** /**
@@ -69,12 +68,13 @@ class TriggerRequest extends FormRequest
} }
/** /**
* @param string $field * @return array
*
* @return Carbon|null
*/ */
private function getDate(string $field): ?Carbon public function rules(): array
{ {
return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field)); return [
'start' => 'date',
'end' => 'date|after_or_equal:start',
];
} }
} }

View File

@@ -66,7 +66,7 @@ class UpdateRequest extends FormRequest
$ruleGroup = $this->route()->parameter('ruleGroup'); $ruleGroup = $this->route()->parameter('ruleGroup');
return [ return [
'title' => 'between:1,100|uniqueObjectForUser:rule_groups,title,'.$ruleGroup->id, 'title' => 'between:1,100|uniqueObjectForUser:rule_groups,title,' . $ruleGroup->id,
'description' => 'between:1,5000|nullable', 'description' => 'between:1,5000|nullable',
'active' => [new IsBoolean()], 'active' => [new IsBoolean()],
]; ];

View File

@@ -71,7 +71,7 @@ class UpdateRequest extends FormRequest
$tag = $this->route()->parameter('tagOrId'); $tag = $this->route()->parameter('tagOrId');
// TODO check if uniqueObjectForUser is obsolete // TODO check if uniqueObjectForUser is obsolete
$rules = [ $rules = [
'tag' => 'min:1|max:1024|uniqueObjectForUser:tags,tag,'.$tag->id, 'tag' => 'min:1|max:1024|uniqueObjectForUser:tags,tag,' . $tag->id,
'description' => 'min:1|nullable|max:65536', 'description' => 'min:1|nullable|max:65536',
'date' => 'date|nullable', 'date' => 'date|nullable',
]; ];

View File

@@ -69,6 +69,103 @@ class StoreRequest extends FormRequest
// TODO include location and ability to process it. // TODO include location and ability to process it.
} }
/**
* Get transaction data.
*
* @return array
*/
private function getTransactionData(): array
{
$return = [];
/**
* @var array $transaction
*/
foreach ($this->get('transactions') as $transaction) {
$object = new NullArrayObject($transaction);
$return[] = [
'type' => $this->clearString($object['type'], false),
'date' => $this->dateFromValue($object['date']),
'order' => $this->integerFromValue((string)$object['order']),
'currency_id' => $this->integerFromValue((string)$object['currency_id']),
'currency_code' => $this->clearString((string)$object['currency_code'], false),
// foreign currency info:
'foreign_currency_id' => $this->integerFromValue((string)$object['foreign_currency_id']),
'foreign_currency_code' => $this->clearString((string)$object['foreign_currency_code'], false),
// amount and foreign amount. Cannot be 0.
'amount' => $this->clearString((string)$object['amount'], false),
'foreign_amount' => $this->clearString((string)$object['foreign_amount'], false),
// description.
'description' => $this->clearString($object['description'], false),
// source of transaction. If everything is null, assume cash account.
'source_id' => $this->integerFromValue((string)$object['source_id']),
'source_name' => $this->clearString((string)$object['source_name'], false),
'source_iban' => $this->clearString((string)$object['source_iban'], false),
'source_number' => $this->clearString((string)$object['source_number'], false),
'source_bic' => $this->clearString((string)$object['source_bic'], false),
// destination of transaction. If everything is null, assume cash account.
'destination_id' => $this->integerFromValue((string)$object['destination_id']),
'destination_name' => $this->clearString((string)$object['destination_name'], false),
'destination_iban' => $this->clearString((string)$object['destination_iban'], false),
'destination_number' => $this->clearString((string)$object['destination_number'], false),
'destination_bic' => $this->clearString((string)$object['destination_bic'], false),
// budget info
'budget_id' => $this->integerFromValue((string)$object['budget_id']),
'budget_name' => $this->clearString((string)$object['budget_name'], false),
// category info
'category_id' => $this->integerFromValue((string)$object['category_id']),
'category_name' => $this->clearString((string)$object['category_name'], false),
// journal bill reference. Optional. Will only work for withdrawals
'bill_id' => $this->integerFromValue((string)$object['bill_id']),
'bill_name' => $this->clearString((string)$object['bill_name'], false),
// piggy bank reference. Optional. Will only work for transfers
'piggy_bank_id' => $this->integerFromValue((string)$object['piggy_bank_id']),
'piggy_bank_name' => $this->clearString((string)$object['piggy_bank_name'], false),
// some other interesting properties
'reconciled' => $this->convertBoolean((string)$object['reconciled']),
'notes' => $this->clearString((string)$object['notes']),
'tags' => $this->arrayFromValue($object['tags']),
// all custom fields:
'internal_reference' => $this->clearString((string)$object['internal_reference'], false),
'external_id' => $this->clearString((string)$object['external_id'], false),
'original_source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')),
'recurrence_id' => $this->integerFromValue($object['recurrence_id']),
'bunq_payment_id' => $this->clearString((string)$object['bunq_payment_id'], false),
'external_url' => $this->clearString((string)$object['external_url'], false),
'sepa_cc' => $this->clearString((string)$object['sepa_cc'], false),
'sepa_ct_op' => $this->clearString((string)$object['sepa_ct_op'], false),
'sepa_ct_id' => $this->clearString((string)$object['sepa_ct_id'], false),
'sepa_db' => $this->clearString((string)$object['sepa_db'], false),
'sepa_country' => $this->clearString((string)$object['sepa_country'], false),
'sepa_ep' => $this->clearString((string)$object['sepa_ep'], false),
'sepa_ci' => $this->clearString((string)$object['sepa_ci'], false),
'sepa_batch_id' => $this->clearString((string)$object['sepa_batch_id'], false),
// custom date fields. Must be Carbon objects. Presence is optional.
'interest_date' => $this->dateFromValue($object['interest_date']),
'book_date' => $this->dateFromValue($object['book_date']),
'process_date' => $this->dateFromValue($object['process_date']),
'due_date' => $this->dateFromValue($object['due_date']),
'payment_date' => $this->dateFromValue($object['payment_date']),
'invoice_date' => $this->dateFromValue($object['invoice_date']),
];
}
return $return;
}
/** /**
* The rules that the incoming request must be matched against. * The rules that the incoming request must be matched against.
* *
@@ -197,101 +294,4 @@ class StoreRequest extends FormRequest
} }
); );
} }
/**
* Get transaction data.
*
* @return array
*/
private function getTransactionData(): array
{
$return = [];
/**
* @var array $transaction
*/
foreach ($this->get('transactions') as $transaction) {
$object = new NullArrayObject($transaction);
$return[] = [
'type' => $this->clearString($object['type'], false),
'date' => $this->dateFromValue($object['date']),
'order' => $this->integerFromValue((string)$object['order']),
'currency_id' => $this->integerFromValue((string)$object['currency_id']),
'currency_code' => $this->clearString((string)$object['currency_code'], false),
// foreign currency info:
'foreign_currency_id' => $this->integerFromValue((string)$object['foreign_currency_id']),
'foreign_currency_code' => $this->clearString((string)$object['foreign_currency_code'], false),
// amount and foreign amount. Cannot be 0.
'amount' => $this->clearString((string)$object['amount'], false),
'foreign_amount' => $this->clearString((string)$object['foreign_amount'], false),
// description.
'description' => $this->clearString($object['description'], false),
// source of transaction. If everything is null, assume cash account.
'source_id' => $this->integerFromValue((string)$object['source_id']),
'source_name' => $this->clearString((string)$object['source_name'], false),
'source_iban' => $this->clearString((string)$object['source_iban'], false),
'source_number' => $this->clearString((string)$object['source_number'], false),
'source_bic' => $this->clearString((string)$object['source_bic'], false),
// destination of transaction. If everything is null, assume cash account.
'destination_id' => $this->integerFromValue((string)$object['destination_id']),
'destination_name' => $this->clearString((string)$object['destination_name'], false),
'destination_iban' => $this->clearString((string)$object['destination_iban'], false),
'destination_number' => $this->clearString((string)$object['destination_number'], false),
'destination_bic' => $this->clearString((string)$object['destination_bic'], false),
// budget info
'budget_id' => $this->integerFromValue((string)$object['budget_id']),
'budget_name' => $this->clearString((string)$object['budget_name'], false),
// category info
'category_id' => $this->integerFromValue((string)$object['category_id']),
'category_name' => $this->clearString((string)$object['category_name'], false),
// journal bill reference. Optional. Will only work for withdrawals
'bill_id' => $this->integerFromValue((string)$object['bill_id']),
'bill_name' => $this->clearString((string)$object['bill_name'], false),
// piggy bank reference. Optional. Will only work for transfers
'piggy_bank_id' => $this->integerFromValue((string)$object['piggy_bank_id']),
'piggy_bank_name' => $this->clearString((string)$object['piggy_bank_name'], false),
// some other interesting properties
'reconciled' => $this->convertBoolean((string)$object['reconciled']),
'notes' => $this->clearString((string)$object['notes']),
'tags' => $this->arrayFromValue($object['tags']),
// all custom fields:
'internal_reference' => $this->clearString((string)$object['internal_reference'], false),
'external_id' => $this->clearString((string)$object['external_id'], false),
'original_source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')),
'recurrence_id' => $this->integerFromValue($object['recurrence_id']),
'bunq_payment_id' => $this->clearString((string)$object['bunq_payment_id'], false),
'external_url' => $this->clearString((string)$object['external_url'], false),
'sepa_cc' => $this->clearString((string)$object['sepa_cc'], false),
'sepa_ct_op' => $this->clearString((string)$object['sepa_ct_op'], false),
'sepa_ct_id' => $this->clearString((string)$object['sepa_ct_id'], false),
'sepa_db' => $this->clearString((string)$object['sepa_db'], false),
'sepa_country' => $this->clearString((string)$object['sepa_country'], false),
'sepa_ep' => $this->clearString((string)$object['sepa_ep'], false),
'sepa_ci' => $this->clearString((string)$object['sepa_ci'], false),
'sepa_batch_id' => $this->clearString((string)$object['sepa_batch_id'], false),
// custom date fields. Must be Carbon objects. Presence is optional.
'interest_date' => $this->dateFromValue($object['interest_date']),
'book_date' => $this->dateFromValue($object['book_date']),
'process_date' => $this->dateFromValue($object['process_date']),
'due_date' => $this->dateFromValue($object['due_date']),
'payment_date' => $this->dateFromValue($object['payment_date']),
'invoice_date' => $this->dateFromValue($object['invoice_date']),
];
}
return $return;
}
} }

View File

@@ -32,7 +32,6 @@ use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Administration\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface; use FireflyIII\Repositories\Administration\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
use FireflyIII\Support\Http\Api\AccountFilter; use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use JsonException; use JsonException;

View File

@@ -64,54 +64,6 @@ class Controller extends BaseController
} }
} }
/**
* @param string $key
* @param LengthAwarePaginator $paginator
* @param AbstractTransformer $transformer
*
* @return array
*/
final protected function jsonApiList(string $key, LengthAwarePaginator $paginator, AbstractTransformer $transformer): array
{
$manager = new Manager();
$baseUrl = request()->getSchemeAndHttpHost().'/api/v2';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$objects = $paginator->getCollection();
// the transformer, at this point, needs to collect information that ALL items in the collection
// require, like meta data and stuff like that, and save it for later.
$transformer->collectMetaData($objects);
$resource = new FractalCollection($objects, $transformer, $key);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return $manager->createData($resource)->toArray();
}
/**
* Returns a JSON API object and returns it.
*
* @param string $key
* @param Model $object
* @param AbstractTransformer $transformer
*
* @return array
*/
final protected function jsonApiObject(string $key, Model $object, AbstractTransformer $transformer): array
{
// create some objects:
$manager = new Manager();
$baseUrl = request()->getSchemeAndHttpHost().'/api/v2';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$transformer->collectMetaData(new Collection([$object]));
$resource = new Item($object, $transformer, $key);
return $manager->createData($resource)->toArray();
}
/** /**
* TODO duplicate from V1 controller * TODO duplicate from V1 controller
* Method to grab all parameters from the URL. * Method to grab all parameters from the URL.
@@ -123,7 +75,7 @@ class Controller extends BaseController
$bag = new ParameterBag(); $bag = new ParameterBag();
try { try {
$page = (int)request()->get('page'); $page = (int)request()->get('page');
} catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) { } catch (ContainerExceptionInterface | NotFoundExceptionInterface $e) {
$page = 1; $page = 1;
} }
@@ -152,7 +104,7 @@ class Controller extends BaseController
if (null !== $date) { if (null !== $date) {
try { try {
$obj = Carbon::parse($date); $obj = Carbon::parse($date);
} catch (InvalidDateException|InvalidFormatException $e) { } catch (InvalidDateException | InvalidFormatException $e) {
// don't care // don't care
app('log')->warning(sprintf('Ignored invalid date "%s" in API v2 controller parameter check: %s', substr($date, 0, 20), $e->getMessage())); app('log')->warning(sprintf('Ignored invalid date "%s" in API v2 controller parameter check: %s', substr($date, 0, 20), $e->getMessage()));
} }
@@ -179,4 +131,52 @@ class Controller extends BaseController
return $bag; return $bag;
} }
/**
* @param string $key
* @param LengthAwarePaginator $paginator
* @param AbstractTransformer $transformer
*
* @return array
*/
final protected function jsonApiList(string $key, LengthAwarePaginator $paginator, AbstractTransformer $transformer): array
{
$manager = new Manager();
$baseUrl = request()->getSchemeAndHttpHost() . '/api/v2';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$objects = $paginator->getCollection();
// the transformer, at this point, needs to collect information that ALL items in the collection
// require, like meta data and stuff like that, and save it for later.
$transformer->collectMetaData($objects);
$resource = new FractalCollection($objects, $transformer, $key);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return $manager->createData($resource)->toArray();
}
/**
* Returns a JSON API object and returns it.
*
* @param string $key
* @param Model $object
* @param AbstractTransformer $transformer
*
* @return array
*/
final protected function jsonApiObject(string $key, Model $object, AbstractTransformer $transformer): array
{
// create some objects:
$manager = new Manager();
$baseUrl = request()->getSchemeAndHttpHost() . '/api/v2';
$manager->setSerializer(new JsonApiSerializer($baseUrl));
$transformer->collectMetaData(new Collection([$object]));
$resource = new Item($object, $transformer, $key);
return $manager->createData($resource)->toArray();
}
} }

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\AutoBudget; use FireflyIII\Models\AutoBudget;
use FireflyIII\Models\AvailableBudget; use FireflyIII\Models\AvailableBudget;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
@@ -39,6 +40,8 @@ use Illuminate\Console\Command;
*/ */
class CorrectAmounts extends Command class CorrectAmounts extends Command
{ {
use ShowsFriendlyMessages;
protected $description = 'This command makes sure positive and negative amounts are recorded correctly.'; protected $description = 'This command makes sure positive and negative amounts are recorded correctly.';
protected $signature = 'firefly-iii:fix-amount-pos-neg'; protected $signature = 'firefly-iii:fix-amount-pos-neg';
@@ -78,7 +81,7 @@ class CorrectAmounts extends Command
$set = AutoBudget::where('amount', '<', 0)->get(); $set = AutoBudget::where('amount', '<', 0)->get();
$count = $set->count(); $count = $set->count();
if (0 === $count) { if (0 === $count) {
$this->info('Correct: All auto budget amounts are positive.'); $this->friendlyPositive('All auto budget amounts are positive.');
return; return;
} }
@@ -87,7 +90,7 @@ class CorrectAmounts extends Command
$item->amount = app('steam')->positive((string)$item->amount); $item->amount = app('steam')->positive((string)$item->amount);
$item->save(); $item->save();
} }
$this->line(sprintf('Corrected %d auto budget amount(s).', $count)); $this->friendlyInfo(sprintf('Corrected %d auto budget amount(s).', $count));
} }
/** /**
@@ -98,7 +101,7 @@ class CorrectAmounts extends Command
$set = AvailableBudget::where('amount', '<', 0)->get(); $set = AvailableBudget::where('amount', '<', 0)->get();
$count = $set->count(); $count = $set->count();
if (0 === $count) { if (0 === $count) {
$this->info('Correct: All available budget amounts are positive.'); $this->friendlyPositive('All available budget amounts are positive.');
return; return;
} }
@@ -107,7 +110,7 @@ class CorrectAmounts extends Command
$item->amount = app('steam')->positive((string)$item->amount); $item->amount = app('steam')->positive((string)$item->amount);
$item->save(); $item->save();
} }
$this->line(sprintf('Corrected %d available budget amount(s).', $count)); $this->friendlyInfo(sprintf('Corrected %d available budget amount(s).', $count));
} }
/** /**
@@ -118,7 +121,7 @@ class CorrectAmounts extends Command
$set = Bill::where('amount_min', '<', 0)->orWhere('amount_max', '<', 0)->get(); $set = Bill::where('amount_min', '<', 0)->orWhere('amount_max', '<', 0)->get();
$count = $set->count(); $count = $set->count();
if (0 === $count) { if (0 === $count) {
$this->info('Correct: All bill amounts are positive.'); $this->friendlyPositive('All bill amounts are positive.');
return; return;
} }
@@ -128,6 +131,7 @@ class CorrectAmounts extends Command
$item->amount_max = app('steam')->positive((string)$item->amount_max); $item->amount_max = app('steam')->positive((string)$item->amount_max);
$item->save(); $item->save();
} }
$this->friendlyInfo(sprintf('Corrected %d bill amount(s).', $count));
} }
/** /**
@@ -138,7 +142,7 @@ class CorrectAmounts extends Command
$set = BudgetLimit::where('amount', '<', 0)->get(); $set = BudgetLimit::where('amount', '<', 0)->get();
$count = $set->count(); $count = $set->count();
if (0 === $count) { if (0 === $count) {
$this->info('Correct: All budget limit amounts are positive.'); $this->friendlyPositive('All budget limit amounts are positive.');
return; return;
} }
@@ -147,7 +151,7 @@ class CorrectAmounts extends Command
$item->amount = app('steam')->positive((string)$item->amount); $item->amount = app('steam')->positive((string)$item->amount);
$item->save(); $item->save();
} }
$this->line(sprintf('Corrected %d budget limit amount(s).', $count)); $this->friendlyInfo(sprintf('Corrected %d budget limit amount(s).', $count));
} }
/** /**
@@ -158,7 +162,7 @@ class CorrectAmounts extends Command
$set = CurrencyExchangeRate::where('rate', '<', 0)->get(); $set = CurrencyExchangeRate::where('rate', '<', 0)->get();
$count = $set->count(); $count = $set->count();
if (0 === $count) { if (0 === $count) {
$this->info('Correct: All currency exchange rates are positive.'); $this->friendlyPositive('All currency exchange rates are positive.');
return; return;
} }
@@ -167,7 +171,27 @@ class CorrectAmounts extends Command
$item->rate = app('steam')->positive((string)$item->rate); $item->rate = app('steam')->positive((string)$item->rate);
$item->save(); $item->save();
} }
$this->line(sprintf('Corrected %d currency exchange rate(s).', $count)); $this->friendlyInfo(sprintf('Corrected %d currency exchange rate(s).', $count));
}
/**
* @return void
*/
private function fixRepetitions(): void
{
$set = PiggyBankRepetition::where('currentamount', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->friendlyPositive('All piggy bank repetition amounts are positive.');
return;
}
/** @var PiggyBankRepetition $item */
foreach ($set as $item) {
$item->currentamount = app('steam')->positive((string)$item->currentamount);
$item->save();
}
$this->friendlyInfo(sprintf('Corrected %d piggy bank repetition amount(s).', $count));
} }
/** /**
@@ -178,7 +202,7 @@ class CorrectAmounts extends Command
$set = PiggyBank::where('targetamount', '<', 0)->get(); $set = PiggyBank::where('targetamount', '<', 0)->get();
$count = $set->count(); $count = $set->count();
if (0 === $count) { if (0 === $count) {
$this->info('Correct: All piggy bank amounts are positive.'); $this->friendlyPositive('All piggy bank amounts are positive.');
return; return;
} }
@@ -187,7 +211,7 @@ class CorrectAmounts extends Command
$item->targetamount = app('steam')->positive((string)$item->targetamount); $item->targetamount = app('steam')->positive((string)$item->targetamount);
$item->save(); $item->save();
} }
$this->line(sprintf('Corrected %d piggy bank amount(s).', $count)); $this->friendlyInfo(sprintf('Corrected %d piggy bank amount(s).', $count));
} }
/** /**
@@ -200,7 +224,7 @@ class CorrectAmounts extends Command
->get(); ->get();
$count = $set->count(); $count = $set->count();
if (0 === $count) { if (0 === $count) {
$this->info('Correct: All recurring transaction amounts are positive.'); $this->friendlyPositive('All recurring transaction amounts are positive.');
return; return;
} }
@@ -210,27 +234,7 @@ class CorrectAmounts extends Command
$item->foreign_amount = app('steam')->positive((string)$item->foreign_amount); $item->foreign_amount = app('steam')->positive((string)$item->foreign_amount);
$item->save(); $item->save();
} }
$this->line(sprintf('Corrected %d recurring transaction amount(s).', $count)); $this->friendlyInfo(sprintf('Corrected %d recurring transaction amount(s).', $count));
}
/**
* @return void
*/
private function fixRepetitions(): void
{
$set = PiggyBankRepetition::where('currentamount', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->info('Correct: All piggy bank repetition amounts are positive.');
return;
}
/** @var PiggyBankRepetition $item */
foreach ($set as $item) {
$item->currentamount = app('steam')->positive((string)$item->currentamount);
$item->save();
}
$this->line(sprintf('Corrected %d piggy bank repetition amount(s).', $count));
} }
/** /**
@@ -250,11 +254,11 @@ class CorrectAmounts extends Command
} }
} }
if (0 === $fixed) { if (0 === $fixed) {
$this->info('Correct: All rule trigger amounts are positive.'); $this->friendlyPositive('All rule trigger amounts are positive.');
return; return;
} }
$this->line(sprintf('Corrected %d rule trigger amount(s).', $fixed)); $this->friendlyInfo(sprintf('Corrected %d rule trigger amount(s).', $fixed));
} }
} }

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use Artisan; use Artisan;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Schema; use Schema;
@@ -34,6 +35,8 @@ use Schema;
*/ */
class CorrectDatabase extends Command class CorrectDatabase extends Command
{ {
use ShowsFriendlyMessages;
protected $description = 'Will correct the integrity of your database, if necessary.'; protected $description = 'Will correct the integrity of your database, if necessary.';
protected $signature = 'firefly-iii:correct-database'; protected $signature = 'firefly-iii:correct-database';
@@ -44,7 +47,7 @@ class CorrectDatabase extends Command
{ {
// if table does not exist, return false // if table does not exist, return false
if (!Schema::hasTable('users')) { if (!Schema::hasTable('users')) {
$this->error('No "users"-table, will not continue.'); $this->friendlyError('No "users"-table, will not continue.');
return 1; return 1;
} }
@@ -76,7 +79,7 @@ class CorrectDatabase extends Command
'firefly-iii:trigger-credit-recalculation', 'firefly-iii:trigger-credit-recalculation',
]; ];
foreach ($commands as $command) { foreach ($commands as $command) {
$this->line(sprintf('Now executing command "%s"', $command)); $this->friendlyLine(sprintf('Now executing command "%s"', $command));
$this->call($command); $this->call($command);
} }

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
@@ -39,6 +40,8 @@ use Illuminate\Support\Collection;
*/ */
class CorrectOpeningBalanceCurrencies extends Command class CorrectOpeningBalanceCurrencies extends Command
{ {
use ShowsFriendlyMessages;
protected $description = 'Will make sure that opening balance transaction currencies match the account they\'re for.'; protected $description = 'Will make sure that opening balance transaction currencies match the account they\'re for.';
protected $signature = 'firefly-iii:fix-ob-currencies'; protected $signature = 'firefly-iii:fix-ob-currencies';
@@ -58,16 +61,27 @@ class CorrectOpeningBalanceCurrencies extends Command
if ($count > 0) { if ($count > 0) {
$message = sprintf('Corrected %d opening balance transaction(s).', $count); $message = sprintf('Corrected %d opening balance transaction(s).', $count);
$this->line($message); $this->friendlyInfo($message);
} }
if (0 === $count) { if (0 === $count) {
$message = 'Correct: There was nothing to fix in the opening balance transactions.'; $message = 'There was nothing to fix in the opening balance transactions.';
$this->info($message); $this->friendlyPositive($message);
} }
return 0; return 0;
} }
/**
* @return Collection
*/
private function getJournals(): Collection
{
/** @var Collection */
return TransactionJournal::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->whereNull('transaction_journals.deleted_at')
->where('transaction_types.type', TransactionType::OPENING_BALANCE)->get(['transaction_journals.*']);
}
/** /**
* @param TransactionJournal $journal * @param TransactionJournal $journal
* *
@@ -80,7 +94,7 @@ class CorrectOpeningBalanceCurrencies extends Command
if (null === $account) { if (null === $account) {
$message = sprintf('Transaction journal #%d has no valid account. Can\'t fix this line.', $journal->id); $message = sprintf('Transaction journal #%d has no valid account. Can\'t fix this line.', $journal->id);
app('log')->warning($message); app('log')->warning($message);
$this->warn($message); $this->friendlyError($message);
return 0; return 0;
} }
@@ -109,31 +123,6 @@ class CorrectOpeningBalanceCurrencies extends Command
return null; return null;
} }
/**
* @param Account $account
*
* @return TransactionCurrency
*/
private function getCurrency(Account $account): TransactionCurrency
{
/** @var AccountRepositoryInterface $repos */
$repos = app(AccountRepositoryInterface::class);
$repos->setUser($account->user);
return $repos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUser($account->user);
}
/**
* @return Collection
*/
private function getJournals(): Collection
{
/** @var Collection */
return TransactionJournal::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->whereNull('transaction_journals.deleted_at')
->where('transaction_types.type', TransactionType::OPENING_BALANCE)->get(['transaction_journals.*']);
}
/** /**
* @param Account $account * @param Account $account
* @param TransactionJournal $journal * @param TransactionJournal $journal
@@ -160,4 +149,18 @@ class CorrectOpeningBalanceCurrencies extends Command
return $count; return $count;
} }
/**
* @param Account $account
*
* @return TransactionCurrency
*/
private function getCurrency(Account $account): TransactionCurrency
{
/** @var AccountRepositoryInterface $repos */
$repos = app(AccountRepositoryInterface::class);
$repos->setUser($account->user);
return $repos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUser($account->user);
}
} }

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use Exception; use Exception;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -33,6 +34,8 @@ use Illuminate\Console\Command;
*/ */
class CreateAccessTokens extends Command class CreateAccessTokens extends Command
{ {
use ShowsFriendlyMessages;
/** /**
* The console command description. * The console command description.
* *
@@ -66,12 +69,12 @@ class CreateAccessTokens extends Command
if (null === $pref) { if (null === $pref) {
$token = $user->generateAccessToken(); $token = $user->generateAccessToken();
app('preferences')->setForUser($user, 'access_token', $token); app('preferences')->setForUser($user, 'access_token', $token);
$this->line(sprintf('Generated access token for user %s', $user->email)); $this->friendlyInfo(sprintf('Generated access token for user %s', $user->email));
++$count; ++$count;
} }
} }
if (0 === $count) { if (0 === $count) {
$this->info('Correct: Verified access tokens.'); $this->friendlyPositive('Verified access tokens.');
} }
return 0; return 0;

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\LinkType; use FireflyIII\Models\LinkType;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -31,6 +32,8 @@ use Illuminate\Console\Command;
*/ */
class CreateLinkTypes extends Command class CreateLinkTypes extends Command
{ {
use ShowsFriendlyMessages;
/** /**
* The console command description. * The console command description.
* *
@@ -67,13 +70,13 @@ class CreateLinkTypes extends Command
$link->inward = $values[1]; $link->inward = $values[1];
$link->outward = $values[0]; $link->outward = $values[0];
++$count; ++$count;
$this->line(sprintf('Created missing link type "%s"', $name)); $this->friendlyInfo(sprintf('Created missing link type "%s"', $name));
} }
$link->editable = false; $link->editable = false;
$link->save(); $link->save();
} }
if (0 === $count) { if (0 === $count) {
$this->info('Correct: all link types are OK'); $this->friendlyPositive('All link types are OK');
} }
return 0; return 0;
} }

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use Exception; use Exception;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionGroup;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -32,6 +33,8 @@ use Illuminate\Console\Command;
*/ */
class DeleteEmptyGroups extends Command class DeleteEmptyGroups extends Command
{ {
use ShowsFriendlyMessages;
protected $description = 'Delete empty transaction groups.'; protected $description = 'Delete empty transaction groups.';
protected $signature = 'firefly-iii:delete-empty-groups'; protected $signature = 'firefly-iii:delete-empty-groups';
@@ -50,7 +53,7 @@ class DeleteEmptyGroups extends Command
$total = count($groupIds); $total = count($groupIds);
if ($total > 0) { if ($total > 0) {
$this->info(sprintf('Deleted %d empty transaction group(s).', $total)); $this->friendlyInfo(sprintf('Deleted %d empty transaction group(s).', $total));
// again, chunks for SQLite. // again, chunks for SQLite.
$chunks = array_chunk($groupIds, 500); $chunks = array_chunk($groupIds, 500);
@@ -59,7 +62,7 @@ class DeleteEmptyGroups extends Command
} }
} }
if (0 === $total) { if (0 === $total) {
$this->info('Correct: verified empty groups.'); $this->friendlyInfo('Verified there are no empty groups.');
} }
return 0; return 0;

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use DB; use DB;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -35,6 +36,8 @@ use Illuminate\Support\Facades\Log;
*/ */
class DeleteEmptyJournals extends Command class DeleteEmptyJournals extends Command
{ {
use ShowsFriendlyMessages;
/** /**
* The console command description. * The console command description.
* *
@@ -61,30 +64,6 @@ class DeleteEmptyJournals extends Command
return 0; return 0;
} }
private function deleteEmptyJournals(): void
{
$count = 0;
$set = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->groupBy('transaction_journals.id')
->whereNull('transactions.transaction_journal_id')
->get(['transaction_journals.id']);
foreach ($set as $entry) {
try {
TransactionJournal::find($entry->id)->delete();
} catch (QueryException $e) {
Log::info(sprintf('Could not delete entry: %s', $e->getMessage()));
}
$this->info(sprintf('Deleted empty transaction journal #%d', $entry->id));
++$count;
}
if (0 === $count) {
$this->info('Correct: no empty transaction journals.');
}
}
/** /**
* Delete transactions and their journals if they have an uneven number of transactions. * Delete transactions and their journals if they have an uneven number of transactions.
*/ */
@@ -107,12 +86,38 @@ class DeleteEmptyJournals extends Command
Transaction::where('transaction_journal_id', (int)$row->transaction_journal_id)->delete(); Transaction::where('transaction_journal_id', (int)$row->transaction_journal_id)->delete();
$this->info(sprintf('Deleted transaction journal #%d because it had an uneven number of transactions.', $row->transaction_journal_id)); $this->friendlyWarning(
sprintf('Deleted transaction journal #%d because it had an uneven number of transactions.', $row->transaction_journal_id)
);
$total++; $total++;
} }
} }
if (0 === $total) { if (0 === $total) {
$this->info('Correct: no uneven transaction journals.'); $this->friendlyPositive('No uneven transaction journals.');
}
}
private function deleteEmptyJournals(): void
{
$count = 0;
$set = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->groupBy('transaction_journals.id')
->whereNull('transactions.transaction_journal_id')
->get(['transaction_journals.id']);
foreach ($set as $entry) {
try {
TransactionJournal::find($entry->id)->delete();
} catch (QueryException $e) {
Log::info(sprintf('Could not delete entry: %s', $e->getMessage()));
}
$this->friendlyInfo(sprintf('Deleted empty transaction journal #%d', $entry->id));
++$count;
}
if (0 === $count) {
$this->friendlyPositive('No empty transaction journals.');
} }
} }
} }

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use Exception; use Exception;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -34,6 +35,8 @@ use stdClass;
*/ */
class DeleteOrphanedTransactions extends Command class DeleteOrphanedTransactions extends Command
{ {
use ShowsFriendlyMessages;
/** /**
* The console command description. * The console command description.
* *
@@ -62,38 +65,6 @@ class DeleteOrphanedTransactions extends Command
return 0; return 0;
} }
/**
*
*/
private function deleteFromOrphanedAccounts(): void
{
$set
= Transaction::leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id')
->whereNotNull('accounts.deleted_at')
->get(['transactions.*']);
$count = 0;
/** @var Transaction $transaction */
foreach ($set as $transaction) {
// delete journals
$journal = TransactionJournal::find((int)$transaction->transaction_journal_id);
if ($journal) {
$journal->delete();
}
Transaction::where('transaction_journal_id', (int)$transaction->transaction_journal_id)->delete();
$this->line(
sprintf(
'Deleted transaction journal #%d because account #%d was already deleted.',
$transaction->transaction_journal_id,
$transaction->account_id
)
);
$count++;
}
if (0 === $count) {
$this->info('Correct: no orphaned accounts.');
}
}
private function deleteOrphanedJournals(): void private function deleteOrphanedJournals(): void
{ {
$set = TransactionJournal::leftJoin('transaction_groups', 'transaction_journals.transaction_group_id', 'transaction_groups.id') $set = TransactionJournal::leftJoin('transaction_groups', 'transaction_journals.transaction_group_id', 'transaction_groups.id')
@@ -102,15 +73,15 @@ class DeleteOrphanedTransactions extends Command
->get(['transaction_journals.id', 'transaction_journals.transaction_group_id']); ->get(['transaction_journals.id', 'transaction_journals.transaction_group_id']);
$count = $set->count(); $count = $set->count();
if (0 === $count) { if (0 === $count) {
$this->info('Correct: no orphaned journals.'); $this->friendlyPositive('No orphaned journals.');
return;
} }
if ($count > 0) { $this->friendlyInfo(sprintf('Found %d orphaned journal(s).', $count));
$this->info(sprintf('Found %d orphaned journal(s).', $count));
foreach ($set as $entry) { foreach ($set as $entry) {
$journal = TransactionJournal::withTrashed()->find((int)$entry->id); $journal = TransactionJournal::withTrashed()->find((int)$entry->id);
if (null !== $journal) { if (null !== $journal) {
$journal->delete(); $journal->delete();
$this->info( $this->friendlyWarning(
sprintf( sprintf(
'Journal #%d (part of deleted transaction group #%d) has been deleted as well.', 'Journal #%d (part of deleted transaction group #%d) has been deleted as well.',
$entry->id, $entry->id,
@@ -120,7 +91,6 @@ class DeleteOrphanedTransactions extends Command
} }
} }
} }
}
/** /**
* @throws Exception * @throws Exception
@@ -143,7 +113,7 @@ class DeleteOrphanedTransactions extends Command
$transaction = Transaction::find((int)$entry->transaction_id); $transaction = Transaction::find((int)$entry->transaction_id);
if (null !== $transaction) { if (null !== $transaction) {
$transaction->delete(); $transaction->delete();
$this->info( $this->friendlyWarning(
sprintf( sprintf(
'Transaction #%d (part of deleted transaction journal #%d) has been deleted as well.', 'Transaction #%d (part of deleted transaction journal #%d) has been deleted as well.',
$entry->transaction_id, $entry->transaction_id,
@@ -154,7 +124,39 @@ class DeleteOrphanedTransactions extends Command
} }
} }
if (0 === $count) { if (0 === $count) {
$this->info('Correct: no orphaned transactions.'); $this->friendlyPositive('No orphaned transactions.');
}
}
/**
*
*/
private function deleteFromOrphanedAccounts(): void
{
$set
= Transaction::leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id')
->whereNotNull('accounts.deleted_at')
->get(['transactions.*']);
$count = 0;
/** @var Transaction $transaction */
foreach ($set as $transaction) {
// delete journals
$journal = TransactionJournal::find((int)$transaction->transaction_journal_id);
if ($journal) {
$journal->delete();
}
Transaction::where('transaction_journal_id', (int)$transaction->transaction_journal_id)->delete();
$this->friendlyWarning(
sprintf(
'Deleted transaction journal #%d because account #%d was already deleted.',
$transaction->transaction_journal_id,
$transaction->account_id
)
);
$count++;
}
if (0 === $count) {
$this->friendlyPositive('No orphaned accounts.');
} }
} }
} }

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -32,6 +33,8 @@ use Illuminate\Console\Command;
*/ */
class DeleteZeroAmount extends Command class DeleteZeroAmount extends Command
{ {
use ShowsFriendlyMessages;
/** /**
* The console command description. * The console command description.
* *
@@ -57,13 +60,13 @@ class DeleteZeroAmount extends Command
$journals = TransactionJournal::whereIn('id', $set)->get(); $journals = TransactionJournal::whereIn('id', $set)->get();
/** @var TransactionJournal $journal */ /** @var TransactionJournal $journal */
foreach ($journals as $journal) { foreach ($journals as $journal) {
$this->info(sprintf('Deleted transaction journal #%d because the amount is zero (0.00).', $journal->id)); $this->friendlyWarning(sprintf('Deleted transaction journal #%d because the amount is zero (0.00).', $journal->id));
$journal->delete(); $journal->delete();
Transaction::where('transaction_journal_id', $journal->id)->delete(); Transaction::where('transaction_journal_id', $journal->id)->delete();
} }
if (0 === $journals->count()) { if (0 === $journals->count()) {
$this->info('Correct: no zero-amount transaction journals.'); $this->friendlyPositive('No zero-amount transaction journals.');
} }
return 0; return 0;

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\AccountMeta; use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
@@ -30,13 +31,14 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
/** /**
* Class EnableCurrencies * Class EnableCurrencies
*/ */
class EnableCurrencies extends Command class EnableCurrencies extends Command
{ {
use ShowsFriendlyMessages;
protected $description = 'Enables all currencies in use.'; protected $description = 'Enables all currencies in use.';
protected $signature = 'firefly-iii:enable-currencies'; protected $signature = 'firefly-iii:enable-currencies';
@@ -85,10 +87,10 @@ class EnableCurrencies extends Command
); );
$disabled = TransactionCurrency::whereIn('id', $found)->where('enabled', false)->count(); $disabled = TransactionCurrency::whereIn('id', $found)->where('enabled', false)->count();
if ($disabled > 0) { if ($disabled > 0) {
$this->info(sprintf('%d were (was) still disabled. This has been corrected.', $disabled)); $this->friendlyInfo(sprintf('%d currencies were (was) disabled while in use by transactions. This has been corrected.', $disabled));
} }
if (0 === $disabled) { if (0 === $disabled) {
$this->info('Correct: All currencies are correctly enabled or disabled.'); $this->friendlyPositive('All currencies are correctly enabled or disabled.');
} }
TransactionCurrency::whereIn('id', $found)->update(['enabled' => true]); TransactionCurrency::whereIn('id', $found)->update(['enabled' => true]);

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -32,6 +33,8 @@ use Illuminate\Console\Command;
*/ */
class FixAccountOrder extends Command class FixAccountOrder extends Command
{ {
use ShowsFriendlyMessages;
protected $description = 'Make sure account order is correct.'; protected $description = 'Make sure account order is correct.';
protected $signature = 'firefly-iii:fix-account-order'; protected $signature = 'firefly-iii:fix-account-order';
@@ -52,7 +55,7 @@ class FixAccountOrder extends Command
$this->repository->resetAccountOrder(); $this->repository->resetAccountOrder();
} }
$this->info('Correct: All accounts are ordered correctly'); $this->friendlyPositive('All accounts are ordered correctly');
return 0; return 0;
} }

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\AccountFactory; use FireflyIII\Factory\AccountFactory;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
@@ -30,14 +31,16 @@ use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use JsonException;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use JsonException;
/** /**
* Class FixAccountTypes * Class FixAccountTypes
*/ */
class FixAccountTypes extends Command class FixAccountTypes extends Command
{ {
use ShowsFriendlyMessages;
protected $description = 'Make sure all journals have the correct from/to account types.'; protected $description = 'Make sure all journals have the correct from/to account types.';
protected $signature = 'firefly-iii:fix-account-types'; protected $signature = 'firefly-iii:fix-account-types';
private int $count; private int $count;
@@ -60,16 +63,89 @@ class FixAccountTypes extends Command
$this->inspectJournal($journal); $this->inspectJournal($journal);
} }
if (0 === $this->count) { if (0 === $this->count) {
$this->info('Correct: all account types are OK'); $this->friendlyPositive('All account types are OK');
} }
if (0 !== $this->count) { if (0 !== $this->count) {
Log::debug(sprintf('%d journals had to be fixed.', $this->count)); Log::debug(sprintf('%d journals had to be fixed.', $this->count));
$this->info(sprintf('Acted on %d transaction(s)!', $this->count)); $this->friendlyInfo(sprintf('Acted on %d transaction(s)', $this->count));
} }
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
*/
private function stupidLaravel(): void
{
$this->count = 0;
}
/**
* @param TransactionJournal $journal
*
* @throws FireflyException
*/
private function inspectJournal(TransactionJournal $journal): void
{
$transactions = $journal->transactions()->count();
if (2 !== $transactions) {
Log::debug(sprintf('Journal has %d transactions, so can\'t fix.', $transactions));
$this->friendlyError(sprintf('Cannot inspect transaction journal #%d because it has %d transaction(s) instead of 2.', $journal->id, $transactions));
return;
}
$type = $journal->transactionType->type;
$sourceTransaction = $this->getSourceTransaction($journal);
$destTransaction = $this->getDestinationTransaction($journal);
$sourceAccount = $sourceTransaction->account;
$sourceAccountType = $sourceAccount->accountType->type;
$destAccount = $destTransaction->account;
$destAccountType = $destAccount->accountType->type;
if (!array_key_exists($type, $this->expected)) {
Log::info(sprintf('No source/destination info for transaction type %s.', $type));
$this->friendlyError(sprintf('No source/destination info for transaction type %s.', $type));
return;
}
if (!array_key_exists($sourceAccountType, $this->expected[$type])) {
Log::debug(sprintf('Going to fix journal #%d', $journal->id));
$this->fixJournal($journal, $type, $sourceTransaction, $destTransaction);
return;
}
$expectedTypes = $this->expected[$type][$sourceAccountType];
if (!in_array($destAccountType, $expectedTypes, true)) {
Log::debug(sprintf('Going to fix journal #%d', $journal->id));
$this->fixJournal($journal, $type, $sourceTransaction, $destTransaction);
}
}
/**
* @param TransactionJournal $journal
*
* @return Transaction
*/
private function getSourceTransaction(TransactionJournal $journal): Transaction
{
return $journal->transactions->firstWhere('amount', '<', 0);
}
/**
* @param TransactionJournal $journal
*
* @return Transaction
*/
private function getDestinationTransaction(TransactionJournal $journal): Transaction
{
return $journal->transactions->firstWhere('amount', '>', 0);
}
/** /**
* @param TransactionJournal $journal * @param TransactionJournal $journal
* @param string $type * @param string $type
@@ -94,7 +170,7 @@ class FixAccountTypes extends Command
$journal->transactionType()->associate($withdrawal); $journal->transactionType()->associate($withdrawal);
$journal->save(); $journal->save();
$message = sprintf('Converted transaction #%d from a transfer to a withdrawal.', $journal->id); $message = sprintf('Converted transaction #%d from a transfer to a withdrawal.', $journal->id);
$this->info($message); $this->friendlyInfo($message);
Log::debug($message); Log::debug($message);
// check it again: // check it again:
$this->inspectJournal($journal); $this->inspectJournal($journal);
@@ -107,7 +183,7 @@ class FixAccountTypes extends Command
$journal->transactionType()->associate($deposit); $journal->transactionType()->associate($deposit);
$journal->save(); $journal->save();
$message = sprintf('Converted transaction #%d from a transfer to a deposit.', $journal->id); $message = sprintf('Converted transaction #%d from a transfer to a deposit.', $journal->id);
$this->info($message); $this->friendlyInfo($message);
Log::debug($message); Log::debug($message);
// check it again: // check it again:
$this->inspectJournal($journal); $this->inspectJournal($journal);
@@ -128,7 +204,7 @@ class FixAccountTypes extends Command
$result->id, $result->id,
$result->name $result->name
); );
$this->info($message); $this->friendlyWarning($message);
Log::debug($message); Log::debug($message);
$this->inspectJournal($journal); $this->inspectJournal($journal);
break; break;
@@ -148,93 +224,20 @@ class FixAccountTypes extends Command
$result->id, $result->id,
$result->name $result->name
); );
$this->info($message); $this->friendlyWarning($message);
Log::debug($message); Log::debug($message);
$this->inspectJournal($journal); $this->inspectJournal($journal);
break; break;
default: default:
$message = sprintf('The source account of %s #%d cannot be of type "%s".', $type, $journal->id, $source->account->accountType->type); $message = sprintf('The source account of %s #%d cannot be of type "%s".', $type, $journal->id, $source->account->accountType->type);
$this->info($message); $this->friendlyError($message);
Log::debug($message); Log::debug($message);
$message = sprintf('The destination account of %s #%d cannot be of type "%s".', $type, $journal->id, $dest->account->accountType->type); $message = sprintf('The destination account of %s #%d cannot be of type "%s".', $type, $journal->id, $dest->account->accountType->type);
$this->info($message); $this->friendlyError($message);
Log::debug($message); Log::debug($message);
break; break;
} }
} }
/**
* @param TransactionJournal $journal
*
* @return Transaction
*/
private function getDestinationTransaction(TransactionJournal $journal): Transaction
{
return $journal->transactions->firstWhere('amount', '>', 0);
}
/**
* @param TransactionJournal $journal
*
* @return Transaction
*/
private function getSourceTransaction(TransactionJournal $journal): Transaction
{
return $journal->transactions->firstWhere('amount', '<', 0);
}
/**
* @param TransactionJournal $journal
*
* @throws FireflyException
*/
private function inspectJournal(TransactionJournal $journal): void
{
$transactions = $journal->transactions()->count();
if (2 !== $transactions) {
Log::debug(sprintf('Journal has %d transactions, so can\'t fix.', $transactions));
$this->info(sprintf('Cannot inspect transaction journal #%d because it has %d transaction(s) instead of 2.', $journal->id, $transactions));
return;
}
$type = $journal->transactionType->type;
$sourceTransaction = $this->getSourceTransaction($journal);
$destTransaction = $this->getDestinationTransaction($journal);
$sourceAccount = $sourceTransaction->account;
$sourceAccountType = $sourceAccount->accountType->type;
$destAccount = $destTransaction->account;
$destAccountType = $destAccount->accountType->type;
if (!array_key_exists($type, $this->expected)) {
Log::info(sprintf('No source/destination info for transaction type %s.', $type));
$this->info(sprintf('No source/destination info for transaction type %s.', $type));
return;
}
if (!array_key_exists($sourceAccountType, $this->expected[$type])) {
Log::debug(sprintf('Going to fix journal #%d', $journal->id));
$this->fixJournal($journal, $type, $sourceTransaction, $destTransaction);
return;
}
$expectedTypes = $this->expected[$type][$sourceAccountType];
if (!in_array($destAccountType, $expectedTypes, true)) {
Log::debug(sprintf('Going to fix journal #%d', $journal->id));
$this->fixJournal($journal, $type, $sourceTransaction, $destTransaction);
}
}
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
*/
private function stupidLaravel(): void
{
$this->count = 0;
}
} }

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use FireflyIII\Models\Preference; use FireflyIII\Models\Preference;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
@@ -36,6 +37,8 @@ use Illuminate\Console\Command;
*/ */
class FixFrontpageAccounts extends Command class FixFrontpageAccounts extends Command
{ {
use ShowsFriendlyMessages;
protected $description = 'Fixes a preference that may include deleted accounts or accounts of another type.'; protected $description = 'Fixes a preference that may include deleted accounts or accounts of another type.';
protected $signature = 'firefly-iii:fix-frontpage-accounts'; protected $signature = 'firefly-iii:fix-frontpage-accounts';
@@ -54,7 +57,7 @@ class FixFrontpageAccounts extends Command
$this->fixPreference($preference); $this->fixPreference($preference);
} }
} }
$this->info('Correct: account preferences are OK'); $this->friendlyPositive('Account preferences are OK');
return 0; return 0;
} }

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use DB; use DB;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Events\UpdatedTransactionGroup; use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Handlers\Events\UpdatedGroupEventHandler; use FireflyIII\Handlers\Events\UpdatedGroupEventHandler;
use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionGroup;
@@ -36,6 +37,8 @@ use Illuminate\Console\Command;
*/ */
class FixGroupAccounts extends Command class FixGroupAccounts extends Command
{ {
use ShowsFriendlyMessages;
protected $description = 'Unify the source / destination accounts of split groups.'; protected $description = 'Unify the source / destination accounts of split groups.';
protected $signature = 'firefly-iii:unify-group-accounts'; protected $signature = 'firefly-iii:unify-group-accounts';
@@ -62,7 +65,7 @@ class FixGroupAccounts extends Command
$handler->unifyAccounts($event); $handler->unifyAccounts($event);
} }
$this->info('Correct: updated possible inconsistent transaction groups.'); $this->friendlyPositive('Updated possible inconsistent transaction groups.');
return 0; return 0;
} }

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -34,6 +35,8 @@ use Illuminate\Support\Collection;
*/ */
class FixIbans extends Command class FixIbans extends Command
{ {
use ShowsFriendlyMessages;
protected $description = 'Removes spaces from IBANs'; protected $description = 'Removes spaces from IBANs';
protected $signature = 'firefly-iii:fix-ibans'; protected $signature = 'firefly-iii:fix-ibans';
private int $count = 0; private int $count = 0;
@@ -49,12 +52,34 @@ class FixIbans extends Command
$this->filterIbans($accounts); $this->filterIbans($accounts);
$this->countAndCorrectIbans($accounts); $this->countAndCorrectIbans($accounts);
if (0 === $this->count) { if (0 === $this->count) {
$this->info('Correct: All IBANs are valid.'); $this->friendlyPositive('All IBANs are valid.');
} }
return 0; return 0;
} }
/**
* @param Collection $accounts
*
* @return void
*/
private function filterIbans(Collection $accounts): void
{
/** @var Account $account */
foreach ($accounts as $account) {
$iban = $account->iban;
if (str_contains($iban, ' ')) {
$iban = app('steam')->filterSpaces((string)$account->iban);
if ('' !== $iban) {
$account->iban = $iban;
$account->save();
$this->friendlyInfo(sprintf('Removed spaces from IBAN of account #%d', $account->id));
$this->count++;
}
}
}
}
/** /**
* @param Collection $accounts * @param Collection $accounts
* *
@@ -82,7 +107,7 @@ class FixIbans extends Command
&& // allowed combination && // allowed combination
!(AccountType::REVENUE === $set[$userId][$iban] && AccountType::EXPENSE === $type) // also allowed combination. !(AccountType::REVENUE === $set[$userId][$iban] && AccountType::EXPENSE === $type) // also allowed combination.
) { ) {
$this->line( $this->friendlyWarning(
sprintf( sprintf(
'IBAN "%s" is used more than once and will be removed from %s #%d ("%s")', 'IBAN "%s" is used more than once and will be removed from %s #%d ("%s")',
$iban, $iban,
@@ -102,26 +127,4 @@ class FixIbans extends Command
} }
} }
} }
/**
* @param Collection $accounts
*
* @return void
*/
private function filterIbans(Collection $accounts): void
{
/** @var Account $account */
foreach ($accounts as $account) {
$iban = $account->iban;
if (str_contains($iban, ' ')) {
$iban = app('steam')->filterSpaces((string)$account->iban);
if ('' !== $iban) {
$account->iban = $iban;
$account->save();
$this->line(sprintf('Removed spaces from IBAN of account #%d', $account->id));
$this->count++;
}
}
}
}
} }

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -33,6 +34,8 @@ use Illuminate\Console\Command;
*/ */
class FixLongDescriptions extends Command class FixLongDescriptions extends Command
{ {
use ShowsFriendlyMessages;
private const MAX_LENGTH = 1000; private const MAX_LENGTH = 1000;
protected $description = 'Fixes long descriptions in journals and groups.'; protected $description = 'Fixes long descriptions in journals and groups.';
protected $signature = 'firefly-iii:fix-long-descriptions'; protected $signature = 'firefly-iii:fix-long-descriptions';
@@ -51,7 +54,7 @@ class FixLongDescriptions extends Command
if (strlen($journal->description) > self::MAX_LENGTH) { if (strlen($journal->description) > self::MAX_LENGTH) {
$journal->description = substr($journal->description, 0, self::MAX_LENGTH); $journal->description = substr($journal->description, 0, self::MAX_LENGTH);
$journal->save(); $journal->save();
$this->line(sprintf('Truncated description of transaction journal #%d', $journal->id)); $this->friendlyWarning(sprintf('Truncated description of transaction journal #%d', $journal->id));
$count++; $count++;
} }
} }
@@ -62,12 +65,12 @@ class FixLongDescriptions extends Command
if (strlen((string)$group->title) > self::MAX_LENGTH) { if (strlen((string)$group->title) > self::MAX_LENGTH) {
$group->title = substr($group->title, 0, self::MAX_LENGTH); $group->title = substr($group->title, 0, self::MAX_LENGTH);
$group->save(); $group->save();
$this->line(sprintf('Truncated description of transaction group #%d', $group->id)); $this->friendlyWarning(sprintf('Truncated description of transaction group #%d', $group->id));
$count++; $count++;
} }
} }
if (0 === $count) { if (0 === $count) {
$this->info('Correct: all transaction group and journal title lengths are within bounds.'); $this->friendlyPositive('All transaction group and journal title lengths are within bounds.');
} }
return 0; return 0;

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\PiggyBankEvent; use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -34,6 +35,8 @@ use Illuminate\Console\Command;
*/ */
class FixPiggies extends Command class FixPiggies extends Command
{ {
use ShowsFriendlyMessages;
protected $description = 'Fixes common issues with piggy banks.'; protected $description = 'Fixes common issues with piggy banks.';
protected $signature = 'firefly-iii:fix-piggies'; protected $signature = 'firefly-iii:fix-piggies';
@@ -63,10 +66,10 @@ class FixPiggies extends Command
} }
} }
if (0 === $count) { if (0 === $count) {
$this->info('Correct: all piggy bank events are OK.'); $this->friendlyPositive('All piggy bank events are OK.');
} }
if (0 !== $count) { if (0 !== $count) {
$this->line(sprintf('Fixed %d piggy bank event(s).', $count)); $this->friendlyInfo(sprintf('Fixed %d piggy bank event(s).', $count));
} }
return 0; return 0;

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\Recurrence; use FireflyIII\Models\Recurrence;
use FireflyIII\Models\RecurrenceTransaction; use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
@@ -37,6 +38,8 @@ use Illuminate\Console\Command;
*/ */
class FixRecurringTransactions extends Command class FixRecurringTransactions extends Command
{ {
use ShowsFriendlyMessages;
protected $description = 'Fixes recurring transactions with the wrong transaction type.'; protected $description = 'Fixes recurring transactions with the wrong transaction type.';
protected $signature = 'firefly-iii:fix-recurring-transactions'; protected $signature = 'firefly-iii:fix-recurring-transactions';
private int $count = 0; private int $count = 0;
@@ -53,12 +56,25 @@ class FixRecurringTransactions extends Command
$this->stupidLaravel(); $this->stupidLaravel();
$this->correctTransactions(); $this->correctTransactions();
if (0 === $this->count) { if (0 === $this->count) {
$this->info('Correct: all recurring transactions are OK.'); $this->friendlyPositive('All recurring transactions are OK.');
} }
return 0; return 0;
} }
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
*/
private function stupidLaravel(): void
{
$this->recurringRepos = app(RecurringRepositoryInterface::class);
$this->userRepos = app(UserRepositoryInterface::class);
}
/** /**
* *
*/ */
@@ -71,6 +87,19 @@ class FixRecurringTransactions extends Command
} }
} }
/**
* @param User $user
*/
private function processUser(User $user): void
{
$this->recurringRepos->setUser($user);
$recurrences = $this->recurringRepos->get();
/** @var Recurrence $recurrence */
foreach ($recurrences as $recurrence) {
$this->processRecurrence($recurrence);
}
}
/** /**
* @param Recurrence $recurrence * @param Recurrence $recurrence
*/ */
@@ -93,7 +122,7 @@ class FixRecurringTransactions extends Command
$type = $recurrence->transactionType; $type = $recurrence->transactionType;
$link = config(sprintf('firefly.account_to_transaction.%s.%s', $source->accountType->type, $destination->accountType->type)); $link = config(sprintf('firefly.account_to_transaction.%s.%s', $source->accountType->type, $destination->accountType->type));
if (null !== $link && strtolower($type->type) !== strtolower($link)) { if (null !== $link && strtolower($type->type) !== strtolower($link)) {
$this->warn( $this->friendlyWarning(
sprintf('Recurring transaction #%d should be a "%s" but is a "%s" and will be corrected.', $recurrence->id, $link, $type->type) sprintf('Recurring transaction #%d should be a "%s" but is a "%s" and will be corrected.', $recurrence->id, $link, $type->type)
); );
$transactionType = TransactionType::whereType($link)->first(); $transactionType = TransactionType::whereType($link)->first();
@@ -104,30 +133,4 @@ class FixRecurringTransactions extends Command
} }
} }
} }
/**
* @param User $user
*/
private function processUser(User $user): void
{
$this->recurringRepos->setUser($user);
$recurrences = $this->recurringRepos->get();
/** @var Recurrence $recurrence */
foreach ($recurrences as $recurrence) {
$this->processRecurrence($recurrence);
}
}
/**
* Laravel will execute ALL __construct() methods for ALL commands whenever a SINGLE command is
* executed. This leads to noticeable slow-downs and class calls. To prevent this, this method should
* be called from the handle method instead of using the constructor to initialize the command.
*
*/
private function stupidLaravel(): void
{
$this->recurringRepos = app(RecurringRepositoryInterface::class);
$this->userRepos = app(UserRepositoryInterface::class);
}
} }

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