mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-08-22 13:19:29 +00:00
Compare commits
114 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b47614c965 | ||
|
9af458df49 | ||
|
a67e2b597d | ||
|
3c36eed461 | ||
|
5a7c3bd716 | ||
|
43476167d8 | ||
|
d357eaeb51 | ||
|
2e118c5f22 | ||
|
8e95530ca8 | ||
|
a04a6845f7 | ||
|
185e9b66d6 | ||
|
93a7c51dd1 | ||
|
f9ac40a811 | ||
|
b0027acf34 | ||
|
f5e5854479 | ||
|
95d72d065b | ||
|
56b2fa69bc | ||
|
e614427925 | ||
|
34dc1f9f53 | ||
|
94d9b78a33 | ||
|
b9d949d259 | ||
|
3376e1e663 | ||
|
ea98c2631f | ||
|
50b9fe649d | ||
|
56054531a3 | ||
|
1912e46113 | ||
|
075f951cfe | ||
|
26aad765ae | ||
|
73ba78d46d | ||
|
0d5dd40134 | ||
|
f0d84ad142 | ||
|
0b4ebf644d | ||
|
5b60db120f | ||
|
f2073a4494 | ||
|
3e12d26afd | ||
|
e458208966 | ||
|
e28a77dc87 | ||
|
a709596ccb | ||
|
849c7dfe02 | ||
|
e580093a34 | ||
|
4fa7a5c1bc | ||
|
d668007fee | ||
|
6cbccf3be6 | ||
|
9cd75dda1a | ||
|
56dff7ea67 | ||
|
6160f99e92 | ||
|
115639a004 | ||
|
a0c98c7d9f | ||
|
7842700bf1 | ||
|
4ecda4d4e0 | ||
|
c76d140d0b | ||
|
4f42eb1796 | ||
|
c67b10e38d | ||
|
614ceabd45 | ||
|
a94b2e8806 | ||
|
732616984b | ||
|
eddf0c1200 | ||
|
49013264d5 | ||
|
f12744ad8c | ||
|
4ddcb0c965 | ||
|
0846d4898f | ||
|
cb746200fa | ||
|
fe06a1f7a0 | ||
|
9c1cee738d | ||
|
7cc778673a | ||
|
38d0f0427f | ||
|
8572280b7b | ||
|
69b1769f22 | ||
|
5ceef2e9c3 | ||
|
d32446b171 | ||
|
d8ca39ffea | ||
|
d47bddde62 | ||
|
e4802ec958 | ||
|
6d855e119d | ||
|
7ab81e493a | ||
|
fa0397e431 | ||
|
aba3b361be | ||
|
1cf188ee08 | ||
|
f5983f08fd | ||
|
b812c2e09f | ||
|
d7466efbe1 | ||
|
dff30af9f2 | ||
|
25dcb73e27 | ||
|
63ed3d09d5 | ||
|
caf1e6010b | ||
|
2d97408c1f | ||
|
01c0d76c5a | ||
|
7c7032d951 | ||
|
6e722f5833 | ||
|
d3502c56d3 | ||
|
1b8eb3cd68 | ||
|
bc7bd84221 | ||
|
85b22341a4 | ||
|
f8c725e5b2 | ||
|
e6344e4f51 | ||
|
8eac10bf89 | ||
|
c1da0eeced | ||
|
0a6d5b1766 | ||
|
4035ac09ce | ||
|
f81a7cfac0 | ||
|
2b086879cc | ||
|
a3091f7509 | ||
|
70a6ac0038 | ||
|
468a53d587 | ||
|
51f3b17ad2 | ||
|
a864d3bd56 | ||
|
a4d5aa0d10 | ||
|
aff5ac2c0a | ||
|
effe92a05c | ||
|
a4ca6dfd38 | ||
|
e6012e1ca2 | ||
|
472497cafd | ||
|
34f4b16a63 | ||
|
7f55a870d9 |
@@ -10,6 +10,19 @@ parameters:
|
||||
- '#is neither abstract nor final#'
|
||||
- '#Control structures using switch should not be used\.#'
|
||||
- '#has a nullable return type declaration#'
|
||||
- '#with a nullable type declaration#'
|
||||
- '#with null as default value#'
|
||||
- '#Constructor in [a-zA-Z0-9\\_]+ has parameter \$[a-zA-Z0-9\\_]+ with default value#'
|
||||
-
|
||||
message: '#Function compact\(\) should not be used.#'
|
||||
paths:
|
||||
- ../app/Http/Controllers
|
||||
- ../app/Support/Http/Controllers/RenderPartialViews.php
|
||||
- ../app/Support/Form/FormSupport.php
|
||||
- ../app/Support/Form/CurrencyForm.php
|
||||
- ../app/Support/Form/AccountForm.php
|
||||
- ../app/Support/ExpandedForm.php
|
||||
- ../app/Generator/Report
|
||||
paths:
|
||||
- ../app
|
||||
- ../database
|
||||
@@ -17,4 +30,4 @@ parameters:
|
||||
- ../bootstrap/app.php
|
||||
|
||||
# The level 8 is the highest level. original was 5
|
||||
level: 5
|
||||
level: 2
|
||||
|
@@ -21,12 +21,13 @@
|
||||
#
|
||||
|
||||
# Install composer packages
|
||||
composer install --no-scripts --no-ansi
|
||||
#composer install --no-scripts --no-ansi
|
||||
|
||||
# enable test .env file.
|
||||
cp .ci/.env.ci .env
|
||||
|
||||
# Do static code analysis.
|
||||
./vendor/bin/phpstan analyse -c .ci/phpstan.neon --no-progress
|
||||
# ./vendor/bin/phpstan analyse -c .ci/phpstan.neon --no-progress
|
||||
./vendor/bin/phpstan analyse -c .ci/phpstan.neon
|
||||
|
||||
exit 0
|
@@ -24,6 +24,7 @@
|
||||
cp .ci/.env.ci ../.env
|
||||
|
||||
# download test database
|
||||
# TODO no longer exists
|
||||
wget --quiet https://raw.githubusercontent.com/firefly-iii/test-data/main/test_db.sqlite -o storage/database/test_db.sqlite
|
||||
|
||||
# run phpunit
|
||||
|
@@ -155,8 +155,16 @@ SEND_REPORT_JOURNALS=true
|
||||
|
||||
# Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places.
|
||||
# If you use Docker or similar, you can set this variable from a file by appending it with _FILE
|
||||
# Take note: it is no longer necessary to set this value, and it will be removed in future versions.
|
||||
MAPBOX_API_KEY=
|
||||
|
||||
#
|
||||
# Instead of the mapbox API key, just set this value to true if you want to set the location
|
||||
# of certain things, like transactions. Since this involves an external service, it's optional
|
||||
# and disabled by default.
|
||||
#
|
||||
ENABLE_EXTERNAL_MAP=false
|
||||
|
||||
# The map will default to this location:
|
||||
MAP_DEFAULT_LAT=51.983333
|
||||
MAP_DEFAULT_LONG=5.916667
|
||||
@@ -320,6 +328,7 @@ BROADCAST_DRIVER=log
|
||||
QUEUE_DRIVER=sync
|
||||
CACHE_PREFIX=firefly
|
||||
PUSHER_KEY=
|
||||
IPINFO_TOKEN=
|
||||
PUSHER_SECRET=
|
||||
PUSHER_ID=
|
||||
DEMO_USERNAME=
|
||||
|
@@ -66,7 +66,7 @@ class ObjectGroupController extends Controller
|
||||
$return = [];
|
||||
$result = $this->repository->search($data['query'], $data['limit']);
|
||||
|
||||
/** @var ObjectGroup $account */
|
||||
/** @var ObjectGroup $objectGroup */
|
||||
foreach ($result as $objectGroup) {
|
||||
$return[] = [
|
||||
'id' => (string)$objectGroup->id,
|
||||
|
@@ -86,12 +86,12 @@ class AccountController extends Controller
|
||||
$defaultSet = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray();
|
||||
$frontPage = app('preferences')->get('frontPageAccounts', $defaultSet);
|
||||
$default = app('amount')->getDefaultCurrency();
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if (0 === count($frontPage->data)) {
|
||||
$frontPage->data = $defaultSet;
|
||||
$frontPage->save();
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
// get accounts:
|
||||
$accounts = $this->repository->getAccountsById($frontPage->data);
|
||||
@@ -100,7 +100,7 @@ class AccountController extends Controller
|
||||
foreach ($accounts as $account) {
|
||||
$currency = $this->repository->getAccountCurrency($account);
|
||||
if (null === $currency) {
|
||||
$currency = $default; // @codeCoverageIgnore
|
||||
$currency = $default;
|
||||
}
|
||||
$currentSet = [
|
||||
'label' => $account->name,
|
||||
@@ -108,8 +108,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'),
|
||||
'start_date' => $start->toAtomString(),
|
||||
'end_date' => $end->toAtomString(),
|
||||
'type' => 'line', // line, area or bar
|
||||
'yAxisID' => 0, // 0, 1, 2
|
||||
'entries' => [],
|
||||
@@ -120,7 +120,7 @@ class AccountController extends Controller
|
||||
$previous = round((float)array_values($range)[0], 12);
|
||||
while ($currentStart <= $end) {
|
||||
$format = $currentStart->format('Y-m-d');
|
||||
$label = $currentStart->format('Y-m-d');
|
||||
$label = $currentStart->toAtomString();
|
||||
$balance = array_key_exists($format, $range) ? round((float)$range[$format], 12) : $previous;
|
||||
$previous = $balance;
|
||||
$currentStart->addDay();
|
||||
|
71
app/Api/V1/Controllers/Data/Bulk/AccountController.php
Normal file
71
app/Api/V1/Controllers/Data/Bulk/AccountController.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* AccountController.php
|
||||
* Copyright (c) 2021 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\Data\Bulk;
|
||||
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Data\Bulk\MoveTransactionsRequest;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Services\Internal\Destroy\AccountDestroyService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
* Class AccountController
|
||||
*/
|
||||
class AccountController extends Controller
|
||||
{
|
||||
private AccountRepositoryInterface $repository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->repository = app(AccountRepositoryInterface::class);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MoveTransactionsRequest $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function moveTransactions(MoveTransactionsRequest $request): JsonResponse
|
||||
{
|
||||
$accountIds = $request->getAll();
|
||||
$original = $this->repository->findNull($accountIds['original_account']);
|
||||
$destination = $this->repository->findNull($accountIds['destination_account']);
|
||||
|
||||
/** @var AccountDestroyService $service */
|
||||
$service = app(AccountDestroyService::class);
|
||||
$service->moveTransactions($original, $destination);
|
||||
|
||||
return response()->json([], 204);
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -25,7 +25,6 @@ namespace FireflyIII\Api\V1\Controllers\Data\Export;
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Api\V1\Requests\Data\Export\ExportRequest;
|
||||
use FireflyIII\Support\Export\ExportDataGenerator;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\Response as LaravelResponse;
|
||||
use League\Csv\CannotInsertRecord;
|
||||
|
||||
@@ -44,11 +43,8 @@ class ExportController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
/** @var ExportDataGenerator $exporter */
|
||||
$this->exporter = app(ExportDataGenerator::class);
|
||||
$this->exporter->setUser($user);
|
||||
$this->exporter->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -92,7 +88,7 @@ class ExportController extends Controller
|
||||
->header('Expires', '0')
|
||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||
->header('Pragma', 'public')
|
||||
->header('Content-Length', strlen($data[$key]));
|
||||
->header('Content-Length', (string)strlen($data[$key]));
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
@@ -44,9 +44,8 @@ class TagController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$user = auth()->user();
|
||||
$this->repository = app(TagRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -128,7 +127,7 @@ class TagController extends Controller
|
||||
$collector->setTypes([TransactionType::WITHDRAWAL])->setRange($start, $end)->setSourceAccounts($accounts);
|
||||
$collector->setTags($tags);
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
/** @var array $entry */
|
||||
/** @var array $journal */
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
|
@@ -130,7 +130,7 @@ class TagController extends Controller
|
||||
$collector->setTypes([TransactionType::DEPOSIT])->setRange($start, $end)->setDestinationAccounts($accounts);
|
||||
$collector->setTags($tags);
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
/** @var array $entry */
|
||||
/** @var array $journal */
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
|
@@ -132,7 +132,7 @@ class TagController extends Controller
|
||||
$collector->setTypes([TransactionType::TRANSFER])->setRange($start, $end)->setDestinationAccounts($accounts);
|
||||
$collector->setTags($tags);
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
/** @var array $entry */
|
||||
/** @var array $journal */
|
||||
foreach ($genericSet as $journal) {
|
||||
$currencyId = (int)$journal['currency_id'];
|
||||
$foreignCurrencyId = (int)$journal['foreign_currency_id'];
|
||||
|
@@ -100,7 +100,7 @@ class ShowController extends Controller
|
||||
->header('Expires', '0')
|
||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||
->header('Pragma', 'public')
|
||||
->header('Content-Length', strlen($content));
|
||||
->header('Content-Length', (string)strlen($content));
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
@@ -46,12 +46,8 @@ class DestroyController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var BillRepositoryInterface repository */
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -57,12 +57,8 @@ class ListController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var BillRepositoryInterface repository */
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -51,12 +51,8 @@ class ShowController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var BillRepositoryInterface repository */
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -52,12 +52,8 @@ class StoreController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var BillRepositoryInterface repository */
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -49,12 +49,8 @@ class UpdateController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var BillRepositoryInterface repository */
|
||||
$this->repository = app(BillRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -46,12 +46,8 @@ class DestroyController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CategoryRepositoryInterface repository */
|
||||
$this->repository = app(CategoryRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -56,12 +56,8 @@ class ListController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CategoryRepositoryInterface repository */
|
||||
$this->repository = app(CategoryRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -51,12 +51,8 @@ class ShowController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CategoryRepositoryInterface repository */
|
||||
$this->repository = app(CategoryRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -49,12 +49,8 @@ class StoreController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CategoryRepositoryInterface repository */
|
||||
$this->repository = app(CategoryRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -49,12 +49,8 @@ class UpdateController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CategoryRepositoryInterface repository */
|
||||
$this->repository = app(CategoryRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -46,12 +46,8 @@ class DestroyController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
/** @var RecurringRepositoryInterface repository */
|
||||
$this->repository = app(RecurringRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -54,12 +54,8 @@ class ListController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
/** @var RecurringRepositoryInterface repository */
|
||||
$this->repository = app(RecurringRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -51,12 +51,8 @@ class ShowController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
/** @var RecurringRepositoryInterface repository */
|
||||
$this->repository = app(RecurringRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -49,12 +49,8 @@ class StoreController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
/** @var RecurringRepositoryInterface repository */
|
||||
$this->repository = app(RecurringRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -1,86 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* TriggerController.php
|
||||
* Copyright (c) 2021 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\Models\Recurrence;
|
||||
|
||||
use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||
use FireflyIII\Support\Cronjobs\RecurringCronjob;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class TriggerController
|
||||
*/
|
||||
class TriggerController extends Controller
|
||||
{
|
||||
private RecurringRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* RecurrenceController constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
/** @var RecurringRepositoryInterface repository */
|
||||
$this->repository = app(RecurringRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* TODO currently unused + unreachable.
|
||||
*/
|
||||
public function trigger(): JsonResponse
|
||||
{
|
||||
/** @var RecurringCronjob $recurring */
|
||||
$recurring = app(RecurringCronjob::class);
|
||||
try {
|
||||
$result = $recurring->fire();
|
||||
} catch (FireflyException $e) {
|
||||
Log::error($e->getMessage());
|
||||
throw new FireflyException('200022: Error in cron job.', 0, $e);
|
||||
}
|
||||
if (false === $result) {
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
||||
return response()->json();
|
||||
}
|
||||
}
|
@@ -49,12 +49,8 @@ class UpdateController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
/** @var RecurringRepositoryInterface repository */
|
||||
$this->repository = app(RecurringRepositoryInterface::class);
|
||||
$this->repository->setUser($user);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -37,6 +37,7 @@ use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection as FractalCollection;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class TriggerController
|
||||
|
@@ -94,13 +94,13 @@ class StoreController extends Controller
|
||||
$validator = Validator::make(
|
||||
['transactions' => [['description' => $e->getMessage()]]], ['transactions.0.description' => new IsDuplicateTransaction]
|
||||
);
|
||||
throw new ValidationException($validator);
|
||||
throw new ValidationException($validator,0, $e);
|
||||
} catch (FireflyException $e) {
|
||||
Log::warning('Caught an exception. Return error message.');
|
||||
Log::error($e->getMessage());
|
||||
$message = sprintf('Internal exception: %s', $e->getMessage());
|
||||
$validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction]);
|
||||
throw new ValidationException($validator);
|
||||
throw new ValidationException($validator,0, $e);
|
||||
}
|
||||
app('preferences')->mark();
|
||||
event(new StoredTransactionGroup($transactionGroup, $data['apply_rules'] ?? true));
|
||||
|
@@ -96,7 +96,7 @@ class UpdateController extends Controller
|
||||
|
||||
$selectedGroup = $collector->getGroups()->first();
|
||||
if (null === $selectedGroup) {
|
||||
throw new NotFoundHttpException(); // @codeCoverageIgnore
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
/** @var TransactionGroupTransformer $transformer */
|
||||
$transformer = app(TransactionGroupTransformer::class);
|
||||
|
@@ -50,13 +50,9 @@ class DestroyController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CurrencyRepositoryInterface repository */
|
||||
$this->repository = app(CurrencyRepositoryInterface::class);
|
||||
$this->userRepository = app(UserRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -79,13 +75,13 @@ class DestroyController extends Controller
|
||||
|
||||
if (!$this->userRepository->hasRole($admin, 'owner')) {
|
||||
// access denied:
|
||||
throw new FireflyException('200005: You need the "owner" role to do this.'); // @codeCoverageIgnore
|
||||
throw new FireflyException('200005: You need the "owner" role to do this.');
|
||||
}
|
||||
if ($this->repository->currencyInUse($currency)) {
|
||||
throw new FireflyException('200006: Currency in use.'); // @codeCoverageIgnore
|
||||
throw new FireflyException('200006: Currency in use.');
|
||||
}
|
||||
if ($this->repository->isFallbackCurrency($currency)) {
|
||||
throw new FireflyException('200026: Currency is fallback.'); // @codeCoverageIgnore
|
||||
throw new FireflyException('200026: Currency is fallback.');
|
||||
}
|
||||
|
||||
$this->repository->destroy($currency);
|
||||
|
@@ -77,13 +77,9 @@ class ListController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CurrencyRepositoryInterface repository */
|
||||
$this->repository = app(CurrencyRepositoryInterface::class);
|
||||
$this->userRepository = app(UserRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -56,12 +56,8 @@ class ShowController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CurrencyRepositoryInterface repository */
|
||||
$this->repository = app(CurrencyRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -56,13 +56,9 @@ class StoreController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CurrencyRepositoryInterface repository */
|
||||
$this->repository = app(CurrencyRepositoryInterface::class);
|
||||
$this->userRepository = app(UserRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -56,13 +56,9 @@ class UpdateController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var CurrencyRepositoryInterface repository */
|
||||
$this->repository = app(CurrencyRepositoryInterface::class);
|
||||
$this->userRepository = app(UserRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -80,7 +80,7 @@ class StoreController extends Controller
|
||||
$admin = auth()->user();
|
||||
|
||||
if (!$this->userRepository->hasRole($admin, 'owner')) {
|
||||
throw new FireflyException('200005: You need the "owner" role to do this.'); // @codeCoverageIgnore
|
||||
throw new FireflyException('200005: You need the "owner" role to do this.');
|
||||
}
|
||||
$data = $request->getAll();
|
||||
// if currency ID is 0, find the currency by the code:
|
||||
|
@@ -86,7 +86,7 @@ class UpdateController extends Controller
|
||||
$admin = auth()->user();
|
||||
|
||||
if (!$this->userRepository->hasRole($admin, 'owner')) {
|
||||
throw new FireflyException('200005: You need the "owner" role to do this.'); // @codeCoverageIgnore
|
||||
throw new FireflyException('200005: You need the "owner" role to do this.');
|
||||
}
|
||||
|
||||
$data = $request->getAll();
|
||||
|
@@ -64,7 +64,7 @@ class ConfigurationController extends Controller
|
||||
} catch (FireflyException $e) {
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
throw new FireflyException('200030: Could not load config variables.');
|
||||
throw new FireflyException('200030: Could not load config variables.', 0, $e);
|
||||
}
|
||||
$staticData = $this->getStaticConfiguration();
|
||||
$return = [];
|
||||
@@ -161,7 +161,7 @@ class ConfigurationController extends Controller
|
||||
public function update(UpdateRequest $request, string $name): JsonResponse
|
||||
{
|
||||
if (!$this->repository->hasRole(auth()->user(), 'owner')) {
|
||||
throw new FireflyException('200005: You need the "owner" role to do this.'); // @codeCoverageIgnore
|
||||
throw new FireflyException('200005: You need the "owner" role to do this.');
|
||||
}
|
||||
$data = $request->getAll();
|
||||
$shortName = str_replace('configuration.', '', $name);
|
||||
|
@@ -54,7 +54,6 @@ class UserController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var UserRepositoryInterface repository */
|
||||
$this->repository = app(UserRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
@@ -84,7 +83,7 @@ class UserController extends Controller
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
throw new FireflyException('200025: No access to function.'); // @codeCoverageIgnore
|
||||
throw new FireflyException('200025: No access to function.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -53,12 +53,8 @@ class AttemptController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var WebhookRepositoryInterface repository */
|
||||
$this->repository = app(WebhookRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -48,12 +48,8 @@ class DestroyController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var WebhookRepositoryInterface repository */
|
||||
$this->repository = app(WebhookRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -49,12 +49,8 @@ class MessageController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var WebhookRepositoryInterface repository */
|
||||
$this->repository = app(WebhookRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -50,12 +50,8 @@ class ShowController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var WebhookRepositoryInterface repository */
|
||||
$this->repository = app(WebhookRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -47,12 +47,8 @@ class StoreController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var WebhookRepositoryInterface repository */
|
||||
$this->repository = app(WebhookRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -27,7 +27,6 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Jobs\SendWebhookMessage;
|
||||
use FireflyIII\Models\Webhook;
|
||||
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
/**
|
||||
@@ -45,12 +44,8 @@ class SubmitController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var WebhookRepositoryInterface repository */
|
||||
$this->repository = app(WebhookRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -47,12 +47,8 @@ class UpdateController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
|
||||
/** @var WebhookRepositoryInterface repository */
|
||||
$this->repository = app(WebhookRepositoryInterface::class);
|
||||
$this->repository->setUser($admin);
|
||||
$this->repository->setUser(auth()->user());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
@@ -41,7 +41,7 @@ class ApiDemoUser
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
/** @var User $user */
|
||||
/** @var User|null $user */
|
||||
$user = $request->user();
|
||||
|
||||
if (null === $user) {
|
||||
|
105
app/Api/V1/Requests/Data/Bulk/MoveTransactionsRequest.php
Normal file
105
app/Api/V1/Requests/Data/Bulk/MoveTransactionsRequest.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* MoveTransactionsRequest.php
|
||||
* Copyright (c) 2021 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\Requests\Data\Bulk;
|
||||
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
* Class MoveTransactionsRequest
|
||||
*/
|
||||
class MoveTransactionsRequest extends FormRequest
|
||||
{
|
||||
use ChecksLogin, ConvertsDataTypes;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
return [
|
||||
'original_account' => $this->integer('original_account'),
|
||||
'destination_account' => $this->integer('destination_account'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'original_account' => 'required|different:destination_account|belongsToUser:accounts,id',
|
||||
'destination_account' => 'required|different:original_account|belongsToUser:accounts,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator instance with special rules for after the basic validation rules.
|
||||
*
|
||||
* @param Validator $validator
|
||||
* TODO duplicate code.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator) {
|
||||
// validate start before end only if both are there.
|
||||
$data = $validator->getData();
|
||||
if (array_key_exists('original_account', $data) && array_key_exists('destination_account', $data)) {
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser(auth()->user());
|
||||
$original = $repository->findNull((int)$data['original_account']);
|
||||
$destination = $repository->findNull((int)$data['destination_account']);
|
||||
if ($original->accountType->type !== $destination->accountType->type) {
|
||||
$validator->errors()->add('title', (string)trans('validation.same_account_type'));
|
||||
|
||||
return;
|
||||
}
|
||||
// get currency pref:
|
||||
$originalCurrency = $repository->getAccountCurrency($original);
|
||||
$destinationCurrency = $repository->getAccountCurrency($destination);
|
||||
if (null === $originalCurrency xor null === $destinationCurrency) {
|
||||
$validator->errors()->add('title', (string)trans('validation.same_account_currency'));
|
||||
|
||||
return;
|
||||
}
|
||||
if (null === $originalCurrency && null === $destinationCurrency) {
|
||||
// this is OK
|
||||
return;
|
||||
}
|
||||
if ($originalCurrency->code !== $destinationCurrency->code) {
|
||||
$validator->errors()->add('title', (string)trans('validation.same_account_currency'));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@@ -86,9 +86,6 @@ class GenericRequest extends FormRequest
|
||||
*/
|
||||
private function parseAccounts(): void
|
||||
{
|
||||
if (null === $this->accounts) {
|
||||
$this->accounts = new Collection;
|
||||
}
|
||||
if (0 !== $this->accounts->count()) {
|
||||
return;
|
||||
}
|
||||
@@ -121,9 +118,6 @@ class GenericRequest extends FormRequest
|
||||
*/
|
||||
private function parseBills(): void
|
||||
{
|
||||
if (null === $this->bills) {
|
||||
$this->bills = new Collection;
|
||||
}
|
||||
if (0 !== $this->bills->count()) {
|
||||
return;
|
||||
}
|
||||
@@ -156,9 +150,6 @@ class GenericRequest extends FormRequest
|
||||
*/
|
||||
private function parseBudgets(): void
|
||||
{
|
||||
if (null === $this->budgets) {
|
||||
$this->budgets = new Collection;
|
||||
}
|
||||
if (0 !== $this->budgets->count()) {
|
||||
return;
|
||||
}
|
||||
@@ -191,9 +182,6 @@ class GenericRequest extends FormRequest
|
||||
*/
|
||||
private function parseCategories(): void
|
||||
{
|
||||
if (null === $this->categories) {
|
||||
$this->categories = new Collection;
|
||||
}
|
||||
if (0 !== $this->categories->count()) {
|
||||
return;
|
||||
}
|
||||
@@ -284,9 +272,6 @@ class GenericRequest extends FormRequest
|
||||
*/
|
||||
private function parseTags(): void
|
||||
{
|
||||
if (null === $this->tags) {
|
||||
$this->tags = new Collection;
|
||||
}
|
||||
if (0 !== $this->tags->count()) {
|
||||
return;
|
||||
}
|
||||
@@ -311,7 +296,7 @@ class GenericRequest extends FormRequest
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
// this is cheating but it works:
|
||||
// this is cheating but it works to initialize the collections.
|
||||
$this->accounts = new Collection;
|
||||
$this->budgets = new Collection;
|
||||
$this->categories = new Collection;
|
||||
|
@@ -59,7 +59,7 @@ class StoreRequest extends FormRequest
|
||||
'name' => $this->string('name'),
|
||||
'active' => $active,
|
||||
'include_net_worth' => $includeNetWorth,
|
||||
'account_type' => $this->string('type'),
|
||||
'account_type_name' => $this->string('type'),
|
||||
'account_type_id' => null,
|
||||
'currency_id' => $this->integer('currency_id'),
|
||||
'order' => $this->integer('order'),
|
||||
@@ -73,17 +73,17 @@ class StoreRequest extends FormRequest
|
||||
'opening_balance_date' => $this->date('opening_balance_date'),
|
||||
'cc_type' => $this->string('credit_card_type'),
|
||||
'cc_monthly_payment_date' => $this->string('monthly_payment_date'),
|
||||
'notes' => $this->nlString('notes'),
|
||||
'notes' => $this->stringWithNewlines('notes'),
|
||||
'interest' => $this->string('interest'),
|
||||
'interest_period' => $this->string('interest_period'),
|
||||
];
|
||||
// append Location information.
|
||||
$data = $this->appendLocationData($data, null);
|
||||
|
||||
if ('liability' === $data['account_type'] || 'liabilities' === $data['account_type']) {
|
||||
if ('liability' === $data['account_type_name'] || 'liabilities' === $data['account_type_name']) {
|
||||
$data['opening_balance'] = bcmul($this->string('liability_amount'), '-1');
|
||||
$data['opening_balance_date'] = $this->date('liability_start_date');
|
||||
$data['account_type'] = $this->string('liability_type');
|
||||
$data['account_type_name'] = $this->string('liability_type');
|
||||
$data['account_type_id'] = null;
|
||||
}
|
||||
|
||||
|
@@ -51,7 +51,7 @@ class UpdateRequest extends FormRequest
|
||||
'name' => ['name', 'string'],
|
||||
'active' => ['active', 'boolean'],
|
||||
'include_net_worth' => ['include_net_worth', 'boolean'],
|
||||
'account_type' => ['type', 'string'],
|
||||
'account_type_name' => ['type', 'string'],
|
||||
'virtual_balance' => ['virtual_balance', 'string'],
|
||||
'iban' => ['iban', 'string'],
|
||||
'BIC' => ['bic', 'string'],
|
||||
@@ -62,7 +62,7 @@ class UpdateRequest extends FormRequest
|
||||
'opening_balance_date' => ['opening_balance_date', 'date'],
|
||||
'cc_type' => ['credit_card_type', 'string'],
|
||||
'cc_monthly_payment_date' => ['monthly_payment_date', 'string'],
|
||||
'notes' => ['notes', 'nlString'],
|
||||
'notes' => ['notes', 'stringWithNewlines'],
|
||||
'interest' => ['interest', 'string'],
|
||||
'interest_period' => ['interest_period', 'string'],
|
||||
'order' => ['order', 'integer'],
|
||||
@@ -72,10 +72,10 @@ class UpdateRequest extends FormRequest
|
||||
$data = $this->getAllData($fields);
|
||||
$data = $this->appendLocationData($data, null);
|
||||
|
||||
if (array_key_exists('account_type', $data) && 'liability' === $data['account_type']) {
|
||||
$data['opening_balance'] = bcmul($this->nullableString('liability_amount'), '-1');
|
||||
if (array_key_exists('account_type_name', $data) && 'liability' === $data['account_type_name']) {
|
||||
$data['opening_balance'] = bcmul($this->string('liability_amount'), '-1');
|
||||
$data['opening_balance_date'] = $this->date('liability_start_date');
|
||||
$data['account_type'] = $this->nullableString('liability_type');
|
||||
$data['account_type_name'] = $this->string('liability_type');
|
||||
$data['account_type_id'] = null;
|
||||
}
|
||||
|
||||
@@ -97,9 +97,9 @@ class UpdateRequest extends FormRequest
|
||||
$rules = [
|
||||
'name' => sprintf('min:1|uniqueAccountForUser:%d', $account->id),
|
||||
'type' => sprintf('in:%s', $types),
|
||||
'iban' => ['iban', 'nullable', new UniqueIban($account, $this->nullableString('type'))],
|
||||
'iban' => ['iban', 'nullable', new UniqueIban($account, $this->string('type'))],
|
||||
'bic' => 'bic|nullable',
|
||||
'account_number' => ['between:1,255', 'nullable', new UniqueAccountNumber($account, $this->nullableString('type'))],
|
||||
'account_number' => ['between:1,255', 'nullable', new UniqueAccountNumber($account, $this->string('type'))],
|
||||
'opening_balance' => 'numeric|required_with:opening_balance_date|nullable',
|
||||
'opening_balance_date' => 'date|required_with:opening_balance|nullable',
|
||||
'virtual_balance' => 'numeric|nullable',
|
||||
|
@@ -47,7 +47,7 @@ class StoreRequest extends FormRequest
|
||||
return [
|
||||
'filename' => $this->string('filename'),
|
||||
'title' => $this->string('title'),
|
||||
'notes' => $this->nlString('notes'),
|
||||
'notes' => $this->stringWithNewlines('notes'),
|
||||
'attachable_type' => $this->string('attachable_type'),
|
||||
'attachable_id' => $this->integer('attachable_id'),
|
||||
];
|
||||
|
@@ -47,7 +47,7 @@ class UpdateRequest extends FormRequest
|
||||
$fields = [
|
||||
'filename' => ['filename', 'string'],
|
||||
'title' => ['title', 'string'],
|
||||
'notes' => ['notes', 'nlString'],
|
||||
'notes' => ['notes', 'stringWithNewlines'],
|
||||
'attachable_type' => ['attachable_type', 'string'],
|
||||
'attachable_id' => ['attachable_id', 'integer'],
|
||||
];
|
||||
|
@@ -59,7 +59,7 @@ class StoreRequest extends FormRequest
|
||||
'skip' => ['skip', 'integer'],
|
||||
'active' => ['active', 'boolean'],
|
||||
'order' => ['order', 'integer'],
|
||||
'notes' => ['notes', 'nlString'],
|
||||
'notes' => ['notes', 'stringWithNewlines'],
|
||||
'object_group_id' => ['object_group_id', 'integer'],
|
||||
'object_group_title' => ['object_group_title', 'string'],
|
||||
];
|
||||
|
@@ -57,7 +57,7 @@ class UpdateRequest extends FormRequest
|
||||
'skip' => ['skip', 'integer'],
|
||||
'active' => ['active', 'boolean'],
|
||||
'order' => ['order', 'integer'],
|
||||
'notes' => ['notes', 'nlString'],
|
||||
'notes' => ['notes', 'stringWithNewlines'],
|
||||
'object_group_id' => ['object_group_id', 'integer'],
|
||||
'object_group_title' => ['object_group_title', 'string'],
|
||||
];
|
||||
|
@@ -46,7 +46,7 @@ class StoreRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'name' => $this->string('name'),
|
||||
'notes' => $this->nlString('notes'),
|
||||
'notes' => $this->stringWithNewlines('notes'),
|
||||
];
|
||||
}
|
||||
|
||||
|
@@ -45,7 +45,7 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
$fields = [
|
||||
'name' => ['name', 'string'],
|
||||
'notes' => ['notes', 'nlString'],
|
||||
'notes' => ['notes', 'stringWithNewlines'],
|
||||
];
|
||||
|
||||
return $this->getAllData($fields);
|
||||
|
@@ -53,7 +53,7 @@ class StoreRequest extends FormRequest
|
||||
$data['current_amount'] = $this->string('current_amount');
|
||||
$data['startdate'] = $this->date('start_date');
|
||||
$data['targetdate'] = $this->date('target_date');
|
||||
$data['notes'] = $this->nlString('notes');
|
||||
$data['notes'] = $this->stringWithNewlines('notes');
|
||||
$data['object_group_id'] = $this->integer('object_group_id');
|
||||
$data['object_group_title'] = $this->string('object_group_title');
|
||||
|
||||
|
@@ -52,7 +52,7 @@ class UpdateRequest extends FormRequest
|
||||
'current_amount' => ['current_amount', 'string'],
|
||||
'startdate' => ['start_date', 'date'],
|
||||
'targetdate' => ['target_date', 'string'],
|
||||
'notes' => ['notes', 'nlString'],
|
||||
'notes' => ['notes', 'stringWithNewlines'],
|
||||
'order' => ['order', 'integer'],
|
||||
'object_group_title' => ['object_group_title', 'string'],
|
||||
'object_group_id' => ['object_group_id', 'integer'],
|
||||
|
@@ -58,7 +58,7 @@ class StoreRequest extends FormRequest
|
||||
'nr_of_repetitions' => ['nr_of_repetitions', 'integer'],
|
||||
'apply_rules' => ['apply_rules', 'boolean'],
|
||||
'active' => ['active', 'boolean'],
|
||||
'notes' => ['notes', 'nlString'],
|
||||
'notes' => ['notes', 'stringWithNewlines'],
|
||||
];
|
||||
$recurrence = $this->getAllData($fields);
|
||||
|
||||
@@ -79,7 +79,7 @@ class StoreRequest extends FormRequest
|
||||
{
|
||||
$return = [];
|
||||
// transaction data:
|
||||
/** @var array $transactions */
|
||||
/** @var array|null $transactions */
|
||||
$transactions = $this->get('transactions');
|
||||
if (null === $transactions) {
|
||||
return [];
|
||||
@@ -101,7 +101,7 @@ class StoreRequest extends FormRequest
|
||||
{
|
||||
$return = [];
|
||||
// repetition data:
|
||||
/** @var array $repetitions */
|
||||
/** @var array|null $repetitions */
|
||||
$repetitions = $this->get('repetitions');
|
||||
if (null === $repetitions) {
|
||||
return [];
|
||||
|
@@ -84,7 +84,7 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
$return = [];
|
||||
// repetition data:
|
||||
/** @var array $repetitions */
|
||||
/** @var array|null $repetitions */
|
||||
$repetitions = $this->get('repetitions');
|
||||
if (null === $repetitions) {
|
||||
return null;
|
||||
@@ -126,7 +126,7 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
$return = [];
|
||||
// transaction data:
|
||||
/** @var array $transactions */
|
||||
/** @var array|null $transactions */
|
||||
$transactions = $this->get('transactions');
|
||||
if (null === $transactions) {
|
||||
return null;
|
||||
|
@@ -47,7 +47,7 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
$fields = [
|
||||
'title' => ['title', 'string'],
|
||||
'description' => ['description', 'nlString'],
|
||||
'description' => ['description', 'stringWithNewlines'],
|
||||
'rule_group_id' => ['rule_group_id', 'integer'],
|
||||
'trigger' => ['trigger', 'string'],
|
||||
'strict' => ['strict', 'boolean'],
|
||||
|
@@ -46,7 +46,7 @@ class UpdateRequest extends FormRequest
|
||||
// This is the way.
|
||||
$fields = [
|
||||
'title' => ['title', 'string'],
|
||||
'description' => ['description', 'nlString'],
|
||||
'description' => ['description', 'stringWithNewlines'],
|
||||
'active' => ['active', 'boolean'],
|
||||
'order' => ['order', 'integer'],
|
||||
];
|
||||
|
@@ -78,75 +78,75 @@ class StoreRequest extends FormRequest
|
||||
foreach ($this->get('transactions') as $transaction) {
|
||||
$object = new NullArrayObject($transaction);
|
||||
$return[] = [
|
||||
'type' => $this->stringFromValue($object['type']),
|
||||
'type' => $this->clearString($object['type'], false),
|
||||
'date' => $this->dateFromValue($object['date']),
|
||||
'order' => $this->integerFromValue((string)$object['order']),
|
||||
|
||||
'currency_id' => $this->integerFromValue((string)$object['currency_id']),
|
||||
'currency_code' => $this->stringFromValue($object['currency_code']),
|
||||
'currency_code' => $this->clearString((string)$object['currency_code'], false),
|
||||
|
||||
// foreign currency info:
|
||||
'foreign_currency_id' => $this->integerFromValue((string)$object['foreign_currency_id']),
|
||||
'foreign_currency_code' => $this->stringFromValue((string)$object['foreign_currency_code']),
|
||||
'foreign_currency_code' => $this->clearString((string)$object['foreign_currency_code'], false),
|
||||
|
||||
// amount and foreign amount. Cannot be 0.
|
||||
'amount' => $this->stringFromValue((string)$object['amount']),
|
||||
'foreign_amount' => $this->stringFromValue((string)$object['foreign_amount']),
|
||||
'amount' => $this->clearString((string)$object['amount'], false),
|
||||
'foreign_amount' => $this->clearString((string)$object['foreign_amount'], false),
|
||||
|
||||
// description.
|
||||
'description' => $this->stringFromValue($object['description']),
|
||||
'description' => $this->clearString($object['description'], false),
|
||||
|
||||
// source of transaction. If everything is null, assume cash account.
|
||||
'source_id' => $this->integerFromValue((string)$object['source_id']),
|
||||
'source_name' => $this->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']),
|
||||
'source_name' => $this->clearString($object['source_name'], false),
|
||||
'source_iban' => $this->clearString($object['source_iban'], false),
|
||||
'source_number' => $this->clearString($object['source_number'], false),
|
||||
'source_bic' => $this->clearString($object['source_bic'], false),
|
||||
|
||||
// destination of transaction. If everything is null, assume cash account.
|
||||
'destination_id' => $this->integerFromValue((string)$object['destination_id']),
|
||||
'destination_name' => $this->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']),
|
||||
'destination_name' => $this->clearString($object['destination_name'], false),
|
||||
'destination_iban' => $this->clearString($object['destination_iban'], false),
|
||||
'destination_number' => $this->clearString($object['destination_number'], false),
|
||||
'destination_bic' => $this->clearString($object['destination_bic'], false),
|
||||
|
||||
// budget info
|
||||
'budget_id' => $this->integerFromValue((string)$object['budget_id']),
|
||||
'budget_name' => $this->stringFromValue((string)$object['budget_name']),
|
||||
'budget_name' => $this->clearString((string)$object['budget_name'], false),
|
||||
|
||||
// category info
|
||||
'category_id' => $this->integerFromValue((string)$object['category_id']),
|
||||
'category_name' => $this->stringFromValue((string)$object['category_name']),
|
||||
'category_name' => $this->clearString((string)$object['category_name'], false),
|
||||
|
||||
// journal bill reference. Optional. Will only work for withdrawals
|
||||
'bill_id' => $this->integerFromValue((string)$object['bill_id']),
|
||||
'bill_name' => $this->stringFromValue((string)$object['bill_name']),
|
||||
'bill_name' => $this->clearString((string)$object['bill_name'], false),
|
||||
|
||||
// piggy bank reference. Optional. Will only work for transfers
|
||||
'piggy_bank_id' => $this->integerFromValue((string)$object['piggy_bank_id']),
|
||||
'piggy_bank_name' => $this->stringFromValue((string)$object['piggy_bank_name']),
|
||||
'piggy_bank_name' => $this->clearString((string)$object['piggy_bank_name'], false),
|
||||
|
||||
// some other interesting properties
|
||||
'reconciled' => $this->convertBoolean((string)$object['reconciled']),
|
||||
'notes' => $this->nlStringFromValue((string)$object['notes']),
|
||||
'notes' => $this->clearString((string)$object['notes']),
|
||||
'tags' => $this->arrayFromValue($object['tags']),
|
||||
|
||||
// all custom fields:
|
||||
'internal_reference' => $this->stringFromValue((string)$object['internal_reference']),
|
||||
'external_id' => $this->stringFromValue((string)$object['external_id']),
|
||||
'internal_reference' => $this->clearString((string)$object['internal_reference'], false),
|
||||
'external_id' => $this->clearString((string)$object['external_id'], false),
|
||||
'original_source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')),
|
||||
'recurrence_id' => $this->integerFromValue($object['recurrence_id']),
|
||||
'bunq_payment_id' => $this->stringFromValue((string)$object['bunq_payment_id']),
|
||||
'external_uri' => $this->stringFromValue((string)$object['external_uri']),
|
||||
'bunq_payment_id' => $this->clearString((string)$object['bunq_payment_id'], false),
|
||||
'external_uri' => $this->clearString((string)$object['external_uri'], false),
|
||||
|
||||
'sepa_cc' => $this->stringFromValue($object['sepa_cc']),
|
||||
'sepa_ct_op' => $this->stringFromValue($object['sepa_ct_op']),
|
||||
'sepa_ct_id' => $this->stringFromValue($object['sepa_ct_id']),
|
||||
'sepa_db' => $this->stringFromValue($object['sepa_db']),
|
||||
'sepa_country' => $this->stringFromValue($object['sepa_country']),
|
||||
'sepa_ep' => $this->stringFromValue($object['sepa_ep']),
|
||||
'sepa_ci' => $this->stringFromValue($object['sepa_ci']),
|
||||
'sepa_batch_id' => $this->stringFromValue($object['sepa_batch_id']),
|
||||
'sepa_cc' => $this->clearString((string)$object['sepa_cc'], false),
|
||||
'sepa_ct_op' => $this->clearString((string)$object['sepa_ct_op'], false),
|
||||
'sepa_ct_id' => $this->clearString((string)$object['sepa_ct_id'], false),
|
||||
'sepa_db' => $this->clearString((string)$object['sepa_db'], false),
|
||||
'sepa_country' => $this->clearString((string)$object['sepa_country'], false),
|
||||
'sepa_ep' => $this->clearString((string)$object['sepa_ep'], false),
|
||||
'sepa_ci' => $this->clearString((string)$object['sepa_ci'], false),
|
||||
'sepa_batch_id' => $this->clearString((string)$object['sepa_batch_id'], false),
|
||||
// custom date fields. Must be Carbon objects. Presence is optional.
|
||||
'interest_date' => $this->dateFromValue($object['interest_date']),
|
||||
'book_date' => $this->dateFromValue($object['book_date']),
|
||||
|
@@ -150,10 +150,7 @@ class UpdateRequest extends FormRequest
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var int $index
|
||||
* @var array $transaction
|
||||
*/
|
||||
/** @var array $transaction */
|
||||
foreach ($this->get('transactions') as $transaction) {
|
||||
// default response is to update nothing in the transaction:
|
||||
$current = [];
|
||||
@@ -197,7 +194,7 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
foreach ($this->stringFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->stringFromValue((string)$transaction[$fieldName]);
|
||||
$current[$fieldName] = $this->clearString((string)$transaction[$fieldName], false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +211,7 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
foreach ($this->textareaFields as $fieldName) {
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$current[$fieldName] = $this->nlStringFromValue((string)$transaction[$fieldName]);
|
||||
$current[$fieldName] = $this->clearString((string)$transaction[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -50,7 +50,7 @@ class StoreRequest extends FormRequest
|
||||
'link_type_name' => $this->string('link_type_name'),
|
||||
'inward_id' => $this->integer('inward_id'),
|
||||
'outward_id' => $this->integer('outward_id'),
|
||||
'notes' => $this->nlString('notes'),
|
||||
'notes' => $this->stringWithNewlines('notes'),
|
||||
];
|
||||
}
|
||||
|
||||
|
@@ -50,7 +50,7 @@ class UpdateRequest extends FormRequest
|
||||
'link_type_name' => $this->string('link_type_name'),
|
||||
'inward_id' => $this->integer('inward_id'),
|
||||
'outward_id' => $this->integer('outward_id'),
|
||||
'notes' => $this->nullableNlString('notes'),
|
||||
'notes' => $this->stringWithNewlines('notes'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -117,12 +117,6 @@ class UpdateRequest extends FormRequest
|
||||
$validator->errors()->add('outward_id', 'Inward ID must be different from outward ID.');
|
||||
}
|
||||
|
||||
if (null === $inward) {
|
||||
$validator->errors()->add('inward_id', 'This is not a valid inward journal.');
|
||||
}
|
||||
if (null === $outward) {
|
||||
$validator->errors()->add('inward_id', 'This is not a valid outward journal.');
|
||||
}
|
||||
$inDB = $repository->findSpecificLink($existing->linkType, $inward, $outward);
|
||||
if (null === $inDB) {
|
||||
return;
|
||||
|
@@ -57,7 +57,7 @@ class UpdateRequest extends FormRequest
|
||||
return ['value' => $this->integer('value')];
|
||||
}
|
||||
|
||||
return ['value' => $this->string('value')]; // @codeCoverageIgnore
|
||||
return ['value' => $this->string('value')];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,6 +80,6 @@ class UpdateRequest extends FormRequest
|
||||
return ['value' => 'required|numeric|min:464272080'];
|
||||
}
|
||||
|
||||
return ['value' => 'required']; // @codeCoverageIgnore
|
||||
return ['value' => 'required'];
|
||||
}
|
||||
}
|
||||
|
@@ -77,11 +77,11 @@ class DeleteEmptyJournals extends Command
|
||||
// uneven number, delete journal and transactions:
|
||||
try {
|
||||
TransactionJournal::find((int)$row->transaction_journal_id)->delete();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
|
||||
} catch (Exception $e) { // @phpstan-ignore-line
|
||||
Log::info(sprintf('Could not delete journal: %s', $e->getMessage()));
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
Transaction::where('transaction_journal_id', (int)$row->transaction_journal_id)->delete();
|
||||
$this->info(sprintf('Deleted transaction journal #%d because it had an uneven number of transactions.', $row->transaction_journal_id));
|
||||
@@ -105,11 +105,11 @@ class DeleteEmptyJournals extends Command
|
||||
foreach ($set as $entry) {
|
||||
try {
|
||||
TransactionJournal::find($entry->id)->delete();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
|
||||
} catch (Exception $e) { // @phpstan-ignore-line
|
||||
Log::info(sprintf('Could not delete entry: %s', $e->getMessage()));
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
$this->info(sprintf('Deleted empty transaction journal #%d', $entry->id));
|
||||
++$count;
|
||||
|
@@ -118,11 +118,11 @@ class DeleteOrphanedTransactions extends Command
|
||||
if ($journal) {
|
||||
try {
|
||||
$journal->delete();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
|
||||
} catch (Exception $e) { // @phpstan-ignore-line
|
||||
Log::info(sprintf('Could not delete journal %s', $e->getMessage()));
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
}
|
||||
Transaction::where('transaction_journal_id', (int)$transaction->transaction_journal_id)->delete();
|
||||
$this->line(
|
||||
|
@@ -64,11 +64,11 @@ class DeleteZeroAmount extends Command
|
||||
$this->info(sprintf('Deleted transaction journal #%d because the amount is zero (0.00).', $journal->id));
|
||||
try {
|
||||
$journal->delete();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
|
||||
} catch (Exception $e) { // @phpstan-ignore-line
|
||||
$this->line($e->getMessage());
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
Transaction::where('transaction_journal_id', $journal->id)->delete();
|
||||
}
|
||||
if (0 === $journals->count()) {
|
||||
|
@@ -121,12 +121,12 @@ class FixAccountTypes extends Command
|
||||
$destAccountType = $destAccount->accountType->type;
|
||||
|
||||
if (!array_key_exists($type, $this->expected)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
Log::info(sprintf('No source/destination info for transaction type %s.', $type));
|
||||
$this->info(sprintf('No source/destination info for transaction type %s.', $type));
|
||||
|
||||
return;
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
}
|
||||
if (!array_key_exists($sourceAccountType, $this->expected[$type])) {
|
||||
Log::debug(sprintf('Going to fix journal #%d', $journal->id));
|
||||
|
@@ -70,14 +70,14 @@ class FixPiggies extends Command
|
||||
}
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = $event->transactionJournal;
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if (null === $journal) {
|
||||
$event->transaction_journal_id = null;
|
||||
$event->save();
|
||||
$this->count++;
|
||||
continue;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
$type = $journal->transactionType->type;
|
||||
if (TransactionType::TRANSFER !== $type) {
|
||||
|
@@ -91,7 +91,7 @@ class FixUnevenAmount extends Command
|
||||
// one of the transactions is bad.
|
||||
$journal = TransactionJournal::find($param);
|
||||
if (!$journal) {
|
||||
return; // @codeCoverageIgnore
|
||||
return;
|
||||
}
|
||||
/** @var Transaction $source */
|
||||
$source = $journal->transactions()->where('amount', '<', 0)->first();
|
||||
|
@@ -188,7 +188,7 @@ class DecryptDatabase extends Command
|
||||
$value = Crypt::decrypt($value);
|
||||
} catch (DecryptException $e) {
|
||||
if ('The MAC is invalid.' === $e->getMessage()) {
|
||||
throw new FireflyException($e->getMessage()); // @codeCoverageIgnore
|
||||
throw new FireflyException($e->getMessage(), 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -124,11 +124,11 @@ class ExportData extends Command
|
||||
$exporter->setExportBills($options['export']['bills']);
|
||||
$exporter->setExportPiggies($options['export']['piggies']);
|
||||
$data = $exporter->export();
|
||||
if (empty($data)) {
|
||||
if (0 === count($data)) {
|
||||
$this->error('You must export *something*. Use --export-transactions or another option. See docs.firefly-iii.org');
|
||||
}
|
||||
$returnCode = 0;
|
||||
if (!empty($data)) {
|
||||
if (0 !== count($data)) {
|
||||
try {
|
||||
$this->exportData($options, $data);
|
||||
app('telemetry')->feature('system.command.executed', $this->signature);
|
||||
@@ -162,8 +162,9 @@ class ExportData extends Command
|
||||
*/
|
||||
private function parseOptions(): array
|
||||
{
|
||||
$start = $this->getDateParameter('start');
|
||||
$end = $this->getDateParameter('end');
|
||||
$start = $this->getDateParameter('start');
|
||||
$end = $this->getDateParameter('end');
|
||||
exit;
|
||||
$accounts = $this->getAccountsParameter();
|
||||
$export = $this->getExportDirectory();
|
||||
|
||||
@@ -199,24 +200,27 @@ class ExportData extends Command
|
||||
$error = false;
|
||||
if (null !== $this->option($field)) {
|
||||
try {
|
||||
$date = Carbon::createFromFormat('Y-m-d', $this->option($field));
|
||||
$date = Carbon::createFromFormat('!Y-m-d', $this->option($field));
|
||||
} catch (InvalidArgumentException $e) {
|
||||
Log::error($e->getMessage());
|
||||
$this->error(sprintf('%s date "%s" must be formatted YYYY-MM-DD. Field will be ignored.', $field, $this->option('start')));
|
||||
$error = true;
|
||||
}
|
||||
}
|
||||
if (false === $error && 'start' === $field) {
|
||||
|
||||
if (true === $error && 'start' === $field) {
|
||||
$journal = $this->journalRepository->firstNull();
|
||||
$date = null === $journal ? Carbon::now()->subYear() : $journal->date;
|
||||
$date->startOfDay();
|
||||
}
|
||||
if (false === $error && 'end' === $field) {
|
||||
if (true === $error && 'end' === $field) {
|
||||
$date = today(config('app.timezone'));
|
||||
$date->endOfDay();
|
||||
}
|
||||
if ('end' === $field) {
|
||||
$date->endOfDay();
|
||||
}
|
||||
|
||||
// fallback
|
||||
return $date;
|
||||
}
|
||||
|
||||
|
@@ -214,14 +214,6 @@ class ApplyRules extends Command
|
||||
$finalList = new Collection;
|
||||
$accountList = explode(',', $accountString);
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
if (0 === count($accountList)) {
|
||||
$this->error('Please use the --accounts option to indicate the accounts to apply rules to.');
|
||||
|
||||
return false;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
/** @var AccountRepositoryInterface $accountRepository */
|
||||
$accountRepository = app(AccountRepositoryInterface::class);
|
||||
$accountRepository->setUser($this->getUser());
|
||||
@@ -255,12 +247,7 @@ class ApplyRules extends Command
|
||||
return true;
|
||||
}
|
||||
$ruleGroupList = explode(',', $ruleGroupString);
|
||||
// @codeCoverageIgnoreStart
|
||||
if (0 === count($ruleGroupList)) {
|
||||
// can be empty.
|
||||
return true;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
foreach ($ruleGroupList as $ruleGroupId) {
|
||||
$ruleGroup = $this->ruleGroupRepository->find((int)$ruleGroupId);
|
||||
if ($ruleGroup->active) {
|
||||
@@ -286,14 +273,6 @@ class ApplyRules extends Command
|
||||
}
|
||||
$ruleList = explode(',', $ruleString);
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
if (0 === count($ruleList)) {
|
||||
// can be empty.
|
||||
|
||||
return true;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
foreach ($ruleList as $ruleId) {
|
||||
$rule = $this->ruleRepository->find((int)$ruleId);
|
||||
if (null !== $rule && $rule->active) {
|
||||
|
@@ -65,9 +65,8 @@ class Cron extends Command
|
||||
$date = null;
|
||||
try {
|
||||
$date = new Carbon($this->option('date'));
|
||||
} catch (InvalidArgumentException | Exception $e) {
|
||||
} catch (InvalidArgumentException $e) {
|
||||
$this->error(sprintf('"%s" is not a valid date', $this->option('date')));
|
||||
$e->getMessage();
|
||||
}
|
||||
$force = (bool)$this->option('force');
|
||||
|
||||
@@ -127,13 +126,15 @@ class Cron extends Command
|
||||
$recurring->setDate($date);
|
||||
}
|
||||
|
||||
$result = $recurring->fire();
|
||||
|
||||
if (false === $result) {
|
||||
$this->line('The recurring transaction cron job did not fire.');
|
||||
$recurring->fire();
|
||||
if($recurring->jobErrored) {
|
||||
$this->error(sprintf('Error in "create recurring transactions" cron: %s', $recurring->message));
|
||||
}
|
||||
if (true === $result) {
|
||||
$this->line('The recurring transaction cron job fired successfully.');
|
||||
if($recurring->jobFired) {
|
||||
$this->error(sprintf('"Create recurring transactions" cron fired: %s', $recurring->message));
|
||||
}
|
||||
if($recurring->jobSucceeded) {
|
||||
$this->error(sprintf('"Create recurring transactions" cron ran with success: %s', $recurring->message));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +143,6 @@ class Cron extends Command
|
||||
* @param Carbon|null $date
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws Exception
|
||||
*/
|
||||
private function autoBudgetCronJob(bool $force, ?Carbon $date): void
|
||||
{
|
||||
@@ -153,13 +153,16 @@ class Cron extends Command
|
||||
$autoBudget->setDate($date);
|
||||
}
|
||||
|
||||
$result = $autoBudget->fire();
|
||||
$autoBudget->fire();
|
||||
|
||||
if (false === $result) {
|
||||
$this->line('The auto budget cron job did not fire.');
|
||||
if($autoBudget->jobErrored) {
|
||||
$this->error(sprintf('Error in "create auto budgets" cron: %s', $autoBudget->message));
|
||||
}
|
||||
if (true === $result) {
|
||||
$this->line('The auto budget cron job fired successfully.');
|
||||
if($autoBudget->jobFired) {
|
||||
$this->error(sprintf('"Create auto budgets" cron fired: %s', $autoBudget->message));
|
||||
}
|
||||
if($autoBudget->jobSucceeded) {
|
||||
$this->error(sprintf('"Create auto budgets" cron ran with success: %s', $autoBudget->message));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -167,6 +170,8 @@ class Cron extends Command
|
||||
/**
|
||||
* @param bool $force
|
||||
* @param Carbon|null $date
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function telemetryCronJob(bool $force, ?Carbon $date): void
|
||||
{
|
||||
@@ -182,13 +187,16 @@ class Cron extends Command
|
||||
$telemetry->setDate($date);
|
||||
}
|
||||
|
||||
$result = $telemetry->fire();
|
||||
$telemetry->fire();
|
||||
|
||||
if (false === $result) {
|
||||
$this->line('The telemetry cron job did not fire.');
|
||||
if($telemetry->jobErrored) {
|
||||
$this->error(sprintf('Error in "send telemetry" cron: %s', $telemetry->message));
|
||||
}
|
||||
if (true === $result) {
|
||||
$this->line('The telemetry cron job fired successfully.');
|
||||
if($telemetry->jobFired) {
|
||||
$this->error(sprintf('"Send telemetry" cron fired: %s', $telemetry->message));
|
||||
}
|
||||
if($telemetry->jobSucceeded) {
|
||||
$this->error(sprintf('"Send telemetry" cron ran with success: %s', $telemetry->message));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -114,7 +114,7 @@ class AccountCurrencies extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,7 +148,7 @@ class AccountCurrencies extends Command
|
||||
}
|
||||
Log::debug(sprintf('Users currency pref is %s', $defaultCurrencyCode));
|
||||
|
||||
/** @var TransactionCurrency $defaultCurrency */
|
||||
/** @var TransactionCurrency|null $defaultCurrency */
|
||||
$defaultCurrency = TransactionCurrency::where('code', $defaultCurrencyCode)->first();
|
||||
|
||||
if (null === $defaultCurrency) {
|
||||
|
@@ -73,11 +73,8 @@ class AppendBudgetLimitPeriods extends Command
|
||||
private function isExecuted(): bool
|
||||
{
|
||||
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
|
||||
if (null !== $configVar) {
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -58,7 +58,7 @@ class BackToJournals extends Command
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
$start = microtime(true);
|
||||
if (!$this->isMigrated()) {
|
||||
$this->error('Please run firefly-iii:migrate-to-groups first.');
|
||||
@@ -71,7 +71,7 @@ class BackToJournals extends Command
|
||||
if (true === $this->option('force')) {
|
||||
$this->warn('Forcing the command.');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
$this->migrateAll();
|
||||
$end = round(microtime(true) - $start, 2);
|
||||
@@ -87,11 +87,8 @@ class BackToJournals extends Command
|
||||
private function isMigrated(): bool
|
||||
{
|
||||
$configVar = app('fireflyconfig')->get(MigrateToGroups::CONFIG_NAME, false);
|
||||
if (null !== $configVar) {
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,11 +97,8 @@ class BackToJournals extends Command
|
||||
private function isExecuted(): bool
|
||||
{
|
||||
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
|
||||
if (null !== $configVar) {
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,15 +139,13 @@ class BackToJournals extends Command
|
||||
*/
|
||||
private function getIdsForBudgets(): array
|
||||
{
|
||||
$transactions = DB::table('budget_transaction')->distinct()->get(['transaction_id'])->pluck('transaction_id')->toArray();
|
||||
$transactions = DB::table('budget_transaction')->distinct()->get(['transaction_id'])->pluck('transaction_id')->toArray(); // @phpstan-ignore-line
|
||||
$array = [];
|
||||
$chunks = array_chunk($transactions, 500);
|
||||
|
||||
foreach ($chunks as $chunk) {
|
||||
$set = DB::table('transactions')
|
||||
->whereIn('transactions.id', $chunk)
|
||||
$set = DB::table('transactions')->whereIn('transactions.id', $chunk)
|
||||
->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
|
||||
/** @noinspection SlowArrayOperationsInLoopInspection */
|
||||
$array = array_merge($array, $set);
|
||||
}
|
||||
|
||||
@@ -170,11 +162,11 @@ class BackToJournals extends Command
|
||||
/** @var Transaction $transaction */
|
||||
$transaction = $journal->transactions->first();
|
||||
if (null === $transaction) {
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
$this->info(sprintf('Transaction journal #%d has no transactions. Will be fixed later.', $journal->id));
|
||||
|
||||
return;
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
}
|
||||
/** @var Budget $budget */
|
||||
$budget = $transaction->budgets->first();
|
||||
@@ -225,12 +217,12 @@ class BackToJournals extends Command
|
||||
*/
|
||||
private function getIdsForCategories(): array
|
||||
{
|
||||
$transactions = DB::table('category_transaction')->distinct()->get(['transaction_id'])->pluck('transaction_id')->toArray();
|
||||
$transactions = DB::table('category_transaction')->distinct()->get(['transaction_id'])->pluck('transaction_id')->toArray(); // @phpstan-ignore-line
|
||||
$array = [];
|
||||
$chunks = array_chunk($transactions, 500);
|
||||
|
||||
foreach ($chunks as $chunk) {
|
||||
$set = DB::table('transactions')
|
||||
$set = DB::table('transactions') // @phpstan-ignore-line
|
||||
->whereIn('transactions.id', $chunk)
|
||||
->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
|
||||
/** @noinspection SlowArrayOperationsInLoopInspection */
|
||||
@@ -249,11 +241,11 @@ class BackToJournals extends Command
|
||||
/** @var Transaction $transaction */
|
||||
$transaction = $journal->transactions->first();
|
||||
if (null === $transaction) {
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
$this->info(sprintf('Transaction journal #%d has no transactions. Will be fixed later.', $journal->id));
|
||||
|
||||
return;
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
}
|
||||
/** @var Category $category */
|
||||
$category = $transaction->categories->first();
|
||||
|
@@ -54,13 +54,13 @@ class BudgetLimitCurrency extends Command
|
||||
public function handle(): int
|
||||
{
|
||||
$start = microtime(true);
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if ($this->isExecuted() && true !== $this->option('force')) {
|
||||
$this->warn('This command has already been executed.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
$count = 0;
|
||||
$budgetLimits = BudgetLimit::get();
|
||||
@@ -104,7 +104,7 @@ class BudgetLimitCurrency extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -56,13 +56,13 @@ class CCLiabilities extends Command
|
||||
{
|
||||
$start = microtime(true);
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if ($this->isExecuted() && true !== $this->option('force')) {
|
||||
$this->warn('This command has already been executed.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
$ccType = AccountType::where('type', AccountType::CREDITCARD)->first();
|
||||
$debtType = AccountType::where('type', AccountType::DEBT)->first();
|
||||
@@ -101,7 +101,7 @@ class CCLiabilities extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -54,14 +54,14 @@ class MigrateAttachments extends Command
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
$start = microtime(true);
|
||||
if ($this->isExecuted() && true !== $this->option('force')) {
|
||||
$this->warn('This command has already been executed.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
$attachments = Attachment::get();
|
||||
$count = 0;
|
||||
@@ -113,7 +113,7 @@ class MigrateAttachments extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -56,13 +56,13 @@ class MigrateJournalNotes extends Command
|
||||
public function handle(): int
|
||||
{
|
||||
$start = microtime(true);
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if ($this->isExecuted() && true !== $this->option('force')) {
|
||||
$this->warn('This command has already been executed.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$count = 0;
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$set = TransactionJournalMeta::whereName('notes')->get();
|
||||
@@ -80,11 +80,11 @@ class MigrateJournalNotes extends Command
|
||||
Log::debug(sprintf('Migrated meta note #%d to Note #%d', $meta->id, $note->id));
|
||||
try {
|
||||
$meta->delete();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Exception $e) {
|
||||
|
||||
} catch (Exception $e) { // @phpstan-ignore-line
|
||||
Log::error(sprintf('Could not delete old meta entry #%d: %s', $meta->id, $e->getMessage()));
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$count++;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ class MigrateJournalNotes extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -87,7 +87,7 @@ class MigrateRecurrenceMeta extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -82,7 +82,7 @@ class MigrateRecurrenceType extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -80,7 +80,7 @@ class MigrateTagLocations extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
private function migrateTagLocations(): void
|
||||
|
@@ -75,7 +75,7 @@ class MigrateToGroups extends Command
|
||||
{
|
||||
$this->stupidLaravel();
|
||||
$start = microtime(true);
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if ($this->isMigrated() && true !== $this->option('force')) {
|
||||
$this->info('Database already seems to be migrated.');
|
||||
|
||||
@@ -85,7 +85,7 @@ class MigrateToGroups extends Command
|
||||
if (true === $this->option('force')) {
|
||||
$this->warn('Forcing the migration.');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
Log::debug('---- start group migration ----');
|
||||
$this->makeGroupsFromSplitJournals();
|
||||
@@ -135,7 +135,7 @@ class MigrateToGroups extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,11 +165,11 @@ class MigrateToGroups extends Command
|
||||
{
|
||||
// double check transaction count.
|
||||
if ($journal->transactions->count() <= 2) {
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
Log::debug(sprintf('Will not try to convert journal #%d because it has 2 or less transactions.', $journal->id));
|
||||
|
||||
return;
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
}
|
||||
Log::debug(sprintf('Will now try to convert journal #%d', $journal->id));
|
||||
|
||||
@@ -217,7 +217,7 @@ class MigrateToGroups extends Command
|
||||
$opposingTr = $this->findOpposingTransaction($journal, $transaction);
|
||||
|
||||
if (null === $opposingTr) {
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
$this->error(
|
||||
sprintf(
|
||||
'Journal #%d has no opposing transaction for transaction #%d. Cannot upgrade this entry.',
|
||||
@@ -226,7 +226,7 @@ class MigrateToGroups extends Command
|
||||
)
|
||||
);
|
||||
continue;
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
}
|
||||
|
||||
// overrule journal category with transaction category.
|
||||
|
@@ -73,13 +73,13 @@ class MigrateToRules extends Command
|
||||
$this->stupidLaravel();
|
||||
$start = microtime(true);
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if ($this->isExecuted() && true !== $this->option('force')) {
|
||||
$this->warn('This command has already been executed.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
$users = $this->userRepository->all();
|
||||
/** @var User $user */
|
||||
@@ -127,7 +127,7 @@ class MigrateToRules extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -75,13 +75,13 @@ class OtherCurrenciesCorrections extends Command
|
||||
{
|
||||
$this->stupidLaravel();
|
||||
$start = microtime(true);
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if ($this->isExecuted() && true !== $this->option('force')) {
|
||||
$this->warn('This command has already been executed.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
$this->updateOtherJournalsCurrencies();
|
||||
$this->markAsExecuted();
|
||||
@@ -120,7 +120,7 @@ class OtherCurrenciesCorrections extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,18 +154,18 @@ class OtherCurrenciesCorrections extends Command
|
||||
$leadTransaction = $this->getLeadTransaction($journal);
|
||||
|
||||
if (null === $leadTransaction) {
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
$this->error(sprintf('Could not reliably determine which transaction is in the lead for transaction journal #%d.', $journal->id));
|
||||
|
||||
return;
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
}
|
||||
|
||||
/** @var Account $account */
|
||||
$account = $leadTransaction->account;
|
||||
$currency = $this->getCurrency($account);
|
||||
if (null === $currency) {
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
$this->error(
|
||||
sprintf(
|
||||
'Account #%d ("%s") has no currency preference, so transaction journal #%d can\'t be corrected', $account->id, $account->name, $journal->id
|
||||
@@ -174,7 +174,7 @@ class OtherCurrenciesCorrections extends Command
|
||||
$this->count++;
|
||||
|
||||
return;
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
}
|
||||
// fix each transaction:
|
||||
$journal->transactions->each(
|
||||
@@ -246,18 +246,18 @@ class OtherCurrenciesCorrections extends Command
|
||||
{
|
||||
$accountId = $account->id;
|
||||
if (array_key_exists($accountId, $this->accountCurrencies) && 0 === $this->accountCurrencies[$accountId]) {
|
||||
return null; // @codeCoverageIgnore
|
||||
return null;
|
||||
}
|
||||
if (array_key_exists($accountId, $this->accountCurrencies) && $this->accountCurrencies[$accountId] instanceof TransactionCurrency) {
|
||||
return $this->accountCurrencies[$accountId]; // @codeCoverageIgnore
|
||||
return $this->accountCurrencies[$accountId];
|
||||
}
|
||||
$currency = $this->accountRepos->getAccountCurrency($account);
|
||||
if (null === $currency) {
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
$this->accountCurrencies[$accountId] = 0;
|
||||
|
||||
return null;
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
}
|
||||
$this->accountCurrencies[$accountId] = $currency;
|
||||
|
||||
|
@@ -53,13 +53,13 @@ class RenameAccountMeta extends Command
|
||||
public function handle(): int
|
||||
{
|
||||
$start = microtime(true);
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if ($this->isExecuted() && true !== $this->option('force')) {
|
||||
$this->warn('This command has already been executed.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$array = [
|
||||
'accountRole' => 'account_role',
|
||||
'ccType' => 'cc_type',
|
||||
@@ -104,7 +104,7 @@ class RenameAccountMeta extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -72,7 +72,7 @@ class TransactionIdentifier extends Command
|
||||
{
|
||||
$this->stupidLaravel();
|
||||
$start = microtime(true);
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if ($this->isExecuted() && true !== $this->option('force')) {
|
||||
$this->warn('This command has already been executed.');
|
||||
|
||||
@@ -83,7 +83,7 @@ class TransactionIdentifier extends Command
|
||||
if (!Schema::hasTable('transaction_journals')) {
|
||||
return 0;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$journals = $this->cliRepository->getSplitJournals();
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($journals as $journal) {
|
||||
@@ -128,7 +128,7 @@ class TransactionIdentifier extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,7 +178,7 @@ class TransactionIdentifier extends Command
|
||||
->where('amount', $amount)->where('identifier', '=', 0)
|
||||
->whereNotIn('id', $exclude)
|
||||
->first();
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
} catch (QueryException $e) {
|
||||
Log::error($e->getMessage());
|
||||
$this->error('Firefly III could not find the "identifier" field in the "transactions" table.');
|
||||
@@ -188,9 +188,6 @@ class TransactionIdentifier extends Command
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
return $opposing;
|
||||
}
|
||||
|
||||
|
@@ -72,13 +72,13 @@ class TransferCurrenciesCorrections extends Command
|
||||
{
|
||||
$this->stupidLaravel();
|
||||
$start = microtime(true);
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if ($this->isExecuted() && true !== $this->option('force')) {
|
||||
$this->warn('This command has already been executed.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
$this->startUpdateRoutine();
|
||||
$this->markAsExecuted();
|
||||
@@ -140,7 +140,7 @@ class TransferCurrenciesCorrections extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,27 +167,27 @@ class TransferCurrenciesCorrections extends Command
|
||||
{
|
||||
$this->resetInformation();
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if ($this->isSplitJournal($transfer)) {
|
||||
$this->line(sprintf(sprintf('Transaction journal #%d is a split journal. Cannot continue.', $transfer->id)));
|
||||
|
||||
return;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
$this->getSourceInformation($transfer);
|
||||
$this->getDestinationInformation($transfer);
|
||||
|
||||
// unexpectedly, either one is null:
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if ($this->isEmptyTransactions()) {
|
||||
$this->error(sprintf('Source or destination information for transaction journal #%d is null. Cannot fix this one.', $transfer->id));
|
||||
|
||||
return;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
// both accounts must have currency preference:
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
if ($this->isNoCurrencyPresent()) {
|
||||
$this->error(
|
||||
sprintf('Source or destination accounts for transaction journal #%d have no currency information. Cannot fix this one.', $transfer->id)
|
||||
@@ -195,7 +195,7 @@ class TransferCurrenciesCorrections extends Command
|
||||
|
||||
return;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
|
||||
// fix source transaction having no currency.
|
||||
$this->fixSourceNoCurrency();
|
||||
@@ -270,18 +270,18 @@ class TransferCurrenciesCorrections extends Command
|
||||
{
|
||||
$accountId = $account->id;
|
||||
if (array_key_exists($accountId, $this->accountCurrencies) && 0 === $this->accountCurrencies[$accountId]) {
|
||||
return null; // @codeCoverageIgnore
|
||||
return null;
|
||||
}
|
||||
if (array_key_exists($accountId, $this->accountCurrencies) && $this->accountCurrencies[$accountId] instanceof TransactionCurrency) {
|
||||
return $this->accountCurrencies[$accountId]; // @codeCoverageIgnore
|
||||
return $this->accountCurrencies[$accountId];
|
||||
}
|
||||
$currency = $this->accountRepos->getAccountCurrency($account);
|
||||
if (null === $currency) {
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
$this->accountCurrencies[$accountId] = 0;
|
||||
|
||||
return null;
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
}
|
||||
$this->accountCurrencies[$accountId] = $currency;
|
||||
|
||||
|
@@ -56,7 +56,7 @@ class UpgradeSkeleton extends Command
|
||||
return (bool)$configVar->data;
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -73,7 +73,7 @@ class UpgradeFireflyInstructions extends Command
|
||||
try {
|
||||
app('telemetry')->feature('system.users.count', (string)User::count());
|
||||
} catch (QueryException $e) {
|
||||
// ignore error.
|
||||
// @ignoreException
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@@ -27,14 +27,17 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Exceptions;
|
||||
|
||||
use ErrorException;
|
||||
use Exception;
|
||||
use FireflyIII\Jobs\MailError;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Session\TokenMismatchException;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Validation\ValidationException as LaravelValidationException;
|
||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
use Laravel\Passport\Exceptions\OAuthServerException as LaravelOAuthException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
@@ -44,33 +47,47 @@ use Throwable;
|
||||
*/
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $dontReport
|
||||
= [
|
||||
AuthenticationException::class,
|
||||
LaravelValidationException::class,
|
||||
NotFoundHttpException::class,
|
||||
OAuthServerException::class,
|
||||
LaravelOAuthException::class,
|
||||
TokenMismatchException::class,
|
||||
HttpException::class
|
||||
];
|
||||
|
||||
/**
|
||||
* Render an exception into an HTTP response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Exception $exception
|
||||
* @param Throwable $e
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function render($request, Throwable $exception)
|
||||
public function render($request, Throwable $e)
|
||||
{
|
||||
if ($exception instanceof LaravelValidationException && $request->expectsJson()) {
|
||||
if ($e instanceof LaravelValidationException && $request->expectsJson()) {
|
||||
// ignore it: controller will handle it.
|
||||
return parent::render($request, $exception);
|
||||
return parent::render($request, $e);
|
||||
}
|
||||
if ($exception instanceof NotFoundHttpException && $request->expectsJson()) {
|
||||
if ($e instanceof NotFoundHttpException && $request->expectsJson()) {
|
||||
// JSON error:
|
||||
return response()->json(['message' => 'Resource not found', 'exception' => 'NotFoundHttpException'], 404);
|
||||
}
|
||||
|
||||
if ($exception instanceof AuthenticationException && $request->expectsJson()) {
|
||||
if ($e instanceof AuthenticationException && $request->expectsJson()) {
|
||||
// somehow Laravel handler does not catch this:
|
||||
return response()->json(['message' => 'Unauthenticated', 'exception' => 'AuthenticationException'], 401);
|
||||
}
|
||||
|
||||
if ($exception instanceof OAuthServerException && $request->expectsJson()) {
|
||||
if ($e instanceof OAuthServerException && $request->expectsJson()) {
|
||||
// somehow Laravel handler does not catch this:
|
||||
return response()->json(['message' => $exception->getMessage(), 'exception' => 'OAuthServerException'], 401);
|
||||
return response()->json(['message' => $e->getMessage(), 'exception' => 'OAuthServerException'], 401);
|
||||
}
|
||||
|
||||
if ($request->expectsJson()) {
|
||||
@@ -78,33 +95,33 @@ class Handler extends ExceptionHandler
|
||||
if ($isDebug) {
|
||||
return response()->json(
|
||||
[
|
||||
'message' => $exception->getMessage(),
|
||||
'exception' => get_class($exception),
|
||||
'line' => $exception->getLine(),
|
||||
'file' => $exception->getFile(),
|
||||
'trace' => $exception->getTrace(),
|
||||
'message' => $e->getMessage(),
|
||||
'exception' => get_class($e),
|
||||
'line' => $e->getLine(),
|
||||
'file' => $e->getFile(),
|
||||
'trace' => $e->getTrace(),
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
return response()->json(
|
||||
['message' => sprintf('Internal Firefly III Exception: %s', $exception->getMessage()), 'exception' => get_class($exception)], 500
|
||||
['message' => sprintf('Internal Firefly III Exception: %s', $e->getMessage()), 'exception' => get_class($e)], 500
|
||||
);
|
||||
}
|
||||
|
||||
if ($exception instanceof NotFoundHttpException) {
|
||||
if ($e instanceof NotFoundHttpException) {
|
||||
$handler = app(GracefulNotFoundHandler::class);
|
||||
|
||||
return $handler->render($request, $exception);
|
||||
return $handler->render($request, $e);
|
||||
}
|
||||
if ($exception instanceof FireflyException || $exception instanceof ErrorException || $exception instanceof OAuthServerException) {
|
||||
if ($e instanceof FireflyException || $e instanceof ErrorException || $e instanceof OAuthServerException) {
|
||||
$isDebug = config('app.debug');
|
||||
|
||||
return response()->view('errors.FireflyException', ['exception' => $exception, 'debug' => $isDebug], 500);
|
||||
return response()->view('errors.FireflyException', ['exception' => $e, 'debug' => $isDebug], 500);
|
||||
}
|
||||
|
||||
return parent::render($request, $exception);
|
||||
return parent::render($request, $e);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,49 +129,63 @@ class Handler extends ExceptionHandler
|
||||
*
|
||||
* This is a great spot to send exceptions to Sentry etc.
|
||||
*
|
||||
* // it's five its fine.
|
||||
*
|
||||
* @param Exception $exception
|
||||
* @param Throwable $e
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
* @throws Throwable
|
||||
*
|
||||
*/
|
||||
public function report(Throwable $exception)
|
||||
public function report(Throwable $e)
|
||||
{
|
||||
$doMailError = config('firefly.send_error_message');
|
||||
// if the user wants us to mail:
|
||||
if (true === $doMailError
|
||||
// and if is one of these error instances
|
||||
&& ($exception instanceof FireflyException || $exception instanceof ErrorException)) {
|
||||
$userData = [
|
||||
'id' => 0,
|
||||
'email' => 'unknown@example.com',
|
||||
];
|
||||
if (auth()->check()) {
|
||||
$userData['id'] = auth()->user()->id;
|
||||
$userData['email'] = auth()->user()->email;
|
||||
}
|
||||
$data = [
|
||||
'class' => get_class($exception),
|
||||
'errorMessage' => $exception->getMessage(),
|
||||
'time' => date('r'),
|
||||
'stackTrace' => $exception->getTraceAsString(),
|
||||
'file' => $exception->getFile(),
|
||||
'line' => $exception->getLine(),
|
||||
'code' => $exception->getCode(),
|
||||
'version' => config('firefly.version'),
|
||||
'url' => request()->fullUrl(),
|
||||
'userAgent' => request()->userAgent(),
|
||||
'json' => request()->acceptsJson(),
|
||||
];
|
||||
if ($this->shouldntReportLocal($e) || !$doMailError) {
|
||||
parent::report($e);
|
||||
|
||||
// create job that will mail.
|
||||
$ipAddress = request()->ip() ?? '0.0.0.0';
|
||||
$job = new MailError($userData, (string)config('firefly.site_owner'), $ipAddress, $data);
|
||||
dispatch($job);
|
||||
return;
|
||||
}
|
||||
$userData = [
|
||||
'id' => 0,
|
||||
'email' => 'unknown@example.com',
|
||||
];
|
||||
if (auth()->check()) {
|
||||
$userData['id'] = auth()->user()->id;
|
||||
$userData['email'] = auth()->user()->email;
|
||||
}
|
||||
$data = [
|
||||
'class' => get_class($e),
|
||||
'errorMessage' => $e->getMessage(),
|
||||
'time' => date('r'),
|
||||
'stackTrace' => $e->getTraceAsString(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'code' => $e->getCode(),
|
||||
'version' => config('firefly.version'),
|
||||
'url' => request()->fullUrl(),
|
||||
'userAgent' => request()->userAgent(),
|
||||
'json' => request()->acceptsJson(),
|
||||
];
|
||||
|
||||
parent::report($exception);
|
||||
// create job that will mail.
|
||||
$ipAddress = request()->ip() ?? '0.0.0.0';
|
||||
$job = new MailError($userData, (string)config('firefly.site_owner'), $ipAddress, $data);
|
||||
dispatch($job);
|
||||
|
||||
parent::report($e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Throwable $e
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function shouldntReportLocal(Throwable $e): bool
|
||||
{
|
||||
return !is_null(
|
||||
Arr::first(
|
||||
$this->dontReport, function ($type) use ($e) {
|
||||
return $e instanceof $type;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -57,12 +57,11 @@ class AccountFactory
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$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'];
|
||||
|
||||
$this->canHaveVirtual = config('firefly.can_have_virtual_amounts');
|
||||
$this->validAssetFields = config('firefly.valid_asset_fields');
|
||||
$this->validCCFields = config('firefly.valid_cc_fields');
|
||||
$this->validFields = config('firefly.valid_account_fields');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,16 +73,26 @@ class AccountFactory
|
||||
*/
|
||||
public function findOrCreate(string $accountName, string $accountType): Account
|
||||
{
|
||||
Log::debug(sprintf('Searching for "%s" of type "%s"', $accountName, $accountType));
|
||||
/** @var AccountType $type */
|
||||
$type = AccountType::whereType($accountType)->first();
|
||||
Log::debug(sprintf('findOrCreate("%s", "%s")', $accountName, $accountType));
|
||||
|
||||
$type = $this->accountRepository->getAccountTypeByType($accountType);
|
||||
if (null === $type) {
|
||||
throw new FireflyException(sprintf('Cannot find account type "%s"', $accountType));
|
||||
}
|
||||
$return = $this->user->accounts->where('account_type_id', $type->id)->where('name', $accountName)->first();
|
||||
|
||||
if (null === $return) {
|
||||
Log::debug('Found nothing. Will create a new one.');
|
||||
$return = $this->create(
|
||||
['user_id' => $this->user->id, 'name' => $accountName, 'account_type_id' => $type->id, 'account_type' => null, 'virtual_balance' => '0',
|
||||
'iban' => null, 'active' => true,]
|
||||
[
|
||||
'user_id' => $this->user->id,
|
||||
'name' => $accountName,
|
||||
'account_type_id' => $type->id,
|
||||
'account_type_name' => null,
|
||||
'virtual_balance' => '0',
|
||||
'iban' => null,
|
||||
'active' => true,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -98,118 +107,51 @@ class AccountFactory
|
||||
*/
|
||||
public function create(array $data): Account
|
||||
{
|
||||
$type = $this->getAccountType($data['account_type_id'] ?? null, $data['account_type'] ?? null);
|
||||
if (null === $type) {
|
||||
throw new FireflyException(
|
||||
sprintf('AccountFactory::create() was unable to find account type #%d ("%s").', $data['account_type_id'] ?? null, $data['account_type'] ?? null)
|
||||
);
|
||||
}
|
||||
|
||||
$type = $this->getAccountType($data);
|
||||
$data['iban'] = $this->filterIban($data['iban'] ?? null);
|
||||
|
||||
// account may exist already:
|
||||
Log::debug('Data array is as follows', $data);
|
||||
$return = $this->find($data['name'], $type->type);
|
||||
|
||||
if (null === $return) {
|
||||
$this->accountRepository->resetAccountOrder();
|
||||
|
||||
// create it:
|
||||
$databaseData = ['user_id' => $this->user->id,
|
||||
'account_type_id' => $type->id,
|
||||
'name' => $data['name'],
|
||||
'order' => 25000,
|
||||
'virtual_balance' => $data['virtual_balance'] ?? null, 'active' => true === $data['active'], 'iban' => $data['iban'],];
|
||||
|
||||
$currency = $this->getCurrency((int)($data['currency_id'] ?? null), (string)($data['currency_code'] ?? null));
|
||||
unset($data['currency_code']);
|
||||
$data['currency_id'] = $currency->id;
|
||||
|
||||
// remove virtual balance when not an asset account or a liability
|
||||
if (!in_array($type->type, $this->canHaveVirtual, true)) {
|
||||
$databaseData['virtual_balance'] = null;
|
||||
}
|
||||
|
||||
// fix virtual balance when it's empty
|
||||
if ('' === (string)$databaseData['virtual_balance']) {
|
||||
$databaseData['virtual_balance'] = null;
|
||||
}
|
||||
|
||||
$return = Account::create($databaseData);
|
||||
$this->updateMetaData($return, $data);
|
||||
|
||||
// if it can have a virtual balance, it can also have an opening balance.
|
||||
if (in_array($type->type, $this->canHaveVirtual, true)) {
|
||||
if ($this->validOBData($data)) {
|
||||
$this->updateOBGroup($return, $data);
|
||||
}
|
||||
if (!$this->validOBData($data)) {
|
||||
$this->deleteOBGroup($return);
|
||||
}
|
||||
}
|
||||
$this->updateNote($return, $data['notes'] ?? '');
|
||||
|
||||
// store location
|
||||
$this->storeNewLocation($return, $data);
|
||||
|
||||
// update order to be correct:
|
||||
|
||||
// set new order:
|
||||
$maxOrder = $this->accountRepository->maxOrder($type->type);
|
||||
$order = null;
|
||||
if (!array_key_exists('order', $data)) {
|
||||
// take maxOrder + 1
|
||||
$order = $maxOrder + 1;
|
||||
}
|
||||
if (array_key_exists('order', $data)) {
|
||||
// limit order
|
||||
$order = (int)($data['order'] > $maxOrder ? $maxOrder + 1 : $data['order']);
|
||||
$order = 0 === $order ? $maxOrder + 1 : $order;
|
||||
}
|
||||
$updateService = app(AccountUpdateService::class);
|
||||
$updateService->setUser($return->user);
|
||||
Log::debug(sprintf('Will set order to %d', $order));
|
||||
$return = $updateService->update($return, ['order' => $order]);
|
||||
$return = $this->createAccount($type, $data);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $accountTypeId
|
||||
* @param null|string $accountType
|
||||
* @param array $data
|
||||
*
|
||||
* @return AccountType|null
|
||||
*/
|
||||
protected function getAccountType(?int $accountTypeId, ?string $accountType): ?AccountType
|
||||
protected function getAccountType(array $data): ?AccountType
|
||||
{
|
||||
$accountTypeId = (int)$accountTypeId;
|
||||
$result = null;
|
||||
$accountTypeId = array_key_exists('account_type_id', $data) ? (int)$data['account_type_id'] : 0;
|
||||
$accountTypeName = array_key_exists('account_type_name', $data) ? $data['account_type_name'] : null;
|
||||
$result = null;
|
||||
// find by name or ID
|
||||
if ($accountTypeId > 0) {
|
||||
$result = AccountType::find($accountTypeId);
|
||||
}
|
||||
if (null !== $accountTypeName) {
|
||||
$result = $this->accountRepository->getAccountTypeByType($accountTypeName);
|
||||
}
|
||||
|
||||
// try with type:
|
||||
if (null === $result) {
|
||||
Log::debug(sprintf('No account type found by ID, continue search for "%s".', $accountType));
|
||||
/** @var array $types */
|
||||
$types = config('firefly.accountTypeByIdentifier.' . $accountType) ?? [];
|
||||
$types = config(sprintf('firefly.accountTypeByIdentifier.%s', $accountTypeName)) ?? [];
|
||||
if (count($types) > 0) {
|
||||
Log::debug(sprintf('%d accounts in list from config', count($types)), $types);
|
||||
$result = AccountType::whereIn('type', $types)->first();
|
||||
}
|
||||
if (null === $result && null !== $accountType) {
|
||||
// try as full name:
|
||||
$result = AccountType::whereType($accountType)->first();
|
||||
}
|
||||
}
|
||||
if (null === $result) {
|
||||
Log::warning(sprintf('Found NO account type based on %d and "%s"', $accountTypeId, $accountType));
|
||||
}
|
||||
if (null !== $result) {
|
||||
Log::debug(sprintf('Found account type based on %d and "%s": "%s"', $accountTypeId, $accountType, $result->type));
|
||||
Log::warning(sprintf('Found NO account type based on %d and "%s"', $accountTypeId, $accountTypeName));
|
||||
throw new FireflyException(sprintf('AccountFactory::create() was unable to find account type #%d ("%s").', $accountTypeId, $accountTypeName));
|
||||
}
|
||||
Log::debug(sprintf('Found account type based on %d and "%s": "%s"', $accountTypeId, $accountTypeName, $result->type));
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,11 +167,168 @@ class AccountFactory
|
||||
return $this->user->accounts()->where('account_type_id', $type->id)->where('name', $accountName)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
private function createAccount(AccountType $type, array $data): Account
|
||||
{
|
||||
$this->accountRepository->resetAccountOrder();
|
||||
|
||||
// create it:
|
||||
$virtualBalance = array_key_exists('virtual_balance', $data) ? $data['virtual_balance'] : null;
|
||||
$active = array_key_exists('active', $data) ? $data['active'] : true;
|
||||
$databaseData = ['user_id' => $this->user->id,
|
||||
'account_type_id' => $type->id,
|
||||
'name' => $data['name'],
|
||||
'order' => 25000,
|
||||
'virtual_balance' => $virtualBalance,
|
||||
'active' => $active,
|
||||
'iban' => $data['iban'],
|
||||
];
|
||||
// fix virtual balance when it's empty
|
||||
if ('' === (string)$databaseData['virtual_balance']) {
|
||||
$databaseData['virtual_balance'] = null;
|
||||
}
|
||||
// remove virtual balance when not an asset account or a liability
|
||||
if (!in_array($type->type, $this->canHaveVirtual, true)) {
|
||||
$databaseData['virtual_balance'] = null;
|
||||
}
|
||||
// create account!
|
||||
$account = Account::create($databaseData);
|
||||
|
||||
// update meta data:
|
||||
$data = $this->cleanMetaDataArray($account, $data);
|
||||
$this->storeMetaData($account, $data);
|
||||
|
||||
// create opening balance
|
||||
$this->storeOpeningBalance($account, $data);
|
||||
|
||||
// create notes
|
||||
$notes = array_key_exists('notes', $data) ? $data['notes'] : '';
|
||||
$this->updateNote($account, $notes);
|
||||
|
||||
// create location
|
||||
$this->storeNewLocation($account, $data);
|
||||
|
||||
// set order
|
||||
$this->storeOrder($account, $data);
|
||||
|
||||
// refresh and return
|
||||
$account->refresh();
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function cleanMetaDataArray(Account $account, array $data): array
|
||||
{
|
||||
$currencyId = array_key_exists('currency_id', $data) ? (int)$data['currency_id'] : 0;
|
||||
$currencyCode = array_key_exists('currency_code', $data) ? (string)$data['currency_code'] : '';
|
||||
$accountRole = array_key_exists('account_role', $data) ? (string)$data['account_role'] : null;
|
||||
$currency = $this->getCurrency($currencyId, $currencyCode);
|
||||
|
||||
// only asset account may have a role:
|
||||
if ($account->accountType->type !== AccountType::ASSET) {
|
||||
$accountRole = '';
|
||||
}
|
||||
|
||||
$data['account_role'] = $accountRole;
|
||||
$data['currency_id'] = $currency->id;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*/
|
||||
private function storeMetaData(Account $account, array $data): void
|
||||
{
|
||||
|
||||
$fields = $this->validFields;
|
||||
if ($account->accountType->type === AccountType::ASSET) {
|
||||
$fields = $this->validAssetFields;
|
||||
}
|
||||
if ($account->accountType->type === AccountType::ASSET && 'ccAsset' === $data['account_role']) {
|
||||
$fields = $this->validCCFields;
|
||||
}
|
||||
|
||||
/** @var AccountMetaFactory $factory */
|
||||
$factory = app(AccountMetaFactory::class);
|
||||
foreach ($fields as $field) {
|
||||
// if the field is set but NULL, skip it.
|
||||
// if the field is set but "", update it.
|
||||
if (array_key_exists($field, $data) && null !== $data[$field]) {
|
||||
|
||||
// convert boolean value:
|
||||
if (is_bool($data[$field]) && false === $data[$field]) {
|
||||
$data[$field] = 0;
|
||||
}
|
||||
if (is_bool($data[$field]) && true === $data[$field]) {
|
||||
$data[$field] = 1;
|
||||
}
|
||||
|
||||
$factory->crud($account, $field, (string)$data[$field]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*/
|
||||
private function storeOpeningBalance(Account $account, array $data)
|
||||
{
|
||||
$accountType = $account->accountType->type;
|
||||
|
||||
// if it can have a virtual balance, it can also have an opening balance.
|
||||
if (in_array($accountType, $this->canHaveVirtual, true)) {
|
||||
if ($this->validOBData($data)) {
|
||||
$this->updateOBGroup($account, $data);
|
||||
}
|
||||
if (!$this->validOBData($data)) {
|
||||
$this->deleteOBGroup($account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*/
|
||||
private function storeOrder(Account $account, array $data): void
|
||||
{
|
||||
$accountType = $account->accountType->type;
|
||||
$maxOrder = $this->accountRepository->maxOrder($accountType);
|
||||
$order = null;
|
||||
if (!array_key_exists('order', $data)) {
|
||||
$order = $maxOrder + 1;
|
||||
}
|
||||
if (array_key_exists('order', $data)) {
|
||||
$order = (int)($data['order'] > $maxOrder ? $maxOrder + 1 : $data['order']);
|
||||
$order = 0 === $order ? $maxOrder + 1 : $order;
|
||||
}
|
||||
|
||||
$updateService = app(AccountUpdateService::class);
|
||||
$updateService->setUser($account->user);
|
||||
$updateService->update($account, ['order' => $order]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->accountRepository->setUser($user);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -67,8 +67,8 @@ class AccountMetaFactory
|
||||
if ('' === $value && null !== $entry) {
|
||||
try {
|
||||
$entry->delete();
|
||||
} catch (Exception $e) { // @codeCoverageIgnore
|
||||
Log::debug(sprintf('Could not delete entry: %s', $e->getMessage())); // @codeCoverageIgnore
|
||||
} catch (Exception $e) { // @phpstan-ignore-line
|
||||
Log::debug(sprintf('Could not delete entry: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user