Merge remote-tracking branch 'upstream/develop' into fix-transfer-sign

This commit is contained in:
Florian Dupret 2020-07-27 11:06:00 +02:00
commit 294cda7f33
850 changed files with 78825 additions and 14247 deletions

View File

@ -10,14 +10,14 @@ APP_DEBUG=false
SITE_OWNER=mail@example.com
# The encryption key for your sessions. Keep this very secure.
# If you generate a new one existing data must be considered LOST.
# If you generate a new one all existing attachments must be considered LOST.
# Change it to a string of exactly 32 chars or use something like `php artisan key:generate` to generate it.
# If you use Docker or similar, you can set this variable from a file by using APP_KEY_FILE
APP_KEY=SomeRandomStringOf32CharsExactly
#
# Firefly III will launch using this language (for new users and unauthenticated visitors)
# For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/master/resources/lang
# For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/main/resources/lang
#
# If text is still in English, remember that not everything may have been translated.
DEFAULT_LANGUAGE=en_US
@ -57,7 +57,9 @@ APP_LOG_LEVEL=notice
# Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III
# For other database types, please see the FAQ: https://docs.firefly-iii.org/support/faq
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
# Use "mysql" for MySQL and MariaDB. Use "sqlite" for SQLite.
# Use "pgsql" for PostgreSQL
# Use "mysql" for MySQL and MariaDB.
# Use "sqlite" for SQLite.
DB_CONNECTION=mysql
DB_HOST=fireflyiiidb
DB_PORT=3306
@ -108,8 +110,8 @@ COOKIE_SECURE=false
# If you want Firefly III to mail you, update these settings
# For instructions, see: https://docs.firefly-iii.org/advanced-installation/email
# If you use Docker or similar, you can set these variables from a file by appending them with _FILE
MAIL_DRIVER=log
MAIL_HOST=smtp.mailtrap.io
MAIL_MAILER=log
MAIL_HOST=null
MAIL_PORT=2525
MAIL_FROM=changeme@example.com
MAIL_USERNAME=null
@ -167,6 +169,23 @@ FIXER_API_KEY=
# If you use Docker or similar, you can set this variable from a file by appending it with _FILE
LOGIN_PROVIDER=eloquent
#
# It's also possible to change the way users are authenticated. You could use Authelia for example.
# Authentication via the REMOTE_USER header is supported. Change the value below to "remote_user_guard".
#
# If you do this please read the documentation for instructions and warnings:
# https://docs.firefly-iii.org/advanced-installation/authentication
#
# This function is available in Firefly III v5.3.0 and higher.
AUTHENTICATION_GUARD=web
#
# Likewise, it's impossible to log out users who's authentication is handled by an external system.
# Enter a custom URL here that will force a logout (your authentication provider can tell you).
# Setting this variable only works when AUTHENTICATION_GUARD != web
#
CUSTOM_LOGOUT_URI=
# LDAP connection configuration
# OpenLDAP, FreeIPA or ActiveDirectory
# # If you use Docker or similar, you can set this variable from a file by appending it with _FILE
@ -287,9 +306,7 @@ PUSHER_ID=
DEMO_USERNAME=
DEMO_PASSWORD=
USE_ENCRYPTION=false
IS_SANDSTORM=false
IS_HEROKU=false
BUNQ_USE_SANDBOX=false
FIREFLY_III_LAYOUT=v1
#

View File

@ -8,7 +8,7 @@ I am always interested in expanding Firefly III's many features. Just open a tic
## Pull requests
When contributing to Firefly III, please first discuss the change you wish to make via issue, email, or any other method. I can only accept pull requests against the `develop` branch, never the `master` branch.
When contributing to Firefly III, please first discuss the change you wish to make via issue, email, or any other method. I can only accept pull requests against the `develop` branch, never the `main` branch.
## Translations :us: :fr: :de:

26
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,26 @@
version: 2
updates:
# composer updates
- package-ecosystem: "composer"
directory: "/" # Location of package manifests
target-branch: develop
labels: bug
schedule:
interval: "daily"
# yarn / JS updates
- package-ecosystem: "npm"
directory: "/"
target-branch: develop
labels: bug
schedule:
interval: "daily"
# yarn / JS updates for new frontend
- package-ecosystem: "npm"
directory: "/frontend"
target-branch: develop
labels: bug
schedule:
interval: "daily"

2
.github/funding.yml vendored
View File

@ -2,4 +2,4 @@
github: jc5
patreon: JC5
custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA
custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=L62W7DVD5ETPC&source=url

View File

@ -1,8 +1,9 @@
<!--
Before you create a new PR, please consider the following two considerations.
Before you create a new PR, please consider:
1) Pull request for the MASTER branch will be closed.
1) Pull requests for the MAIN branch will be closed.
2) We cannot accept pull requests to add new currencies.
3) DO NOT include translations in your PR. Only English US sentences.
Thanks.
-->

50
.github/security.md vendored
View File

@ -1,12 +1,54 @@
# Security Policy
Firefly III is an application to manage your personal finances. As such, the developer has adopted this security disclosure and response policy to ensure that critical issues are responsibly handled.
## Supported Versions
Only the latest Firefly III release is maintained. Applicable fixes, including security fixes, will not backported to older release branches. Please refer to [releases.md](https://github.com/firefly-iii/firefly-iii/blob/main/releases.md) for details.
Only the latest version of Firefly III is supported. If you're not running the latest version of Firefly III, please upgrade at your earliest convenience.
## Reporting a Vulnerability - Private Disclosure Process
Security is of the highest importance and all security vulnerabilities or suspected security vulnerabilities should be reported to Firefly III privately, to minimize attacks against current users of Firefly III before they are fixed. Vulnerabilities will be investigated and patched on the next patch (or minor) release as soon as possible. This information could be kept entirely internal to the project.
## Reporting a Vulnerability
If you know of a publicly disclosed security vulnerability for Firefly III, please **IMMEDIATELY** contact james@firefly-iii.org to inform the Firefly III developer. You can use my [GPG key](https://keybase.io/jc5) for extra security.
If you find something that compromises the security of Firefly III, you should [send me a message](mailto:james@firefly-iii.org) as soon as possible. These issues will be fixed immediately. You can also open an issue, but if you feel the issue is sensitive, please drop me a message instead.
**IMPORTANT: Do not file public issues on GitHub for security vulnerabilities**
You can use my [GPG key](https://keybase.io/jc5) for extra security. My [GitHub commits](https://github.com/firefly-iii/firefly-iii/commits/master) are almost always signed with this key.
To report a vulnerability or a security-related issue, please email the private address james@firefly-iii.org with the details of the vulnerability. The email will be received by the developer of Firefly III. Emails will be addressed within 3 business days, including a detailed plan to investigate the issue and any potential workarounds to perform in the meantime. Do not report non-security-impacting bugs through this channel. Use [GitHub issues](https://github.com/firefly-iii/firefly-iii/issues/new/choose) instead.
### Proposed Email Content
Provide a descriptive subject line and in the body of the email include the following information:
* Basic identity information, such as your name and your affiliation or company.
* Detailed steps to reproduce the vulnerability (POC scripts, screenshots, and compressed packet captures are all helpful to us).
* Description of the effects of the vulnerability on Firefly III and the related hardware and software configurations, so that the developer can reproduce it.
* How the vulnerability affects Firefly III usage and an estimation of the attack surface, if there is one.
* List other projects or dependencies that were used in conjunction with Firefly III to produce the vulnerability.
## When to report a vulnerability
* When you think Firefly III has a potential security vulnerability.
* When you suspect a potential vulnerability but you are unsure that it impacts Firefly III.
* When you know of or suspect a potential vulnerability on another project that is used by Firefly III. For example Firefly III has a dependency on Docker, MySQL, etc.
## Patch, Release, and Disclosure
The Firefly III developer will respond to vulnerability reports as follows:
1. The developer will investigate the vulnerability and determine its effects and criticality.
2. If the issue is not deemed to be a vulnerability, the developer will follow up with a detailed reason for rejection.
3. The developer will initiate a conversation with the reporter within 3 business days.
4. If a vulnerability is acknowledged and the timeline for a fix is determined, the developer will work on a plan to communicate with the appropriate community, including identifying mitigating steps that affected users can take to protect themselves until the fix is rolled out.
5. The developer will also create a [CVSS](https://www.first.org/cvss/specification-document) using the [CVSS Calculator](https://www.first.org/cvss/calculator/3.0). The developer makes the final call on the calculated CVSS; it is better to move quickly than making the CVSS perfect. Issues may also be reported to [Mitre](https://cve.mitre.org/) using this [scoring calculator](https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator). The CVE will initially be set to private.
6. The developer will work on fixing the vulnerability and perform internal testing before preparing to roll out the fix.
7. A public disclosure date is negotiated by the Firefly III developer and the bug submitter. We prefer to fully disclose the bug as soon as possible once a user mitigation or patch is available. It is reasonable to delay disclosure when the bug or the fix is not yet fully understood, the solution is not well-tested, or for distributor coordination. The timeframe for disclosure is from immediate (especially if its already publicly known) to a few weeks. For a critical vulnerability with a straightforward mitigation, we expect report date to public disclosure date to be on the order of 14 business days. The Firefly III developer holds the final say when setting a public disclosure date.
9. Once the fix is confirmed, the developer will patch the vulnerability in the next patch or minor release. Upon release of the patched version of Firefly III, we will follow the **Public Disclosure Process**.
### Public Disclosure Process
The developer publishes a public [advisory](https://github.com/firefly-iii/firefly-iii/security/advisories) to the Firefly III community via GitHub. In most cases, additional communication via Twitter, reddit and other channels will assist in educating Firefly III users and rolling out the patched release to affected users.
The develop will also publish any mitigating steps users can take until the fix can be applied to their Firefly III instances.
## Confidentiality, integrity and availability
We consider vulnerabilities leading to the compromise of data confidentiality, elevation of privilege, or integrity to be our highest priority concerns. Availability, in particular in areas relating to DoS and resource exhaustion, is also a serious security concern. The Firefly III developer takes all vulnerabilities, potential vulnerabilities, and suspected vulnerabilities seriously and will investigate them in an urgent and expeditious manner.
Note that we do not currently consider the default settings for Firefly III to be secure-by-default. It is necessary for operators to explicitly configure settings, role based access control, and other resource related features in Firefly III to provide a hardened Firefly III environment. We will not act on any security disclosure that relates to a lack of safe defaults. Over time, we will work towards improved safe-by-default configuration, taking into account backwards compatibility.
## Credits
This security policy is based on [Harbor](https://github.com/goharbor/harbor)'s security policy.

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
/node_modules
/frontend/node_modules
/frontend/fonts
/public/hot
/public/storage
/storage/*.key

View File

@ -3,7 +3,7 @@
"description": "A free and open source personal finances manager",
"repository": "https://github.com/firefly-iii/firefly-iii",
"website": "https://firefly-iii.org/",
"logo": "https://raw.githubusercontent.com/firefly-iii/firefly-iii/master/public/mstile-150x150.png",
"logo": "https://raw.githubusercontent.com/firefly-iii/firefly-iii/main/public/mstile-150x150.png",
"keywords": [
"finance",
"finances",
@ -41,7 +41,7 @@
{
"plan": "heroku-postgresql",
"options": {
"version": "9.5"
"version": "12"
}
}
],
@ -58,8 +58,8 @@
],
"env": {
"APP_KEY": {
"description": "This key is used to encrypt your data.",
"description": "This key is used to create app cookies en secure attachments.",
"value": "base64:If1gJN4pyycXTq+WS5TjneDympKuu+8SKvTl6RZnhJg="
}
}
}
}

View File

@ -50,8 +50,9 @@ use League\Fractal\Resource\Item;
class AccountController extends Controller
{
use AccountFilter, TransactionFilter;
/** @var AccountRepositoryInterface The account repository */
private $repository;
private AccountRepositoryInterface $repository;
public const RESOURCE_KEY = 'accounts';
/**
* AccountController constructor.
@ -150,7 +151,7 @@ class AccountController extends Controller
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($accounts, $transformer, 'accounts');
$resource = new FractalCollection($accounts, $transformer, self::RESOURCE_KEY);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
@ -208,7 +209,7 @@ class AccountController extends Controller
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($account, $transformer, 'accounts');
$resource = new Item($account, $transformer, self::RESOURCE_KEY);
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
@ -230,7 +231,7 @@ class AccountController extends Controller
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($account, $transformer, 'accounts');
$resource = new Item($account, $transformer, self::RESOURCE_KEY);
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
@ -304,7 +305,7 @@ class AccountController extends Controller
/** @var AccountTransformer $transformer */
$transformer = app(AccountTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($account, $transformer, 'accounts');
$resource = new Item($account, $transformer, self::RESOURCE_KEY);
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}

View File

@ -0,0 +1,107 @@
<?php
/**
* AccountController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
/**
* Class AccountController
*/
class AccountController extends Controller
{
use AccountFilter;
private array $balanceTypes;
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setUser($user);
return $next($request);
}
);
$this->balanceTypes = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE,];
}
/**
* @param AutocompleteRequest $request
*
* @return JsonResponse
*/
public function accounts(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$types = $data['types'];
$query = $data['query'];
$date = $data['date'] ?? today(config('app.timezone'));
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
$return = [];
$result = $repository->searchAccount((string) $query, $types, $data['limit']);
$defaultCurrency = app('amount')->getDefaultCurrency();
/** @var Account $account */
foreach ($result as $account) {
$nameWithBalance = $account->name;
$currency = $repository->getAccountCurrency($account) ?? $defaultCurrency;
if (in_array($account->accountType->type, $this->balanceTypes, true)) {
$balance = app('steam')->balance($account, $date);
$nameWithBalance = sprintf('%s (%s)', $account->name, app('amount')->formatAnything($currency, $balance, false));
}
$return[] = [
'id' => $account->id,
'name' => $account->name,
'name_with_balance' => $nameWithBalance,
'type' => $account->accountType->type,
'currency_id' => $currency->id,
'currency_name' => $currency->name,
'currency_code' => $currency->code,
'currency_decimal_places' => $currency->decimal_places,
];
}
return response()->json($return);
}
}

View File

@ -0,0 +1,82 @@
<?php
/**
* BillController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
/**
* Class BillController
*/
class BillController extends Controller
{
private BillRepositoryInterface $repository;
/**
* BillController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(BillRepositoryInterface::class);
$this->repository->setUser($user);
return $next($request);
}
);
}
/**
* TODO add limit
* @param AutocompleteRequest $request
*
* @return JsonResponse
*/
public function bills(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$result = $this->repository->searchBill($data['query'], $data['limit']);
$filtered = $result->map(
static function (Bill $item) {
return [
'id' => $item->id,
'name' => $item->name,
];
}
);
return response()->json($filtered->toArray());
}
}

View File

@ -0,0 +1,80 @@
<?php
/**
* BudgetController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
/**
* Class BudgetController
*/
class BudgetController extends Controller
{
private BudgetRepositoryInterface $repository;
/**
* BudgetController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(BudgetRepositoryInterface::class);
$this->repository->setUser($user);
return $next($request);
}
);
}
/**
* TODO add limit
* @param AutocompleteRequest $request
*
* @return JsonResponse
*/
public function budgets(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$result = $this->repository->searchBudget($data['query'], $data['limit']);
$filtered = $result->map(
static function (Budget $item) {
return [
'id' => $item->id,
'name' => $item->name,
];
}
);
return response()->json($filtered);
}
}

View File

@ -0,0 +1,78 @@
<?php
/**
* CategoryController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
/**
* Class CategoryController
*/
class CategoryController extends Controller
{
private CategoryRepositoryInterface $repository;
/**
* CategoryController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(CategoryRepositoryInterface::class);
$this->repository->setUser($user);
return $next($request);
}
);
}
/**
* @param AutocompleteRequest $request
*
* @return JsonResponse
*/
public function categories(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$result = $this->repository->searchCategory($data['query'], $data['limit']);
$filtered = $result->map(
static function (Category $item) {
return [
'id' => $item->id,
'name' => $item->name,
];
}
);
return response()->json($filtered);
}
}

View File

@ -0,0 +1,108 @@
<?php
/**
* CurrencyController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
/**
* Class CurrencyController
*/
class CurrencyController extends Controller
{
private CurrencyRepositoryInterface $repository;
/**
* CurrencyController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(CurrencyRepositoryInterface::class);
$this->repository->setUser($user);
return $next($request);
}
);
}
/**
* @param AutocompleteRequest $request
*
* @return JsonResponse
*/
public function currenciesWithCode(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$collection = $this->repository->searchCurrency($data['query'], $data['limit']);
$result = [];
/** @var TransactionCurrency $currency */
foreach ($collection as $currency) {
$result[] = [
'id' => $currency->id,
'name' => sprintf('%s (%s)', $currency->name, $currency->code),
'code' => $currency->code,
'symbol' => $currency->symbol,
'decimal_places' => $currency->decimal_places,
];
}
return response()->json($result);
}
/**
* @param AutocompleteRequest $request
*
* @return JsonResponse
*/
public function currencies(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$collection = $this->repository->searchCurrency($data['query'], $data['limit']);
$result = [];
/** @var TransactionCurrency $currency */
foreach ($collection as $currency) {
$result[] = [
'id' => $currency->id,
'name' => $currency->name,
'code' => $currency->code,
'symbol' => $currency->symbol,
'decimal_places' => $currency->decimal_places,
];
}
return response()->json($result);
}
}

View File

@ -0,0 +1,82 @@
<?php
/**
* ObjectGroupController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\ObjectGroup;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
/**
* Class ObjectGroupController
*/
class ObjectGroupController extends Controller
{
private ObjectGroupRepositoryInterface $repository;
/**
* CurrencyController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(ObjectGroupRepositoryInterface::class);
$this->repository->setUser($user);
return $next($request);
}
);
}
/**
* @param AutocompleteRequest $request
*
* @return JsonResponse
*/
public function objectGroups(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$return = [];
$result = $this->repository->search($data['query'], $data['limit']);
/** @var ObjectGroup $account */
foreach ($result as $objectGroup) {
$return[] = [
'id' => $objectGroup->id,
'name' => $objectGroup->title,
'title' => $objectGroup->title,
];
}
return response()->json($return);
}
}

View File

@ -0,0 +1,123 @@
<?php
/**
* PiggyBankController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
/**
* Class PiggyBankController
*/
class PiggyBankController extends Controller
{
private PiggyBankRepositoryInterface $piggyRepository;
private AccountRepositoryInterface $accountRepository;
/**
* PiggyBankController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->piggyRepository = app(PiggyBankRepositoryInterface::class);
$this->accountRepository = app(AccountRepositoryInterface::class);
$this->piggyRepository->setUser($user);
$this->accountRepository->setUser($user);
return $next($request);
}
);
}
/**
* @param AutocompleteRequest $request
*
* @return JsonResponse
*/
public function piggyBanks(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$piggies = $this->piggyRepository->searchPiggyBank($data['query'], $data['limit']);
$defaultCurrency = app('amount')->getDefaultCurrency();
$response = [];
/** @var PiggyBank $piggy */
foreach ($piggies as $piggy) {
$currency = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency;
$response[] = [
'id' => $piggy->id,
'name' => $piggy->name,
'currency_id' => $currency->id,
'currency_name' => $currency->name,
'currency_code' => $currency->code,
'currency_decimal_places' => $currency->decimal_places,
];
}
return response()->json($response);
}
/**
* @param AutocompleteRequest $request
*
* @return JsonResponse
*/
public function piggyBanksWithBalance(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$piggies = $this->piggyRepository->searchPiggyBank($data['query'], $data['limit']);
$defaultCurrency = app('amount')->getDefaultCurrency();
$response = [];
/** @var PiggyBank $piggy */
foreach ($piggies as $piggy) {
$currency = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency;
$currentAmount = $this->piggyRepository->getRepetition($piggy)->currentamount ?? '0';
$response[] = [
'id' => $piggy->id,
'name' => $piggy->name,
'name_with_balance' => sprintf(
'%s (%s / %s)', $piggy->name, app('amount')->formatAnything($currency, $currentAmount, false),
app('amount')->formatAnything($currency, $piggy->targetamount, false),
),
'currency_id' => $currency->id,
'currency_name' => $currency->name,
'currency_code' => $currency->code,
'currency_decimal_places' => $currency->decimal_places,
];
}
return response()->json($response);
}
}

View File

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

View File

@ -1,8 +1,7 @@
<?php
/**
* csv.php
* Copyright (c) 2019 james@firefly-iii.org
* RuleController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -22,5 +21,15 @@
declare(strict_types=1);
return [
];
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
/**
* Class RuleController
*/
class RuleController extends Controller
{
}

View File

@ -1,8 +1,7 @@
<?php
/**
* csv.php
* Copyright (c) 2019 james@firefly-iii.org
* RuleGroupController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -22,5 +21,15 @@
declare(strict_types=1);
return [
];
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
/**
* Class RuleGroupController
*/
class RuleGroupController extends Controller
{
}

View File

@ -0,0 +1,82 @@
<?php
/**
* TagController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
/**
* Class TagController
*/
class TagController extends Controller
{
private TagRepositoryInterface $repository;
/**
* TagController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(TagRepositoryInterface::class);
$this->repository->setUser($user);
return $next($request);
}
);
}
/**
* @param AutocompleteRequest $request
*
* @return JsonResponse
*/
public function tags(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$result = $this->repository->searchTags($data['query'], $data['limit']);
$array = [];
/** @var Tag $tag */
foreach ($result as $tag) {
$array[] = [
'id' => $tag->id,
'name' => $tag->tag,
'tag' => $tag->tag,
];
}
return response()->json($array);
}
}

View File

@ -0,0 +1,134 @@
<?php
/**
* TransactionController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
/**
* Class TransactionController
*/
class TransactionController extends Controller
{
private JournalRepositoryInterface $repository;
private TransactionGroupRepositoryInterface $groupRepository;
/**
* TransactionController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(JournalRepositoryInterface::class);
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
$this->repository->setUser($user);
$this->groupRepository->setUser($user);
return $next($request);
}
);
}
/**
* @param AutocompleteRequest $request
*
* @return JsonResponse
*/
public function transactions(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$result = $this->repository->searchJournalDescriptions($data['query'], $data['limit']);
// limit and unique
$filtered = $result->unique('description');
$array = [];
/** @var TransactionJournal $journal */
foreach ($filtered as $journal) {
$array[] = [
'id' => $journal->id,
'name' => $journal->description,
'description' => $journal->description,
];
}
return response()->json($array);
}
/**
* Searches in the titles of all transaction journals.
* The result is limited to the top 15 unique results.
*
* If the query is numeric, it will append the journal with that particular ID.
*
* @param AutocompleteRequest $request
*
* @return JsonResponse
*/
public function allJournalsWithID(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$array = [];
$result = new Collection;
if (is_numeric($data['query'])) {
// search for group, not journal.
$firstResult = $this->groupRepository->find((int) $data['query']);
if (null !== $firstResult) {
// group may contain multiple journals, each a result:
foreach ($firstResult->transactionJournals as $journal) {
$result->push($journal);
}
}
}
if (!is_numeric($data['query'])) {
$result = $this->repository->searchJournalDescriptions($data['query'], $data['limit']);
}
/** @var TransactionJournal $journal */
foreach ($result as $journal) {
$array[] = [
'id' => $journal->id,
'name' => printf('#%d: %s', $journal->id, $journal->description),
'description' => $journal->description,
];
}
return response()->json($array);
}
}

View File

@ -0,0 +1,79 @@
<?php
/**
* TransactionTypeController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface;
use Illuminate\Http\JsonResponse;
/**
* Class TransactionTypeController
*/
class TransactionTypeController extends Controller
{
private TransactionTypeRepositoryInterface $repository;
/**
* TransactionTypeController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(TransactionTypeRepositoryInterface::class);
return $next($request);
}
);
}
/**
* @param AutocompleteRequest $request
*
* @return JsonResponse
* @codeCoverageIgnore
*/
public function transactionTypes(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$types = $this->repository->searchTypes($data['query'], $data['limit']);
$array = [];
/** @var TransactionType $type */
foreach ($types as $type) {
// different key for consistency.
$array[] = [
'id' => $type->id,
'name' => $type->type,
'type' => $type->type,
];
}
return response()->json($array);
}
}

View File

@ -42,10 +42,8 @@ use Illuminate\Http\JsonResponse;
class AccountController extends Controller
{
use ApiSupport;
/** @var CurrencyRepositoryInterface */
private $currencyRepository;
/** @var AccountRepositoryInterface */
private $repository;
private CurrencyRepositoryInterface $currencyRepository;
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.
@ -196,6 +194,8 @@ class AccountController extends Controller
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'start_date' => $start->format('Y-m-d'),
'end_date' => $end->format('Y-m-d'),
'type' => 'line', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [],

View File

@ -0,0 +1,298 @@
<?php
/**
* BudgetController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\DateRequest;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
/**
* Class BudgetController
*/
class BudgetController extends Controller
{
private BudgetLimitRepositoryInterface $blRepository;
private OperationsRepositoryInterface $opsRepository;
private BudgetRepositoryInterface $repository;
/**
* BudgetController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
//$this->generator = app(GeneratorInterface::class);
$this->repository = app(BudgetRepositoryInterface::class);
$this->opsRepository = app(OperationsRepositoryInterface::class);
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
//$this->nbRepository = app(NoBudgetRepositoryInterface::class);
return $next($request);
}
);
}
/**
* [
* 'label' => 'label for entire set'
* 'currency_id' => 0,
* 'currency_code' => 'EUR',
* 'currency_symbol' => '$',
* 'currency_decimal_places' => 2,
* 'type' => 'bar', // line, area or bar
* 'yAxisID' => 0, // 0, 1, 2
* 'entries' => ['a' => 1, 'b' => 4],
* ],
*
* @param DateRequest $request
*
* @return JsonResponse
*/
public function overview(DateRequest $request): JsonResponse
{
$dates = $request->getAll();
$budgets = $this->repository->getActiveBudgets();
$budgetNames = [];
$currencyNames = [];
$sets = [];
/** @var Budget $budget */
foreach ($budgets as $budget) {
$expenses = $this->getExpenses($budget, $dates['start'], $dates['end']);
$expenses = $this->filterNulls($expenses);
foreach ($expenses as $set) {
$budgetNames[] = $set['budget_name'];
$currencyNames[] = $set['currency_name'];
$sets[] = $set;
}
}
$budgetNames = array_unique($budgetNames);
$currencyNames = array_unique($currencyNames);
$basic = $this->createSets($budgetNames, $currencyNames);
$filled = $this->fillSets($basic, $sets);
$keys = array_values($filled);
return response()->json($keys);
}
/**
* @param Collection $limits
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
protected function getExpenses(Budget $budget, Carbon $start, Carbon $end): array
{
$limits = $this->blRepository->getBudgetLimits($budget, $start, $end);
if (0 === $limits->count()) {
return $this->getExpenseInRange($budget, $start, $end);
}
$arr = [];
/** @var BudgetLimit $limit */
foreach ($limits as $limit) {
$arr[] = $this->getExpensesForLimit($limit);
}
return $arr;
}
/**
* @param array $budgetNames
* @param array $currencyNames
*
* @return array
*/
private function createSets(array $budgetNames, array $currencyNames): array
{
$return = [];
foreach ($currencyNames as $currencyName) {
$entries = [];
foreach ($budgetNames as $budgetName) {
$label = sprintf('%s (%s)', $budgetName, $currencyName);
$entries[$label] = '0';
}
// left
$return['left'] = [
'label' => sprintf('%s (%s)', trans('firefly.left'), $currencyName),
'data_type' => 'left',
'currency_name' => $currencyName,
'type' => 'bar',
'yAxisID' => 0, // 0, 1, 2
'entries' => $entries,
];
// spent_capped
$return['spent_capped'] = [
'label' => sprintf('%s (%s)', trans('firefly.spent'), $currencyName),
'data_type' => 'spent_capped',
'currency_name' => $currencyName,
'type' => 'bar',
'yAxisID' => 0, // 0, 1, 2
'entries' => $entries,
];
// overspent
$return['overspent'] = [
'label' => sprintf('%s (%s)', trans('firefly.overspent'), $currencyName),
'data_type' => 'overspent',
'currency_name' => $currencyName,
'type' => 'bar',
'yAxisID' => 0, // 0, 1, 2
'entries' => $entries,
];
}
return $return;
}
/**
* @param array $basic
* @param array $sets
*
* @return array
*/
private function fillSets(array $basic, array $sets): array
{
foreach ($sets as $set) {
$label = $set['label'];
//$basic['spent']['entries'][$label] = $set['entries']['spent'];
$basic['spent_capped']['entries'][$label] = $set['entries']['spent_capped'];
$basic['left']['entries'][$label] = $set['entries']['left'];
$basic['overspent']['entries'][$label] = $set['entries']['overspent'];
}
return $basic;
}
/**
* @param array $expenses
*
* @return array
*/
private function filterNulls(array $expenses): array
{
$return = [];
/** @var array|null $arr */
foreach ($expenses as $arr) {
if (null !== $arr) {
$return[] = $arr;
}
}
return $return;
}
/**
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
private function getExpenseInRange(Budget $budget, Carbon $start, Carbon $end): array
{
$spent = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$budget]), null);
$return = [];
/** @var array $set */
foreach ($spent as $set) {
$current = [
'label' => sprintf('%s (%s)', $budget->name, $set['currency_name']),
'budget_name' => $budget->name,
'start_date' => $start->format('Y-m-d'),
'end_date' => $end->format('Y-m-d'),
'currency_id' => (int) $set['currency_id'],
'currency_code' => $set['currency_code'],
'currency_name' => $set['currency_name'],
'currency_symbol' => $set['currency_symbol'],
'currency_decimal_places' => (int) $set['currency_decimal_places'],
'type' => 'bar', // line, area or bar,
'entries' => [],
];
$sumSpent = bcmul($set['sum'], '-1'); // spent
$current['entries']['spent'] = $sumSpent;
$current['entries']['amount'] = '0';
$current['entries']['spent_capped'] = $sumSpent;
$current['entries']['left'] = '0';
$current['entries']['overspent'] = '0';
$return[] = $current;
}
return $return;
}
/**
* @param BudgetLimit $limit
*
* @return array|null
*/
private function getExpensesForLimit(BudgetLimit $limit): ?array
{
$budget = $limit->budget;
$spent = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection([$budget]), $limit->transactionCurrency);
$currency = $limit->transactionCurrency;
// when limited to a currency, the count is always one. Or it's empty.
$set = array_shift($spent);
if (null === $set) {
return null;
}
$return = [
'label' => sprintf('%s (%s)', $budget->name, $set['currency_name']),
'budget_name' => $budget->name,
'start_date' => $limit->start_date->format('Y-m-d'),
'end_date' => $limit->end_date->format('Y-m-d'),
'currency_id' => (int) $currency->id,
'currency_code' => $currency->code,
'currency_name' => $currency->name,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => (int) $currency->decimal_places,
'type' => 'bar', // line, area or bar,
'entries' => [],
];
$sumSpent = bcmul($set['sum'], '-1'); // spent
$return['entries']['spent'] = $sumSpent;
$return['entries']['amount'] = $limit->amount;
$return['entries']['spent_capped'] = 1 === bccomp($sumSpent, $limit->amount) ? $limit->amount : $sumSpent;
$return['entries']['left'] = 1 === bccomp($limit->amount, $sumSpent) ? bcadd($set['sum'], $limit->amount) : '0'; // left
$return['entries']['overspent'] = 1 === bccomp($limit->amount, $sumSpent) ? '0' : bcmul(bcadd($set['sum'], $limit->amount), '-1'); // overspent
return $return;
}
}

View File

@ -74,8 +74,6 @@ class CategoryController extends Controller
* @param DateRequest $request
*
* @return JsonResponse
*
* TODO after 4.8,0, simplify
*/
public function overview(DateRequest $request): JsonResponse
{
@ -89,32 +87,15 @@ class CategoryController extends Controller
$tempData = [];
$spentWith = $this->opsRepository->listExpenses($start, $end);
$earnedWith = $this->opsRepository->listIncome($start, $end);
$spentWithout = $this->noCatRepository->listExpenses($start, $end);
$earnedWithout = $this->noCatRepository->listIncome($start, $end);
$categories = [];
foreach ([$spentWith, $earnedWith, $spentWithout, $earnedWithout] as $set) {
foreach ([$spentWith, $spentWithout,] as $set) {
foreach ($set as $currency) {
foreach ($currency['categories'] as $category) {
$categories[] = $category['name'];
$inKey = sprintf('%d-i', $currency['currency_id']);
$outKey = sprintf('%d-e', $currency['currency_id']);
// make data arrays if not yet present.
$tempData[$inKey] = $tempData[$inKey] ?? [
'currency_id' => $currency['currency_id'],
'label' => (string) trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
'currency_code' => $currency['currency_code'],
'currency_symbol' => $currency['currency_symbol'],
'currency_decimal_places' => $currency['currency_decimal_places'],
'type' => 'bar', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [
// per category:
// "category" => 5,
],
];
$tempData[$outKey] = $tempData[$outKey] ?? [
'currency_id' => $currency['currency_id'],
'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
@ -123,16 +104,12 @@ class CategoryController extends Controller
'currency_decimal_places' => $currency['currency_decimal_places'],
'type' => 'bar', // line, area or bar
'yAxisID' => 0, // 0, 1, 2
'entries' => [
// per category:
// "category" => 5,
],
'entries' => [],
];
foreach ($category['transaction_journals'] as $journal) {
// is it expense or income?
$letter = -1 === bccomp($journal['amount'], '0') ? 'e' : 'i';
$currentKey = sprintf('%d-%s', $currency['currency_id'], $letter);
$currentKey = sprintf('%d-%s', $currency['currency_id'], 'e');
$name = $category['name'];
$tempData[$currentKey]['entries'][$name] = $tempData[$currentKey]['entries'][$name] ?? '0';
$tempData[$currentKey]['entries'][$name] = bcadd($tempData[$currentKey]['entries'][$name], $journal['amount']);
@ -141,49 +118,6 @@ class CategoryController extends Controller
}
}
// foreach ([] as $set) {
// foreach ($set as $currency) {
// $inKey = sprintf('%d-i', $currency['currency_id']);
// $outKey = sprintf('%d-e', $currency['currency_id']);
// $categories[] = (string)trans('firefly.no_category');
// // make data arrays if not yet present.
// $tempData[$inKey] = $tempData[$inKey] ?? [
// 'currency_id' => $currency['currency_id'],
// 'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]),
// 'currency_code' => $currency['currency_code'],
// 'currency_symbol' => $currency['currency_symbol'],
// 'currency_decimal_places' => $currency['currency_decimal_places'],
// 'type' => 'bar', // line, area or bar
// 'yAxisID' => 0, // 0, 1, 2
// 'entries' => [
// // per category:
// // "category" => 5,
// ],
// ];
// $tempData[$outKey] = $tempData[$outKey] ?? [
// 'currency_id' => $currency['currency_id'],
// 'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]),
// 'currency_code' => $currency['currency_code'],
// 'currency_symbol' => $currency['currency_symbol'],
// 'currency_decimal_places' => $currency['currency_decimal_places'],
// 'type' => 'bar', // line, area or bar
// 'yAxisID' => 0, // 0, 1, 2
// 'entries' => [
// // per category:
// // "category" => 5,
// ],
// ];
// foreach ($currency['transaction_journals'] as $journal) {
// // is it expense or income?
// $letter = -1 === bccomp($journal['amount'], '0') ? 'e' : 'i';
// $currentKey = sprintf('%d-%s', $currency['currency_id'], $letter);
// $name = (string)trans('firefly.no_category');
// $tempData[$currentKey]['entries'][$name] = $tempData[$currentKey]['entries'][$name] ?? '0';
// $tempData[$currentKey]['entries'][$name] = bcadd($tempData[$currentKey]['entries'][$name], $journal['amount']);
// }
// }
// }
// re-sort every spent array and add 0 for missing entries.
foreach ($tempData as $index => $set) {
$oldSet = $set['entries'];

View File

@ -577,7 +577,8 @@ class CurrencyController extends Controller
{
$manager = $this->getManager();
$currency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $currency);
/** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class);
$transformer->setParameters($this->parameters);

View File

@ -0,0 +1,278 @@
<?php
/**
* DestroyController.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Data;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\DataDestroyRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Services\Internal\Destroy\AccountDestroyService;
use FireflyIII\Services\Internal\Destroy\JournalDestroyService;
use Illuminate\Http\JsonResponse;
/**
* Class DestroyController
*/
class DestroyController extends Controller
{
/**
* @return JsonResponse
*/
public function destroy(DataDestroyRequest $request): JsonResponse
{
$objects = $request->getObjects();
switch ($objects) {
default:
throw new FireflyException(sprintf('This endpoint can\'t handle object "%s"', $objects));
case 'budgets':
$this->destroyBudgets();
break;
case 'bills':
$this->destroyBills();
break;
case 'piggy_banks':
$this->destroyPiggyBanks();
break;
case 'rules':
$this->destroyRules();
break;
case 'recurring':
$this->destroyRecurringTransactions();
break;
case 'categories':
$this->destroyCategories();
break;
case 'tags':
$this->destroyTags();
break;
case 'object_groups':
$this->destroyObjectGroups();
break;
case 'accounts':
$this->destroyAccounts(
[
AccountType::ASSET, AccountType::DEFAULT,
AccountType::BENEFICIARY, AccountType::EXPENSE,
AccountType::REVENUE, AccountType::INITIAL_BALANCE,
AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD,
]
);
break;
case 'asset_accounts':
$this->destroyAccounts(
[
AccountType::ASSET, AccountType::DEFAULT,
]
);
break;
case 'expense_accounts':
$this->destroyAccounts(
[
AccountType::BENEFICIARY, AccountType::EXPENSE,
]
);
break;
case 'revenue_accounts':
$this->destroyAccounts(
[
AccountType::REVENUE,
]
);
break;
case 'liabilities':
$this->destroyAccounts(
[
AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD,
]
);
break;
case 'transactions':
$this->destroyTransactions(
[
TransactionType::WITHDRAWAL,
TransactionType::DEPOSIT,
TransactionType::TRANSFER,
TransactionType::RECONCILIATION,
TransactionType::OPENING_BALANCE,
]
);
break;
case 'withdrawals':
$this->destroyTransactions(
[
TransactionType::WITHDRAWAL,
]
);
break;
case 'deposits':
$this->destroyTransactions(
[
TransactionType::DEPOSIT,
]
);
break;
case 'transfers':
$this->destroyTransactions(
[
TransactionType::TRANSFER,
]
);
break;
}
return response()->json([], 204);
}
/**
* @param array $types
*/
private function destroyAccounts(array $types): void
{
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
$collection = $repository->getAccountsByType($types);
$service = app(AccountDestroyService::class);
/** @var Account $account */
foreach ($collection as $account) {
$service->destroy($account, null);
}
}
/**
*
*/
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
*/
private function destroyTransactions(array $types): void
{
/** @var JournalRepositoryInterface $repository */
$repository = app(JournalRepositoryInterface::class);
$journals = $repository->findByType($types);
$service = app(JournalDestroyService::class);
/** @var TransactionJournal $journal */
foreach($journals as $journal) {
$service->destroy($journal);
}
}
}

View File

@ -0,0 +1,196 @@
<?php
/**
* GroupController.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Requests\ObjectGroupUpdateRequest;
use FireflyIII\Models\Account;
use FireflyIII\Models\ObjectGroup;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\Transformers\ObjectGroupTransformer;
use FireflyIII\Transformers\PiggyBankTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection;
use League\Fractal\Resource\Item;
/**
* Class GroupController.
*
*/
class ObjectGroupController extends Controller
{
private ObjectGroupRepositoryInterface $repository;
/**
* ObjectGroupController constructor.
*
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
/** @var User $user */
$user = auth()->user();
$this->repository = app(ObjectGroupRepositoryInterface::class);
$this->repository->setUser($user);
return $next($request);
}
);
}
/**
* Remove the specified resource from storage.
*
* @param ObjectGroup $objectGroup
*
* @codeCoverageIgnore
* @return JsonResponse
*/
public function delete(ObjectGroup $objectGroup): JsonResponse
{
$this->repository->destroy($objectGroup);
return response()->json([], 204);
}
/**
* Display a listing of the resource.
*
* @param Request $request
*
* @codeCoverageIgnore
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of accounts. Count it and split it.
$collection = $this->repository->get();
$count = $collection->count();
$objectGroups = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($objectGroups, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.object-groups.index') . $this->buildParams());
/** @var ObjectGroupTransformer $transformer */
$transformer = app(ObjectGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($objectGroups, $transformer, 'object_groups');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* List all piggies under the object group.
*
* @param ObjectGroup $objectGroup
*
* @return JsonResponse
* @codeCoverageIgnore
*
*/
public function piggyBanks(ObjectGroup $objectGroup): JsonResponse
{
// create some objects:
$manager = $this->getManager();
// types to get, page size:
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
// get list of piggy banks. Count it and split it.
$collection = $this->repository->getPiggyBanks($objectGroup);
$count = $collection->count();
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.object-groups.piggy_banks', [$objectGroup->id]) . $this->buildParams());
/** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy_banks');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* Show single instance.
*
* @param ObjectGroup $objectGroup
*
* @return JsonResponse
*/
public function show(ObjectGroup $objectGroup): JsonResponse
{
$manager = $this->getManager();
/** @var ObjectGroupTransformer $transformer */
$transformer = app(ObjectGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($objectGroup, $transformer, 'object_groups');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* Update object.
*
* @param ObjectGroupUpdateRequest $request
* @param Account $account
*
* @return JsonResponse
*/
public function update(ObjectGroupUpdateRequest $request, ObjectGroup $objectGroup): JsonResponse
{
$data = $request->getUpdateData();
$this->repository->update($objectGroup, $data);
$this->repository->sort();
$manager = $this->getManager();
/** @var ObjectGroupTransformer $transformer */
$transformer = app(ObjectGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Item($objectGroup, $transformer, 'object_groups');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
}

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers;
use FireflyIII\Api\V1\Requests\PiggyBankRequest;
use FireflyIII\Api\V1\Requests\PiggyBankStoreRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
@ -204,12 +205,12 @@ class PiggyBankController extends Controller
/**
* Store new object.
*
* @param PiggyBankRequest $request
* @param PiggyBankStoreRequest $request
*
* @throws FireflyException
* @return JsonResponse
*/
public function store(PiggyBankRequest $request): JsonResponse
public function store(PiggyBankStoreRequest $request): JsonResponse
{
$piggyBank = $this->repository->store($request->getAll());
$manager = $this->getManager();
@ -240,7 +241,6 @@ class PiggyBankController extends Controller
$this->repository->setCurrentAmount($piggyBank, $data['current_amount']);
}
$manager = $this->getManager();
/** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class);

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* AccountController.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Search;
use FireflyIII\Api\V1\Controllers\Controller;
@ -41,8 +43,7 @@ class AccountController extends Controller
{
use AccountFilter;
/** @var array */
private $validFields;
private array $validFields;
public function __construct()
{

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* TransactionController.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,45 +20,51 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Search;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Support\Search\SearchInterface;
use FireflyIII\Transformers\TransactionGroupTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection;
/**
* Class TransactionController
*/
class TransactionController extends Controller
{
/** @var string */
public const SEARCH_ALL = 'all';
/** @var string */
public const SEARCH_DESCRIPTION = 'description';
/** @var string */
public const SEARCH_NOTES = 'notes';
/** @var string */
public const SEARCH_ACCOUNTS = 'accounts';
/** @var array */
private $validFields;
public function __construct()
{
parent::__construct();
$this->validFields = [
self::SEARCH_ALL,
self::SEARCH_DESCRIPTION,
self::SEARCH_NOTES,
self::SEARCH_ACCOUNTS,
];
}
/**
* @param Request $request
* @param Request $request
* @param SearchInterface $searcher
*
* @return void
* @return JsonResponse
*/
public function search(Request $request): void
public function search(Request $request, SearchInterface $searcher): JsonResponse
{
die('the route is present but nobody\'s home.');
$manager = $this->getManager();
$fullQuery = (string) $request->get('query');
$page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page');
$searcher->parseQuery($fullQuery);
$searcher->setPage($page);
$searcher->setLimit((int) config('firefly.search_result_limit'));
$groups = $searcher->searchTransactions();
$parameters = ['search' => $fullQuery];
$url = route('api.v1.search.transactions') . '?' . http_build_query($parameters);
$groups->setPath($url);
$transactions = $groups->getCollection();
/** @var TransactionGroupTransformer $transformer */
$transformer = app(TransactionGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new Collection($transactions, $transformer, 'transactions');
$resource->setPaginator(new IlluminatePaginatorAdapter($groups));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
}

View File

@ -1,113 +0,0 @@
<?php
declare(strict_types=1);
/**
* TransferController.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Controllers\Search;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Search\TransferRequest;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Support\Search\TransferSearch;
use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection as FractalCollection;
/**
* Class TransferController
*/
class TransferController extends Controller
{
/**
* @param TransferRequest $request
*
* @return JsonResponse|Response
*/
public function search(TransferRequest $request)
{
// configure transfer search to search for a > b
$search = app(TransferSearch::class);
$search->setSource($request->get('source'));
$search->setDestination($request->get('destination'));
$search->setAmount($request->get('amount'));
$search->setDescription($request->get('description'));
$search->setDate($request->get('date'));
$left = $search->search();
// configure transfer search to search for b > a
$search->setSource($request->get('destination'));
$search->setDestination($request->get('source'));
$search->setAmount($request->get('amount'));
$search->setDescription($request->get('description'));
$search->setDate($request->get('date'));
$right = $search->search();
// add parameters to URL:
$this->parameters->set('source', $request->get('source'));
$this->parameters->set('destination', $request->get('destination'));
$this->parameters->set('amount', $request->get('amount'));
$this->parameters->set('description', $request->get('description'));
$this->parameters->set('date', $request->get('date'));
// get all journal ID's.
$total = $left->merge($right)->unique('id')->pluck('id')->toArray();
if (0 === count($total)) {
// forces search to be empty.
$total = [-1];
}
// collector to return results.
$pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data;
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
// use new group collector:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
->setUser($admin)
// all info needed for the API:
->withAPIInformation()
// set page size:
->setLimit($pageSize)
// set page to retrieve
->setPage(1)
->setJournalIds($total);
$paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.search.transfers') . $this->buildParams());
$transactions = $paginator->getCollection();
/** @var TransactionGroupTransformer $transformer */
$transformer = app(TransactionGroupTransformer::class);
$transformer->setParameters($this->parameters);
$resource = new FractalCollection($transactions, $transformer, 'transactions');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
}

View File

@ -74,25 +74,6 @@ class TagController extends Controller
);
}
/**
* @param DateRequest $request
*
* @return JsonResponse
*/
public function cloud(DateRequest $request): JsonResponse
{
// parameters for boxes:
$dates = $request->getAll();
$start = $dates['start'];
$end = $dates['end'];
// get all tags:
$tags = $this->repository->get();
$cloud = $this->getTagCloud($tags, $start, $end);
return response()->json($cloud);
}
/**
* Delete the resource.
*
@ -284,56 +265,4 @@ class TagController extends Controller
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json');
}
/**
* @param array $cloud
* @param float $min
* @param float $max
*
* @return array
*/
private function analyseTagCloud(array $cloud, float $min, float $max): array
{
foreach (array_keys($cloud['tags']) as $index) {
$cloud['tags'][$index]['relative'] = round($cloud['tags'][$index]['size'] / $max, 4);
}
$cloud['min'] = $min;
$cloud['max'] = $max;
return $cloud;
}
/**
* @param Collection $tags
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
private function getTagCloud(Collection $tags, Carbon $start, Carbon $end): array
{
$min = null;
$max = 0;
$cloud = [
'tags' => [],
];
/** @var Tag $tag */
foreach ($tags as $tag) {
$earned = (float) $this->repository->earnedInPeriod($tag, $start, $end);
$spent = (float) $this->repository->spentInPeriod($tag, $start, $end);
$size = ($spent * -1) + $earned;
$min = $min ?? $size;
if ($size > 0) {
$max = $size > $max ? $size : $max;
$cloud['tags'][] = [
'tag' => $tag->tag,
'id' => $tag->id,
'size' => $size,
];
}
}
$cloud = $this->analyseTagCloud($cloud, $min, $max);
return $cloud;
}
}

View File

@ -26,14 +26,18 @@ namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Location;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\AppendsLocationData;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class AccountStoreRequest
*
* @codeCoverageIgnore
*/
class AccountStoreRequest extends Request
class AccountStoreRequest extends FormRequest
{
use ConvertsDataTypes, AppendsLocationData;
/**
* Authorize logged in users.
@ -66,6 +70,7 @@ class AccountStoreRequest extends Request
'account_type' => $this->string('type'),
'account_type_id' => null,
'currency_id' => $this->integer('currency_id'),
'order' => $this->integer('order'),
'currency_code' => $this->string('currency_code'),
'virtual_balance' => $this->string('virtual_balance'),
'iban' => $this->string('iban'),
@ -75,7 +80,7 @@ class AccountStoreRequest extends Request
'opening_balance' => $this->string('opening_balance'),
'opening_balance_date' => $this->date('opening_balance_date'),
'cc_type' => $this->string('credit_card_type'),
'cc_Monthly_payment_date' => $this->string('monthly_payment_date'),
'cc_monthly_payment_date' => $this->string('monthly_payment_date'),
'notes' => $this->nlString('notes'),
'interest' => $this->string('interest'),
'interest_period' => $this->string('interest_period'),
@ -112,6 +117,7 @@ class AccountStoreRequest extends Request
'opening_balance' => 'numeric|required_with:opening_balance_date|nullable',
'opening_balance_date' => 'date|required_with:opening_balance|nullable',
'virtual_balance' => 'numeric|nullable',
'order' => 'numeric|nullable',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'active' => [new IsBoolean],

View File

@ -26,15 +26,18 @@ namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Location;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\AppendsLocationData;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class AccountUpdateRequest
*
* @codeCoverageIgnore
*/
class AccountUpdateRequest extends Request
class AccountUpdateRequest extends FormRequest
{
use ConvertsDataTypes, AppendsLocationData;
/**
* Authorize logged in users.
*
@ -66,6 +69,7 @@ class AccountUpdateRequest extends Request
'account_type' => $this->nullableString('type'),
'account_type_id' => null,
'currency_id' => $this->nullableInteger('currency_id'),
'order' => $this->integer('order'),
'currency_code' => $this->nullableString('currency_code'),
'virtual_balance' => $this->nullableString('virtual_balance'),
'iban' => $this->nullableString('iban'),
@ -75,7 +79,7 @@ class AccountUpdateRequest extends Request
'opening_balance' => $this->nullableString('opening_balance'),
'opening_balance_date' => $this->date('opening_balance_date'),
'cc_type' => $this->nullableString('credit_card_type'),
'cc_Monthly_payment_date' => $this->nullableString('monthly_payment_date'),
'cc_monthly_payment_date' => $this->nullableString('monthly_payment_date'),
'notes' => $this->nullableNlString('notes'),
'interest' => $this->nullableString('interest'),
'interest_period' => $this->nullableString('interest_period'),
@ -114,6 +118,7 @@ class AccountUpdateRequest extends Request
'opening_balance' => 'numeric|required_with:opening_balance_date|nullable',
'opening_balance_date' => 'date|required_with:opening_balance|nullable',
'virtual_balance' => 'numeric|nullable',
'order' => 'numeric|nullable',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'active' => [new IsBoolean],

View File

@ -24,14 +24,17 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsValidAttachmentModel;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class AttachmentStoreRequest
*
* @codeCoverageIgnore
*/
class AttachmentStoreRequest extends Request
class AttachmentStoreRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -23,13 +23,17 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* ClassAttachmentUpdateRequest
*
* @codeCoverageIgnore
*/
class AttachmentUpdateRequest extends Request
class AttachmentUpdateRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -0,0 +1,78 @@
<?php
/**
* AutocompleteRequest.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Autocomplete;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class AutocompleteRequest
*/
class AutocompleteRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/**
* @return array
*/
public function getData(): array
{
$types = $this->string('types');
$array = [];
if ('' !== $types) {
$array = explode(',', $types);
}
$limit = $this->integer('limit');
$limit = 0 === $limit ? 10 : $limit;
return [
'types' => $array,
'query' => $this->string('query'),
'date' => $this->date('date'),
'limit' => $limit,
];
}
/**
* @return array
*/
public function rules(): array
{
return [
'limit' => 'min:0|max:1337'
];
}
}

View File

@ -23,13 +23,17 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class AvailableBudgetRequest
*
* @codeCoverageIgnore
*/
class AvailableBudgetRequest extends Request
class AvailableBudgetRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*
@ -67,7 +71,7 @@ class AvailableBudgetRequest extends Request
return [
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'amount' => 'required|numeric|more:0',
'amount' => 'required|numeric|gt:0',
'start' => 'required|date|before:end',
'end' => 'required|date|after:start',
];

View File

@ -25,6 +25,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
/**
@ -34,9 +36,9 @@ use Illuminate\Validation\Validator;
*
* @codeCoverageIgnore
*/
class BillRequest extends Request
class BillRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*
@ -70,6 +72,7 @@ class BillRequest extends Request
'repeat_freq' => $this->string('repeat_freq'),
'skip' => $this->integer('skip'),
'active' => $active,
'order' => $this->integer('order'),
'notes' => $this->nlString('notes'),
];
}
@ -83,13 +86,13 @@ class BillRequest extends Request
public function rules(): array
{
$rules = [
'name' => 'required|between:1,255|uniqueObjectForUser:bills,name',
'amount_min' => 'required|numeric|more:0',
'amount_max' => 'required|numeric|more:0',
'name' => 'between:1,255|uniqueObjectForUser:bills,name',
'amount_min' => 'numeric|gt:0',
'amount_max' => 'numeric|gt:0',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'date' => 'required|date',
'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly',
'date' => 'date',
'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly',
'skip' => 'between:0,31',
'active' => [new IsBoolean],
'notes' => 'between:1,65536',

View File

@ -23,14 +23,18 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class BudgetLimitRequest
*
* @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/
class BudgetLimitRequest extends Request
class BudgetLimitRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*
@ -70,7 +74,7 @@ class BudgetLimitRequest extends Request
'budget_id' => 'required|exists:budgets,id|belongsToUser:budgets,id',
'start' => 'required|before:end|date',
'end' => 'required|after:start|date',
'amount' => 'required|more:0',
'amount' => 'required|gt:0',
'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
];

View File

@ -24,6 +24,9 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
/**
@ -31,8 +34,9 @@ use Illuminate\Validation\Validator;
*
* @codeCoverageIgnore
*/
class BudgetStoreRequest extends Request
class BudgetStoreRequest extends FormRequest
{
use ConvertsDataTypes, ValidatesAutoBudgetRequest;
/**
* Authorize logged in users.
*

View File

@ -24,6 +24,9 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
/**
@ -31,8 +34,9 @@ use Illuminate\Validation\Validator;
*
* @codeCoverageIgnore
*/
class BudgetUpdateRequest extends Request
class BudgetUpdateRequest extends FormRequest
{
use ConvertsDataTypes, ValidatesAutoBudgetRequest;
/**
* Authorize logged in users.
*

View File

@ -24,6 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Category;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class CategoryRequest
@ -31,8 +33,9 @@ use FireflyIII\Models\Category;
* @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/
class CategoryRequest extends Request
class CategoryRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -25,15 +25,17 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class ConfigurationRequest
*
* @codeCoverageIgnore
*/
class ConfigurationRequest extends Request
class ConfigurationRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -24,6 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
@ -32,8 +34,9 @@ use FireflyIII\Rules\IsBoolean;
* @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/
class CurrencyRequest extends Request
class CurrencyRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -0,0 +1,70 @@
<?php
/**
* DataDestroyRequest.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class DataDestroyRequest
*/
class DataDestroyRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check() && !auth()->user()->hasRole('demo');
}
/**
* Get all data from the request.
*
* @return string
*/
public function getObjects(): string
{
return $this->get('objects') ?? '';
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
$valid = 'budgets,bills,piggy_banks,rules,recurring,categories,tags,object_groups' .
',accounts,asset_accounts,expense_accounts,revenue_accounts,liabilities,transactions,withdrawals,deposits,transfers';
return [
'objects' => sprintf('min:1|string|in:%s', $valid),
];
}
}

View File

@ -25,13 +25,17 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Request class for end points that require date parameters.
*
* Class DateRequest
*/
class DateRequest extends Request
class DateRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -24,6 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\LinkType;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
/**
@ -33,8 +35,9 @@ use Illuminate\Validation\Rule;
* @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/
class LinkTypeRequest extends Request
class LinkTypeRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -1,7 +1,7 @@
<?php
declare(strict_types=1);
/**
* TransferRequest.php
* ObjectGroupUpdateRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
@ -20,16 +20,21 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Requests\Search;
declare(strict_types=1);
use FireflyIII\Api\V1\Requests\Request;
use FireflyIII\Rules\IsTransferAccount;
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class TransferRequest
* Class AccountObjectGroupUpdateRequestUpdateRequest
*
* @codeCoverageIgnore
*/
class TransferRequest extends Request
class ObjectGroupUpdateRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*
@ -44,14 +49,26 @@ class TransferRequest extends Request
/**
* @return array
*/
public function rules(): array
public function getUpdateData(): array
{
return [
'source' => ['required', new IsTransferAccount],
'destination' => ['required', new IsTransferAccount],
'amount' => 'required|numeric|more:0',
'description' => 'required|min:1',
'date' => 'required|date',
'title' => $this->string('title'),
'order' => $this->integer('order'),
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
$objectGroup = $this->route()->parameter('objectGroup');
return [
'title' => sprintf('min:1|uniqueObjectGroup:%d', $objectGroup->id),
'order' => 'numeric',
];
}
}

View File

@ -27,6 +27,8 @@ use FireflyIII\Models\PiggyBank;
use FireflyIII\Rules\IsAssetAccountId;
use FireflyIII\Rules\LessThanPiggyTarget;
use FireflyIII\Rules\ZeroOrMore;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
*
@ -35,8 +37,10 @@ use FireflyIII\Rules\ZeroOrMore;
* @codeCoverageIgnore
* TODO AFTER 4.8,0: split this into two request classes.
*/
class PiggyBankRequest extends Request
class PiggyBankRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*
@ -63,6 +67,7 @@ class PiggyBankRequest extends Request
'startdate' => $this->date('start_date'),
'targetdate' => $this->date('target_date'),
'notes' => $this->nlString('notes'),
'order' => $this->integer('order'),
];
}
@ -90,7 +95,7 @@ class PiggyBankRequest extends Request
$piggyBank = $this->route()->parameter('piggyBank');
$rules['name'] = 'between:1,255|uniquePiggyBankForUser:' . $piggyBank->id;
$rules['account_id'] = ['belongsToUser:accounts', new IsAssetAccountId];
$rules['target_amount'] = 'numeric|more:0';
$rules['target_amount'] = 'numeric|gt:0';
$rules['current_amount'] = ['numeric', new ZeroOrMore, new LessThanPiggyTarget];
break;
}

View File

@ -0,0 +1,89 @@
<?php
/**
* PiggyBankStoreRequest.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\ZeroOrMore;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
*
* Class PiggyBankStoreRequest
*
* @codeCoverageIgnore
*/
class PiggyBankStoreRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/**
* Get all data from the request.
*
* @return array
*/
public function getAll(): array
{
return [
'name' => $this->string('name'),
'account_id' => $this->integer('account_id'),
'targetamount' => $this->string('target_amount'),
'current_amount' => $this->string('current_amount'),
'startdate' => $this->date('start_date'),
'targetdate' => $this->date('target_date'),
'notes' => $this->nlString('notes'),
'object_group_id' => $this->integer('object_group_id'),
'object_group' => $this->string('object_group_name'),
];
}
/**
* The rules that the incoming request must be matched against.
*
* @return array
*/
public function rules(): array
{
return [
'name' => 'required|between:1,255|uniquePiggyBankForUser',
'current_amount' => ['numeric', new ZeroOrMore, 'lte:target_amount'],
'account_id' => 'required|numeric|belongsToUser:accounts,id',
'object_group_id' => 'numeric|belongsToUser:object_groups,id',
'target_amount' => ['numeric', new ZeroOrMore, 'lte:target_amount', 'required'],
'start_date' => 'date|nullable',
'target_date' => 'date|nullable|after:start_date',
'notes' => 'max:65000',
];
}
}

View File

@ -23,15 +23,18 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
*
* Class PreferenceRequest
*
* @codeCoverageIgnore
*/
class PreferenceRequest extends Request
class PreferenceRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.

View File

@ -26,18 +26,20 @@ namespace FireflyIII\Api\V1\Requests;
use Carbon\Carbon;
use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetRecurrenceData;
use FireflyIII\Validation\CurrencyValidation;
use FireflyIII\Validation\RecurrenceValidation;
use FireflyIII\Validation\TransactionValidation;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
/**
* Class RecurrenceStoreRequest
*/
class RecurrenceStoreRequest extends Request
class RecurrenceStoreRequest extends FormRequest
{
use RecurrenceValidation, TransactionValidation, CurrencyValidation;
use ConvertsDataTypes, RecurrenceValidation, TransactionValidation, CurrencyValidation, GetRecurrenceData;
/**
* Authorize logged in users.
*
@ -104,8 +106,8 @@ class RecurrenceStoreRequest extends Request
'repetitions.*.skip' => 'required|numeric|between:0,31',
'repetitions.*.weekend' => 'required|numeric|min:1|max:4',
'transactions.*.description' => 'required|between:1,255',
'transactions.*.amount' => 'required|numeric|more:0',
'transactions.*.foreign_amount' => 'numeric|more:0',
'transactions.*.amount' => 'required|numeric|gt:0',
'transactions.*.foreign_amount' => 'numeric|gt:0',
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id',
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id',

View File

@ -26,17 +26,20 @@ namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Recurrence;
use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Support\Request\GetRecurrenceData;
use FireflyIII\Validation\CurrencyValidation;
use FireflyIII\Validation\RecurrenceValidation;
use FireflyIII\Validation\TransactionValidation;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
/**
* Class RecurrenceUpdateRequest
*/
class RecurrenceUpdateRequest extends Request
class RecurrenceUpdateRequest extends FormRequest
{
use RecurrenceValidation, TransactionValidation, CurrencyValidation;
use ConvertsDataTypes, RecurrenceValidation, TransactionValidation, CurrencyValidation, GetRecurrenceData;
/**
* Authorize logged in users.
@ -107,8 +110,8 @@ class RecurrenceUpdateRequest extends Request
'repetitions.*.weekend' => 'required|numeric|min:1|max:4',
'transactions.*.description' => 'required|between:1,255',
'transactions.*.amount' => 'required|numeric|more:0',
'transactions.*.foreign_amount' => 'numeric|more:0',
'transactions.*.amount' => 'required|numeric|gt:0',
'transactions.*.foreign_amount' => 'numeric|gt:0',
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id',
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id',

View File

@ -25,6 +25,8 @@ namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\RuleGroup;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
@ -32,8 +34,9 @@ use FireflyIII\Rules\IsBoolean;
* Class RuleGroupRequest
* TODO AFTER 4.8,0: split this into two request classes.
*/
class RuleGroupRequest extends Request
class RuleGroupRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -30,14 +30,17 @@ use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Collection;
use Log;
/**
* Class RuleGroupTestRequest
*/
class RuleGroupTestRequest extends Request
class RuleGroupTestRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -30,14 +30,17 @@ use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Collection;
use Log;
/**
* Class RuleGroupTriggerRequest
*/
class RuleGroupTriggerRequest extends Request
class RuleGroupTriggerRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -24,6 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
use function is_array;
@ -32,8 +34,9 @@ use function is_array;
* Class RuleStoreRequest
*
*/
class RuleStoreRequest extends Request
class RuleStoreRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -30,14 +30,17 @@ use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Collection;
use Log;
/**
* Class RuleTestRequest
*/
class RuleTestRequest extends Request
class RuleTestRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -29,14 +29,17 @@ use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Collection;
use Log;
/**
* Class RuleTriggerRequest
*/
class RuleTriggerRequest extends Request
class RuleTriggerRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -24,6 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
use function is_array;
@ -32,8 +34,9 @@ use function is_array;
* Class RuleUpdateRequest
*
*/
class RuleUpdateRequest extends Request
class RuleUpdateRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -24,6 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Location;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class TagStoreRequest
@ -31,9 +33,9 @@ use FireflyIII\Models\Location;
* @codeCoverageIgnore
*
*/
class TagStoreRequest extends Request
class TagStoreRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -25,6 +25,8 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Models\Location;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class TagUpdateRequest
@ -32,9 +34,9 @@ use FireflyIII\Models\Location;
* @codeCoverageIgnore
*
*/
class TagUpdateRequest extends Request
class TagUpdateRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -25,15 +25,18 @@ namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
/**
*
* Class TransactionLinkRequest
*/
class TransactionLinkRequest extends Request
class TransactionLinkRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*

View File

@ -28,18 +28,20 @@ use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsDateOrTime;
use FireflyIII\Support\NullArrayObject;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Validation\CurrencyValidation;
use FireflyIII\Validation\GroupValidation;
use FireflyIII\Validation\TransactionValidation;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
use Log;
/**
* Class TransactionStoreRequest
*/
class TransactionStoreRequest extends Request
class TransactionStoreRequest extends FormRequest
{
use TransactionValidation, GroupValidation, CurrencyValidation;
use TransactionValidation, GroupValidation, CurrencyValidation, ConvertsDataTypes;
/**
* Authorize logged in users.
@ -98,7 +100,7 @@ class TransactionStoreRequest extends Request
'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code|nullable',
// amount
'transactions.*.amount' => 'required|numeric|more:0',
'transactions.*.amount' => 'required|numeric|gt:0',
'transactions.*.foreign_amount' => 'numeric',
// description
@ -138,6 +140,7 @@ class TransactionStoreRequest extends Request
'transactions.*.external_id' => 'min:1,max:255|nullable',
'transactions.*.recurrence_id' => 'min:1,max:255|nullable',
'transactions.*.bunq_payment_id' => 'min:1,max:255|nullable',
'transactions.*.external_uri' => 'min:1,max:255|nullable|url',
// SEPA fields:
'transactions.*.sepa_cc' => 'min:1,max:255|nullable',
@ -221,7 +224,7 @@ class TransactionStoreRequest extends Request
// foreign currency info:
'foreign_currency_id' => $this->integerFromValue((string) $object['foreign_currency_id']),
'foreign_currency_code' => $this->stringFromValue($object['foreign_currency_code']),
'foreign_currency_code' => $this->stringFromValue((string) $object['foreign_currency_code']),
// amount and foreign amount. Cannot be 0.
'amount' => $this->stringFromValue((string) $object['amount']),
@ -232,37 +235,37 @@ class TransactionStoreRequest extends Request
// source of transaction. If everything is null, assume cash account.
'source_id' => $this->integerFromValue((string) $object['source_id']),
'source_name' => $this->stringFromValue($object['source_name']),
'source_iban' => $this->stringFromValue($object['source_iban']),
'source_number' => $this->stringFromValue($object['source_number']),
'source_bic' => $this->stringFromValue($object['source_bic']),
'source_name' => $this->stringFromValue((string) $object['source_name']),
'source_iban' => $this->stringFromValue((string) $object['source_iban']),
'source_number' => $this->stringFromValue((string) $object['source_number']),
'source_bic' => $this->stringFromValue((string) $object['source_bic']),
// destination of transaction. If everything is null, assume cash account.
'destination_id' => $this->integerFromValue((string) $object['destination_id']),
'destination_name' => $this->stringFromValue($object['destination_name']),
'destination_iban' => $this->stringFromValue($object['destination_iban']),
'destination_number' => $this->stringFromValue($object['destination_number']),
'destination_bic' => $this->stringFromValue($object['destination_bic']),
'destination_name' => $this->stringFromValue((string) $object['destination_name']),
'destination_iban' => $this->stringFromValue((string) $object['destination_iban']),
'destination_number' => $this->stringFromValue((string) $object['destination_number']),
'destination_bic' => $this->stringFromValue((string) $object['destination_bic']),
// budget info
'budget_id' => $this->integerFromValue((string) $object['budget_id']),
'budget_name' => $this->stringFromValue($object['budget_name']),
'budget_name' => $this->stringFromValue((string) $object['budget_name']),
// category info
'category_id' => $this->integerFromValue((string) $object['category_id']),
'category_name' => $this->stringFromValue($object['category_name']),
'category_name' => $this->stringFromValue((string) $object['category_name']),
// journal bill reference. Optional. Will only work for withdrawals
'bill_id' => $this->integerFromValue((string) $object['bill_id']),
'bill_name' => $this->stringFromValue($object['bill_name']),
'bill_name' => $this->stringFromValue((string) $object['bill_name']),
// piggy bank reference. Optional. Will only work for transfers
'piggy_bank_id' => $this->integerFromValue((string) $object['piggy_bank_id']),
'piggy_bank_name' => $this->stringFromValue($object['piggy_bank_name']),
'piggy_bank_name' => $this->stringFromValue((string) $object['piggy_bank_name']),
// some other interesting properties
'reconciled' => $this->convertBoolean((string) $object['reconciled']),
'notes' => $this->nlStringFromValue($object['notes']),
'notes' => $this->nlStringFromValue((string) $object['notes']),
'tags' => $this->arrayFromValue($object['tags']),
// all custom fields:
@ -271,6 +274,7 @@ class TransactionStoreRequest extends Request
'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->stringFromValue((string) $object['bunq_payment_id']),
'external_uri' => $this->stringFromValue((string) $object['external_uri']),
'sepa_cc' => $this->stringFromValue($object['sepa_cc']),
'sepa_ct_op' => $this->stringFromValue($object['sepa_ct_op']),

View File

@ -28,17 +28,19 @@ use FireflyIII\Models\TransactionGroup;
use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Rules\IsDateOrTime;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\Validation\GroupValidation;
use FireflyIII\Validation\TransactionValidation;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
use Log;
/**
* Class TransactionUpdateRequest
*/
class TransactionUpdateRequest extends Request
class TransactionUpdateRequest extends FormRequest
{
use TransactionValidation, GroupValidation;
use TransactionValidation, GroupValidation, ConvertsDataTypes;
/** @var array Array values. */
private $arrayFields;
@ -127,6 +129,7 @@ class TransactionUpdateRequest extends Request
'sepa_ep',
'sepa_ci',
'sepa_batch_id',
'external_uri'
];
$this->booleanFields = [
'reconciled',
@ -172,7 +175,7 @@ class TransactionUpdateRequest extends Request
'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
// amount
'transactions.*.amount' => 'numeric|more:0|max:100000000000',
'transactions.*.amount' => 'numeric|gt:0|max:100000000000',
'transactions.*.foreign_amount' => 'numeric|gte:0',
// description
@ -204,6 +207,7 @@ class TransactionUpdateRequest extends Request
'transactions.*.external_id' => 'min:1,max:255|nullable',
'transactions.*.recurrence_id' => 'min:1,max:255|nullable',
'transactions.*.bunq_payment_id' => 'min:1,max:255|nullable',
'transactions.*.external_uri' => 'min:1,max:255|nullable|url',
// SEPA fields:
'transactions.*.sepa_cc' => 'min:1,max:255|nullable',
@ -263,17 +267,13 @@ class TransactionUpdateRequest extends Request
// TODO if the transaction_journal_id is empty, some fields are mandatory, like the amount!
// all journals must have a description
//$this->validateDescriptions($validator);
// // validate foreign currency info
// $this->validateForeignCurrencyInformation($validator);
//
//
// // make sure all splits have valid source + dest info
// $this->validateSplitAccounts($validator);
// the group must have a description if > 1 journal.
// $this->validateGroupDescription($validator);
}
);
}

View File

@ -24,16 +24,17 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\User;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class UserStoreRequest
*/
class UserStoreRequest extends Request
class UserStoreRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*
@ -41,21 +42,7 @@ class UserStoreRequest extends Request
*/
public function authorize(): bool
{
$result = false;
// Only allow authenticated users
if (auth()->check()) {
/** @var User $user */
$user = auth()->user();
/** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class);
if ($repository->hasRole($user, 'owner')) {
$result = true; // @codeCoverageIgnore
}
}
return $result;
return auth()->check() && auth()->user()->hasRole('owner');
}
/**

View File

@ -26,14 +26,17 @@ namespace FireflyIII\Api\V1\Requests;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Rules\IsBoolean;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\User;
use Illuminate\Foundation\Http\FormRequest;
/**
* Class UserUpdateRequest
*/
class UserUpdateRequest extends Request
class UserUpdateRequest extends FormRequest
{
use ConvertsDataTypes;
/**
* Authorize logged in users.
*
@ -41,21 +44,7 @@ class UserUpdateRequest extends Request
*/
public function authorize(): bool
{
$result = false;
// Only allow authenticated users
if (auth()->check()) {
/** @var User $user */
$user = auth()->user();
/** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class);
if ($repository->hasRole($user, 'owner')) {
$result = true; // @codeCoverageIgnore
}
}
return $result;
return auth()->check() && auth()->user()->hasRole('owner');
}
/**

View File

@ -70,11 +70,13 @@ class CorrectDatabase extends Command
'firefly-iii:delete-empty-journals',
'firefly-iii:delete-empty-groups',
'firefly-iii:fix-account-types',
'firefly-iii:fix-account-order',
'firefly-iii:rename-meta-fields',
'firefly-iii:fix-ob-currencies',
'firefly-iii:fix-long-descriptions',
'firefly-iii:fix-recurring-transactions',
'firefly-iii:restore-oauth-keys',
'firefly-iii:fix-transaction-types'
];
foreach ($commands as $command) {
$this->line(sprintf('Now executing %s', $command));

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* CorrectOpeningBalanceCurrencies.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\Account;

View File

@ -0,0 +1,94 @@
<?php
/**
* FixAccountTypes.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\User;
use Illuminate\Console\Command;
/**
* Class FixAccountOrder
*/
class FixAccountOrder extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Make sure account order is correct.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:fix-account-order';
private AccountRepositoryInterface $repository;
/**
* Execute the console command.
*
* @throws FireflyException
* @return int
*/
public function handle(): int
{
$this->stupidLaravel();
$start = microtime(true);
$users = User::get();
foreach ($users as $user) {
$this->repository->setUser($user);
$sets = [
[AccountType::DEFAULT, AccountType::ASSET],
[AccountType::EXPENSE, AccountType::BENEFICIARY],
[AccountType::REVENUE],
[AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE],
];
foreach ($sets as $set) {
$this->repository->resetAccountOrder($set);
}
}
$end = round(microtime(true) - $start, 2);
$this->info(sprintf('Verifying account order took %s seconds', $end));
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.
*
* @codeCoverageIgnore
*/
private function stupidLaravel(): void
{
$this->repository = app(AccountRepositoryInterface::class);
}
}

View File

@ -222,7 +222,7 @@ class FixAccountTypes extends Command
*/
private function inspectJournal(TransactionJournal $journal): void
{
Log::debug(sprintf('Now trying to fix journal #%d', $journal->id));
//Log::debug(sprintf('Now trying to fix journal #%d', $journal->id));
$count = $journal->transactions()->count();
if (2 !== $count) {
Log::debug(sprintf('Journal has %d transactions, so cant fix.', $count));

View File

@ -0,0 +1,81 @@
<?php
/**
* FixGroupAccounts.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use DB;
use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Handlers\Events\UpdatedGroupEventHandler;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
/**
* Class FixGroupAccounts
*/
class FixGroupAccounts extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Unify the source / destination accounts of split groups.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:unify-group-accounts';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
// select transaction_group_id, count(transaction_group_id) as the_count from transaction_journals group by transaction_group_id having the_count > 1
$groups = [];
$res = TransactionJournal
::groupBy('transaction_group_id')
->get(['transaction_group_id', DB::raw('COUNT(transaction_group_id) as the_count')]);
foreach ($res as $journal) {
if ((int) $journal->the_count > 1) {
$groups[] = (int) $journal->transaction_group_id;
}
}
$handler = new UpdatedGroupEventHandler;
foreach($groups as $groupId) {
$group = TransactionGroup::find($groupId);
$event = new UpdatedTransactionGroup($group);
$handler->unifyAccounts($event);
}
$this->line('Updated inconsistent transaction groups.');
return 0;
}
}

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* FixLongDescriptions.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\TransactionGroup;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* FixRecurringTransactions.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\Recurrence;

View File

@ -0,0 +1,169 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
/**
* Class FixTransactionTypes
*/
class FixTransactionTypes extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Make sure all transactions are of the correct type, based on source + dest.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:fix-transaction-types';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
$start = microtime(true);
$count = 0;
$journals = $this->collectJournals();
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {
$fixed = $this->fixJournal($journal);
if (true === $fixed) {
$count++;
}
}
$end = round(microtime(true) - $start, 2);
if ($count > 0) {
$this->info(sprintf('Corrected transaction type of %d transaction journals in %s seconds.', $count, $end));
return 0;
}
$this->line(sprintf('All transaction journals are of the correct transaction type (in %s seconds).', $end));
return 0;
}
/**
* @param TransactionJournal $journal
* @param string $expectedType
*/
private function changeJournal(TransactionJournal $journal, string $expectedType): void
{
$type = TransactionType::whereType($expectedType)->first();
if (null !== $type) {
$journal->transaction_type_id = $type->id;
$journal->save();
}
}
/**
* Collect all transaction journals.
*
* @return Collection
*/
private function collectJournals(): Collection
{
return TransactionJournal
::with(['transactionType', 'transactions', 'transactions.account', 'transactions.account.accountType'])
->get();
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
private function fixJournal(TransactionJournal $journal): bool
{
$type = $journal->transactionType->type;
try {
$source = $this->getSourceAccount($journal);
$destination = $this->getDestinationAccount($journal);
} catch (FireflyException $e) {
$this->error($e->getMessage());
return false;
}
$expectedType = (string) config(sprintf('firefly.account_to_transaction.%s.%s', $source->accountType->type, $destination->accountType->type));
if ($expectedType !== $type) {
$this->line(sprintf('Transaction journal #%d was of type "%s" but is corrected to "%s"', $journal->id, $type, $expectedType));
$this->changeJournal($journal, $expectedType);
return true;
}
return false;
}
/**
* @param TransactionJournal $journal
*
* @throws FireflyException
* @return Account
*/
private function getDestinationAccount(TransactionJournal $journal): Account
{
$collection = $journal->transactions->filter(
static function (Transaction $transaction) {
return $transaction->amount > 0;
}
);
if (0 === $collection->count()) {
throw new FireflyException(sprintf('Journal #%d has no destination transaction.', $journal->id));
}
if (1 !== $collection->count()) {
throw new FireflyException(sprintf('Journal #%d has multiple destination transactions.', $journal->id));
}
/** @var Transaction $transaction */
$transaction = $collection->first();
$account = $transaction->account;
if (null === $account) {
throw new FireflyException(sprintf('Journal #%d, transaction #%d has no destination account.', $journal->id, $transaction->id));
}
return $account;
}
/**
* @param TransactionJournal $journal
*
* @throws FireflyException
* @return Account
*/
private function getSourceAccount(TransactionJournal $journal): Account
{
$collection = $journal->transactions->filter(
static function (Transaction $transaction) {
return $transaction->amount < 0;
}
);
if (0 === $collection->count()) {
throw new FireflyException(sprintf('Journal #%d has no source transaction.', $journal->id));
}
if (1 !== $collection->count()) {
throw new FireflyException(sprintf('Journal #%d has multiple source transactions.', $journal->id));
}
/** @var Transaction $transaction */
$transaction = $collection->first();
$account = $transaction->account;
if (null === $account) {
throw new FireflyException(sprintf('Journal #%d, transaction #%d has no source account.', $journal->id, $transaction->id));
}
return $account;
}
}

View File

@ -1,6 +1,4 @@
<?php
declare(strict_types=1);
/**
* CreateDatabase.php
@ -22,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands;
use Illuminate\Console\Command;

View File

@ -98,7 +98,7 @@ class DecryptDatabase extends Command
} catch(JsonException $e) {
Log::error($e->getMessage());
}
Log::debug(sprintf('Decrypted field "%s" "%s" to "%s" in table "%s" (row #%d)', $field, $original, print_r($value, true), $table, $id));
//Log::debug(sprintf('Decrypted field "%s" "%s" to "%s" in table "%s" (row #%d)', $field, $original, print_r($value, true), $table, $id));
/** @var Preference $object */
$object = Preference::find((int) $id);
@ -110,7 +110,7 @@ class DecryptDatabase extends Command
}
if ($value !== $original) {
Log::debug(sprintf('Decrypted field "%s" "%s" to "%s" in table "%s" (row #%d)', $field, $original, $value, $table, $id));
//Log::debug(sprintf('Decrypted field "%s" "%s" to "%s" in table "%s" (row #%d)', $field, $original, $value, $table, $id));
DB::table($table)->where('id', $id)->update([$field => $value]);
}
}
@ -159,7 +159,6 @@ class DecryptDatabase extends Command
if ('The MAC is invalid.' === $e->getMessage()) {
throw new FireflyException($e->getMessage()); // @codeCoverageIgnore
}
Log::debug(sprintf('Could not decrypt. %s', $e->getMessage()));
}
return $value;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* ExportData.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Export;
use Carbon\Carbon;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* RestoreOAuthKeys.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Integrity;
use FireflyIII\Support\System\OAuthKeys;

View File

@ -1,5 +1,4 @@
<?php
declare(strict_types=1);
/**
* SetLatestVersion.php
@ -21,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands;
use Illuminate\Console\Command;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* MigrateRecurrenceMeta.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Upgrade;
use FireflyIII\Models\RecurrenceMeta;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* MigrateTagLocations.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Upgrade;
use FireflyIII\Models\Location;

View File

@ -211,7 +211,6 @@ class MigrateToRules extends Command
$lang = app('preferences')->getForUser($user, 'language', 'en_US');
$groupTitle = (string) trans('firefly.rulegroup_for_bills_title', [], $lang->data);
$ruleGroup = $this->ruleGroupRepository->findByTitle($groupTitle);
//$currency = $this->getCurrency($user);
if (null === $ruleGroup) {
$ruleGroup = $this->ruleGroupRepository->store(

View File

@ -341,19 +341,17 @@ class TransferCurrenciesCorrections extends Command
if (isset($this->accountCurrencies[$accountId]) && $this->accountCurrencies[$accountId] instanceof TransactionCurrency) {
return $this->accountCurrencies[$accountId]; // @codeCoverageIgnore
}
// TODO we can use getAccountCurrency() instead
$currencyId = (int) $this->accountRepos->getMetaValue($account, 'currency_id');
$result = $this->currencyRepos->findNull($currencyId);
if (null === $result) {
$currency = $this->accountRepos->getAccountCurrency($account);
if (null === $currency) {
// @codeCoverageIgnoreStart
$this->accountCurrencies[$accountId] = 0;
return null;
// @codeCoverageIgnoreEnd
}
$this->accountCurrencies[$accountId] = $result;
$this->accountCurrencies[$accountId] = $currency;
return $result;
return $currency;
}
/**

View File

@ -89,10 +89,13 @@ class UpgradeDatabase extends Command
'firefly-iii:delete-empty-journals',
'firefly-iii:delete-empty-groups',
'firefly-iii:fix-account-types',
'firefly-iii:fix-account-order',
'firefly-iii:rename-meta-fields',
'firefly-iii:fix-ob-currencies',
'firefly-iii:fix-long-descriptions',
'firefly-iii:fix-recurring-transactions',
'firefly-iii:unify-group-accounts',
'firefly-iii:fix-transaction-types',
// two report commands
'firefly-iii:report-empty-objects',

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands;
use FireflyIII\Support\System\GeneratesInstallationId;
use FireflyIII\User;
use Illuminate\Console\Command;
/**
@ -68,6 +69,7 @@ class UpgradeFireflyInstructions extends Command
app('telemetry')->feature('system.database.driver', env('DB_CONNECTION', '(unknown)'));
app('telemetry')->feature('system.os.is_docker', $isDocker);
app('telemetry')->feature('system.command.executed', $this->signature);
app('telemetry')->feature('system.users.count', (string)User::count());
return 0;
}

View File

@ -1,8 +1,8 @@
<?php
declare(strict_types=1);
/**
* DuplicateTransactionException.php
* Copyright (c) 2019 james@firefly-iii.org
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Exceptions;
use Exception;

View File

@ -43,17 +43,12 @@ class AccountFactory
use AccountServiceTrait, LocationServiceTrait;
/** @var AccountRepositoryInterface */
protected $accountRepository;
/** @var array */
protected $validAssetFields = ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'];
/** @var array */
protected $validCCFields = ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'];
/** @var array */
protected $validFields = ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth'];
/** @var array */
private $canHaveVirtual;
/** @var User */
private $user;
protected $accountRepository;
protected array $validAssetFields;
protected array $validCCFields;
protected array $validFields;
private array $canHaveVirtual;
private User $user;
/**
* AccountFactory constructor.
@ -67,6 +62,10 @@ class AccountFactory
}
$this->canHaveVirtual = [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD];
$this->accountRepository = app(AccountRepositoryInterface::class);
$this->validAssetFields = ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'];
$this->validCCFields = ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'];
$this->validFields = ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth'];
}
/**
@ -98,6 +97,7 @@ class AccountFactory
'user_id' => $this->user->id,
'account_type_id' => $type->id,
'name' => $data['name'],
'order' => $data['order'] ?? 0,
'virtual_balance' => $data['virtual_balance'] ?? null,
'active' => true === $data['active'],
'iban' => $data['iban'],

View File

@ -27,6 +27,7 @@ namespace FireflyIII\Factory;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
use FireflyIII\Services\Internal\Support\BillServiceTrait;
use FireflyIII\User;
use Illuminate\Database\QueryException;
@ -37,7 +38,7 @@ use Log;
*/
class BillFactory
{
use BillServiceTrait;
use BillServiceTrait, CreatesObjectGroups;
/** @var User */
private $user;
@ -97,6 +98,24 @@ class BillFactory
$this->updateNote($bill, $data['notes']);
}
$objectGroupTitle = $data['object_group'] ?? '';
if ('' !== $objectGroupTitle) {
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
if (null !== $objectGroup) {
$bill->objectGroups()->sync([$objectGroup->id]);
$bill->save();
}
}
// try also with ID:
$objectGroupId = (int) ($data['object_group_id'] ?? 0);
if (0 !== $objectGroupId) {
$objectGroup = $this->findObjectGroupById($objectGroupId);
if (null !== $objectGroup) {
$bill->objectGroups()->sync([$objectGroup->id]);
$bill->save();
}
}
return $bill;
}

View File

@ -56,12 +56,9 @@ class TransactionJournalFactory
{
use JournalServiceTrait;
/** @var AccountRepositoryInterface */
private $accountRepository;
/** @var AccountValidator */
private $accountValidator;
/** @var BillRepositoryInterface */
private $billRepository;
private AccountRepositoryInterface $accountRepository;
private AccountValidator $accountValidator;
private BillRepositoryInterface $billRepository;
/** @var CurrencyRepositoryInterface */
private $currencyRepository;
/** @var bool */
@ -88,11 +85,12 @@ class TransactionJournalFactory
public function __construct()
{
$this->errorOnHash = false;
// TODO move valid meta fields to config.
$this->fields = [
// sepa
'sepa_cc', 'sepa_ct_op', 'sepa_ct_id',
'sepa_db', 'sepa_country', 'sepa_ep',
'sepa_ci', 'sepa_batch_id',
'sepa_ci', 'sepa_batch_id', 'external_uri',
// dates
'interest_date', 'book_date', 'process_date',
@ -100,7 +98,11 @@ class TransactionJournalFactory
// others
'recurrence_id', 'internal_reference', 'bunq_payment_id',
'import_hash', 'import_hash_v2', 'external_id', 'original_source'];
'import_hash', 'import_hash_v2', 'external_id', 'original_source',
// recurring transactions
'recurrence_total', 'recurrence_count'
];
if ('testing' === config('app.env')) {
@ -367,19 +369,6 @@ class TransactionJournalFactory
// verify that journal has two transactions. Otherwise, delete and cancel.
// TODO this can't be faked so it can't be tested.
// $count = $journal->transactions()->count();
// if (2 !== $count) {
// // @codeCoverageIgnoreStart
// Log::error(sprintf('The journal unexpectedly has %d transaction(s). This is not OK. Cancel operation.', $count));
// try {
// $journal->delete();
// } catch (Exception $e) {
// Log::debug(sprintf('Dont care: %s.', $e->getMessage()));
// }
//
// return null;
// // @codeCoverageIgnoreEnd
// }
$journal->completed = true;
$journal->save();

View File

@ -23,14 +23,58 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\TransactionRules\Engine\RuleEngine;
use Log;
/**
* Class UpdatedGroupEventHandler
*/
class UpdatedGroupEventHandler
{
/**
* This method will make sure all source / destination accounts are the same.
*
* @param UpdatedTransactionGroup $updatedGroupEvent
*/
public function unifyAccounts(UpdatedTransactionGroup $updatedGroupEvent): void
{
$group = $updatedGroupEvent->transactionGroup;
if (1 === $group->transactionJournals->count()) {
return;
}
Log::debug(sprintf('Correct inconsistent accounts in group #%d', $group->id));
// first journal:
/** @var TransactionJournal $first */
$first = $group->transactionJournals()
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->orderBy('transaction_journals.description', 'DESC')
->first();
$all = $group->transactionJournals()->get()->pluck('id')->toArray();
/** @var Account $sourceAccount */
$sourceAccount = $first->transactions()->where('amount', '<', '0')->first()->account;
/** @var Account $destAccount */
$destAccount = $first->transactions()->where('amount', '>', '0')->first()->account;
$type = $first->transactionType->type;
if (TransactionType::TRANSFER === $type || TransactionType::WITHDRAWAL === $type) {
// set all source transactions to source account:
Transaction::whereIn('transaction_journal_id', $all)
->where('amount', '<', 0)->update(['account_id' => $sourceAccount->id]);
}
if (TransactionType::TRANSFER === $type || TransactionType::DEPOSIT === $type) {
// set all destination transactions to destination account:
Transaction::whereIn('transaction_journal_id', $all)
->where('amount', '>', 0)->update(['account_id' => $destAccount->id]);
}
}
/**
* This method will check all the rules when a journal is updated.
*

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* AccountCollection.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Collector\Extensions;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* AmountCollection.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Collector\Extensions;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* CollectorProperties.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Collector\Extensions;
use FireflyIII\User;
@ -36,6 +38,8 @@ trait CollectorProperties
private $hasAccountInfo;
/** @var bool Will be true if query result includes bill information. */
private $hasBillInformation;
/** @var bool */
private $hasNotesInformation;
/** @var bool Will be true if query result contains budget info. */
private $hasBudgetInformation;
/** @var bool Will be true if query result contains category info. */
@ -56,4 +60,6 @@ trait CollectorProperties
private $total;
/** @var User The user object. */
private $user;
private bool $hasJoinedMetaTables;
}

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* MetaCollection.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Collector\Extensions;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
@ -28,6 +30,7 @@ use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\Tag;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
/**
@ -36,6 +39,27 @@ use Illuminate\Support\Collection;
trait MetaCollection
{
/**
* @inheritDoc
*/
public function withNotes(): GroupCollectorInterface
{
if (false === $this->hasNotesInformation) {
// join bill table
$this->query->leftJoin(
'notes',
static function (JoinClause $join) {
$join->on('notes.noteable_id', '=', 'transaction_journals.id');
$join->where('notes.noteable_type', '=', 'FireflyIII\Models\TransactionJournal');
}
);
// add fields
$this->fields[] = 'notes.text as notes';
$this->hasNotesInformation = true;
}
return $this;
}
/**
* Limit the search to a specific bill.
@ -288,4 +312,36 @@ trait MetaCollection
}
/**
* @inheritDoc
*/
public function setExternalId(string $externalId): GroupCollectorInterface
{
if (false === $this->hasJoinedMetaTables) {
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$this->query->where('journal_meta.name', '=', 'external_id');
$this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s%%', $externalId));
return $this;
}
/**
* @inheritDoc
*/
public function setInternalReference(string $internalReference): GroupCollectorInterface
{
if (false === $this->hasJoinedMetaTables) {
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$this->query->where('journal_meta.name', '=', 'internal_reference');
$this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s%%', $internalReference));
return $this;
}
}

View File

@ -1,5 +1,5 @@
<?php
declare(strict_types=1);
/**
* TimeCollection.php
* Copyright (c) 2020 james@firefly-iii.org
@ -20,6 +20,8 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Collector\Extensions;
use Carbon\Carbon;

View File

@ -62,8 +62,10 @@ class GroupCollector implements GroupCollectorInterface
$this->hasCatInformation = false;
$this->hasBudgetInformation = false;
$this->hasBillInformation = false;
$this->hasNotesInformation = false;
$this->hasJoinedTagTables = false;
$this->hasJoinedAttTables = false;
$this->hasJoinedMetaTables = false;
$this->integerFields = [
'transaction_group_id',
'user_id',
@ -166,13 +168,8 @@ class GroupCollector implements GroupCollectorInterface
*/
public function getGroups(): Collection
{
//$start = microtime(true);
/** @var Collection $result */
$result = $this->query->get($this->fields);
//$end = round(microtime(true) - $start, 5);
// log info about query time.
//Log::info(sprintf('Query took Firefly III %s seconds', $end));
//Log::info($this->query->toSql(), $this->query->getBindings());
// now to parse this into an array.
$collection = $this->parseArray($result);
@ -311,7 +308,7 @@ class GroupCollector implements GroupCollectorInterface
$this->query->where(
static function (EloquentBuilder $q) use ($array) {
$q->where(
function (EloquentBuilder $q1) use ($array) {
static function (EloquentBuilder $q1) use ($array) {
foreach ($array as $word) {
$keyword = sprintf('%%%s%%', $word);
$q1->where('transaction_journals.description', 'LIKE', $keyword);
@ -552,9 +549,14 @@ class GroupCollector implements GroupCollectorInterface
$result['tags'] = [];
$result['attachments'] = [];
try {
$result['date'] = new Carbon($result['date']);
$result['created_at'] = new Carbon($result['created_at']);
$result['updated_at'] = new Carbon($result['updated_at']);
$result['date'] = new Carbon($result['date'], 'UTC');
$result['created_at'] = new Carbon($result['created_at'], 'UTC');
$result['updated_at'] = new Carbon($result['updated_at'], 'UTC');
// this is going to happen a lot:
$result['date']->setTimezone(config('app.timezone'));
$result['created_at']->setTimezone(config('app.timezone'));
$result['updated_at']->setTimezone(config('app.timezone'));
} catch (Exception $e) {
Log::error($e->getMessage());
}

View File

@ -398,6 +398,13 @@ interface GroupCollectorInterface
*/
public function withCategoryInformation(): GroupCollectorInterface;
/**
* Will include notes.
*
* @return GroupCollectorInterface
*/
public function withNotes(): GroupCollectorInterface;
/**
* Add tag info.
*
@ -419,4 +426,22 @@ interface GroupCollectorInterface
*/
public function withoutCategory(): GroupCollectorInterface;
/**
* Look for specific external ID's.
*
* @param string $externalId
*
* @return GroupCollectorInterface
*/
public function setExternalId(string $externalId): GroupCollectorInterface;
/**
* Look for specific external ID's.
*
* @param string $externalId
*
* @return GroupCollectorInterface
*/
public function setInternalReference(string $externalId): GroupCollectorInterface;
}

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