mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-23 14:26:58 +00:00
Expand v2 api
This commit is contained in:
@@ -30,6 +30,7 @@ use FireflyIII\Http\Middleware\IsDemoUser;
|
|||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Support\Http\Controllers\GetConfigurationData;
|
use FireflyIII\Support\Http\Controllers\GetConfigurationData;
|
||||||
|
use FireflyIII\Support\Models\AccountBalanceCalculator;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Contracts\View\Factory;
|
use Illuminate\Contracts\View\Factory;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
@@ -94,6 +95,7 @@ class DebugController extends Controller
|
|||||||
|
|
||||||
// also do some recalculations.
|
// also do some recalculations.
|
||||||
Artisan::call('firefly-iii:trigger-credit-recalculation');
|
Artisan::call('firefly-iii:trigger-credit-recalculation');
|
||||||
|
AccountBalanceCalculator::forceRecalculateAll();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Artisan::call('twig:clean');
|
Artisan::call('twig:clean');
|
||||||
|
@@ -6,6 +6,8 @@ namespace FireflyIII\JsonApi\V2\Accounts;
|
|||||||
|
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Rules\IsAllowedGroupAction;
|
use FireflyIII\Rules\IsAllowedGroupAction;
|
||||||
|
use FireflyIII\Rules\IsDateOrTime;
|
||||||
|
use FireflyIII\Rules\IsValidDateRange;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use LaravelJsonApi\Laravel\Http\Requests\ResourceQuery;
|
use LaravelJsonApi\Laravel\Http\Requests\ResourceQuery;
|
||||||
use LaravelJsonApi\Validation\Rule as JsonApiRule;
|
use LaravelJsonApi\Validation\Rule as JsonApiRule;
|
||||||
@@ -25,11 +27,23 @@ class AccountCollectionQuery extends ResourceQuery
|
|||||||
'array',
|
'array',
|
||||||
JsonApiRule::fieldSets(),
|
JsonApiRule::fieldSets(),
|
||||||
],
|
],
|
||||||
'user_group_id' => [
|
'userGroupId' => [
|
||||||
'nullable',
|
'nullable',
|
||||||
'integer',
|
'integer',
|
||||||
new IsAllowedGroupAction(Account::class, request()->method()),
|
new IsAllowedGroupAction(Account::class, request()->method()),
|
||||||
],
|
],
|
||||||
|
'startPeriod' => [
|
||||||
|
'nullable',
|
||||||
|
'date',
|
||||||
|
new IsDateOrTime(),
|
||||||
|
new isValidDateRange(),
|
||||||
|
],
|
||||||
|
'endPeriod' => [
|
||||||
|
'nullable',
|
||||||
|
'date',
|
||||||
|
new IsDateOrTime(),
|
||||||
|
new isValidDateRange(),
|
||||||
|
],
|
||||||
'filter' => [
|
'filter' => [
|
||||||
'nullable',
|
'nullable',
|
||||||
'array',
|
'array',
|
||||||
@@ -45,6 +59,15 @@ class AccountCollectionQuery extends ResourceQuery
|
|||||||
'array',
|
'array',
|
||||||
JsonApiRule::page(),
|
JsonApiRule::page(),
|
||||||
],
|
],
|
||||||
|
'page.number' => [
|
||||||
|
'integer',
|
||||||
|
'min:1',
|
||||||
|
],
|
||||||
|
|
||||||
|
'page.size' => [
|
||||||
|
'integer',
|
||||||
|
'min:1',
|
||||||
|
],
|
||||||
'sort' => [
|
'sort' => [
|
||||||
'nullable',
|
'nullable',
|
||||||
'string',
|
'string',
|
||||||
|
@@ -39,24 +39,46 @@ class AccountResource extends JsonApiResource
|
|||||||
'name' => $this->resource->name,
|
'name' => $this->resource->name,
|
||||||
'active' => $this->resource->active,
|
'active' => $this->resource->active,
|
||||||
'order' => $this->resource->order,
|
'order' => $this->resource->order,
|
||||||
|
'iban' => $this->resource->iban,
|
||||||
'type' => $this->resource->account_type_string,
|
'type' => $this->resource->account_type_string,
|
||||||
'account_role' => $this->resource->account_role,
|
'account_role' => $this->resource->account_role,
|
||||||
'account_number' => '' === $this->resource->account_number ? null : $this->resource->account_number,
|
'account_number' => '' === $this->resource->account_number ? null : $this->resource->account_number,
|
||||||
|
|
||||||
// currency
|
// currency (if the account has a currency setting, otherwise NULL).
|
||||||
'currency_id' => $this->resource->currency_id,
|
'currency_id' => $this->resource->currency_id,
|
||||||
'currency_name' => $this->resource->currency_name,
|
'currency_name' => $this->resource->currency_name,
|
||||||
'currency_code' => $this->resource->currency_code,
|
'currency_code' => $this->resource->currency_code,
|
||||||
'currency_symbol' => $this->resource->currency_symbol,
|
'currency_symbol' => $this->resource->currency_symbol,
|
||||||
'currency_decimal_places' => $this->resource->currency_decimal_places,
|
'currency_decimal_places' => $this->resource->currency_decimal_places,
|
||||||
|
'is_multi_currency' => '1' === $this->resource->is_multi_currency,
|
||||||
|
|
||||||
|
// balances
|
||||||
|
'balance' => $this->resource->balance,
|
||||||
|
'native_balance' => $this->resource->native_balance,
|
||||||
|
|
||||||
// liability things
|
// liability things
|
||||||
'liability_direction' => $this->resource->liability_direction,
|
'liability_direction' => $this->resource->liability_direction,
|
||||||
'interest' => $this->resource->interest,
|
'interest' => $this->resource->interest,
|
||||||
'interest_period' => $this->resource->interest_period,
|
'interest_period' => $this->resource->interest_period,
|
||||||
'current_debt' => $this->resource->current_debt,
|
'current_debt' => $this->resource->current_debt, // TODO may be removed in the future.
|
||||||
|
|
||||||
|
|
||||||
|
// other things
|
||||||
'last_activity' => $this->resource->last_activity,
|
'last_activity' => $this->resource->last_activity,
|
||||||
|
|
||||||
|
|
||||||
|
// still to do
|
||||||
|
|
||||||
|
// balance difference
|
||||||
|
// 'balance_difference' => $balanceDiff,
|
||||||
|
// 'native_balance_difference' => $nativeBalanceDiff,
|
||||||
|
// 'balance_difference_start' => $diffStart,
|
||||||
|
// 'balance_difference_end' => $diffEnd,
|
||||||
|
|
||||||
|
// object group
|
||||||
|
// 'object_group_id' => null !== $objectGroupId ? (string) $objectGroupId : null,
|
||||||
|
// 'object_group_order' => $objectGroupOrder,
|
||||||
|
// 'object_group_title' => $objectGroupTitle,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\JsonApi\V2\Accounts\Capabilities;
|
namespace FireflyIII\JsonApi\V2\Accounts\Capabilities;
|
||||||
|
|
||||||
|
use FireflyIII\Support\JsonApi\CollectsCustomParameters;
|
||||||
use FireflyIII\Support\JsonApi\Concerns\UsergroupAware;
|
use FireflyIII\Support\JsonApi\Concerns\UsergroupAware;
|
||||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||||
use FireflyIII\Support\JsonApi\ExpandsQuery;
|
use FireflyIII\Support\JsonApi\ExpandsQuery;
|
||||||
@@ -42,6 +43,7 @@ class AccountQuery extends QueryAll implements HasPagination
|
|||||||
use SortsCollection;
|
use SortsCollection;
|
||||||
use UsergroupAware;
|
use UsergroupAware;
|
||||||
use ValidateSortParameters;
|
use ValidateSortParameters;
|
||||||
|
use CollectsCustomParameters;
|
||||||
|
|
||||||
#[\Override]
|
#[\Override]
|
||||||
/**
|
/**
|
||||||
@@ -60,6 +62,9 @@ class AccountQuery extends QueryAll implements HasPagination
|
|||||||
// This is necessary when the user wants to sort on specific params.
|
// This is necessary when the user wants to sort on specific params.
|
||||||
$needsAll = $this->needsFullDataset('account', $sort);
|
$needsAll = $this->needsFullDataset('account', $sort);
|
||||||
|
|
||||||
|
// params that were not recognised, may be my own custom stuff.
|
||||||
|
$otherParams = $this->getOtherParams($this->queryParameters->unrecognisedParameters());
|
||||||
|
|
||||||
// start the query
|
// start the query
|
||||||
$query = $this->userGroup->accounts();
|
$query = $this->userGroup->accounts();
|
||||||
|
|
||||||
@@ -77,6 +82,8 @@ class AccountQuery extends QueryAll implements HasPagination
|
|||||||
|
|
||||||
// enrich the collected data
|
// enrich the collected data
|
||||||
$enrichment = new AccountEnrichment();
|
$enrichment = new AccountEnrichment();
|
||||||
|
$enrichment->setStart($otherParams['start'] ?? null);
|
||||||
|
$enrichment->setEnd($otherParams['end'] ?? null);
|
||||||
$collection = $enrichment->enrich($collection);
|
$collection = $enrichment->enrich($collection);
|
||||||
|
|
||||||
// TODO add filters after the query, if there are filters that cannot be applied to the database but only
|
// TODO add filters after the query, if there are filters that cannot be applied to the database but only
|
||||||
|
@@ -58,6 +58,7 @@ use FireflyIII\Services\Password\Verifier;
|
|||||||
use FireflyIII\Services\Webhook\StandardWebhookSender;
|
use FireflyIII\Services\Webhook\StandardWebhookSender;
|
||||||
use FireflyIII\Services\Webhook\WebhookSenderInterface;
|
use FireflyIII\Services\Webhook\WebhookSenderInterface;
|
||||||
use FireflyIII\Support\Amount;
|
use FireflyIII\Support\Amount;
|
||||||
|
use FireflyIII\Support\Balance;
|
||||||
use FireflyIII\Support\ExpandedForm;
|
use FireflyIII\Support\ExpandedForm;
|
||||||
use FireflyIII\Support\FireflyConfig;
|
use FireflyIII\Support\FireflyConfig;
|
||||||
use FireflyIII\Support\Form\AccountForm;
|
use FireflyIII\Support\Form\AccountForm;
|
||||||
@@ -133,6 +134,12 @@ class FireflyServiceProvider extends ServiceProvider
|
|||||||
return new Steam();
|
return new Steam();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
$this->app->bind(
|
||||||
|
'balance',
|
||||||
|
static function () {
|
||||||
|
return new Balance();
|
||||||
|
}
|
||||||
|
);
|
||||||
$this->app->bind(
|
$this->app->bind(
|
||||||
'expandedform',
|
'expandedform',
|
||||||
static function () {
|
static function () {
|
||||||
|
79
app/Rules/IsValidDateRange.php
Normal file
79
app/Rules/IsValidDateRange.php
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* IsValidDateRange.php
|
||||||
|
* Copyright (c) 2024 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\Rules;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Carbon\Exceptions\InvalidDateException;
|
||||||
|
use Carbon\Exceptions\InvalidFormatException;
|
||||||
|
use Illuminate\Contracts\Validation\ValidationRule;
|
||||||
|
|
||||||
|
class IsValidDateRange implements ValidationRule
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||||
|
*/
|
||||||
|
public function validate(string $attribute, mixed $value, \Closure $fail): void
|
||||||
|
{
|
||||||
|
$value = (string) $value;
|
||||||
|
if ('' === $value) {
|
||||||
|
$fail('validation.date_or_time')->translate();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$other = 'startPeriod';
|
||||||
|
if ('startPeriod' === $attribute) {
|
||||||
|
$other = 'endPeriod';
|
||||||
|
}
|
||||||
|
$otherValue = request()->get($other);
|
||||||
|
// parse date, twice.
|
||||||
|
try {
|
||||||
|
$left = Carbon::parse($value);
|
||||||
|
$right = Carbon::parse($otherValue);
|
||||||
|
} catch (InvalidDateException $e) { // @phpstan-ignore-line
|
||||||
|
app('log')->error(sprintf('"%s" or "%s" is not a valid date or time: %s', $value, $otherValue, $e->getMessage()));
|
||||||
|
|
||||||
|
$fail('validation.date_or_time')->translate();
|
||||||
|
|
||||||
|
return;
|
||||||
|
} catch (InvalidFormatException $e) {
|
||||||
|
app('log')->error(sprintf('"%s" or "%s" is of an invalid format: %s', $value, $otherValue, $e->getMessage()));
|
||||||
|
|
||||||
|
$fail('validation.date_or_time')->translate();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// start must be before end.
|
||||||
|
if ('startPeriod' === $attribute) {
|
||||||
|
if ($left->gt($right)) {
|
||||||
|
$fail('validation.date_after')->translate();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// end must be after start
|
||||||
|
if ($left->lt($right)) {
|
||||||
|
$fail('validation.date_after')->translate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
76
app/Support/Balance.php
Normal file
76
app/Support/Balance.php
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Balance.php
|
||||||
|
* Copyright (c) 2024 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\Support;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Models\Transaction;
|
||||||
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
class Balance
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the accounts balances as an array, on the account ID.
|
||||||
|
*
|
||||||
|
* @param Collection $accounts
|
||||||
|
* @param Carbon $date
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAccountBalances(Collection $accounts, Carbon $date): array
|
||||||
|
{
|
||||||
|
$return = [];
|
||||||
|
$currencies = [];
|
||||||
|
$cache = new CacheProperties();
|
||||||
|
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||||
|
$cache->addProperty('getAccountBalances');
|
||||||
|
$cache->addProperty($date);
|
||||||
|
if ($cache->has()) {
|
||||||
|
return $cache->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = Transaction::
|
||||||
|
whereIn('transactions.account_id', $accounts->pluck('id')->toArray())
|
||||||
|
->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||||
|
->orderBy('transaction_journals.date', 'desc')
|
||||||
|
->orderBy('transaction_journals.order', 'asc')
|
||||||
|
->orderBy('transaction_journals.description', 'desc')
|
||||||
|
->orderBy('transactions.amount', 'desc');
|
||||||
|
|
||||||
|
$result = $query->get(['transactions.account_id', 'transactions.transaction_currency_id', 'transactions.balance_after']);
|
||||||
|
foreach ($result as $entry) {
|
||||||
|
$accountId = (int) $entry->account_id;
|
||||||
|
$currencyId = (int) $entry->transaction_currency_id;
|
||||||
|
$currencies[$currencyId] ??= TransactionCurrency::find($currencyId);
|
||||||
|
$return[$accountId] ??= [];
|
||||||
|
if (array_key_exists($currencyId, $return[$accountId])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$return[$accountId][$currencyId] = ['currency' => $currencies[$currencyId], 'balance' => $entry->balance_after, 'date' => clone $date];
|
||||||
|
}
|
||||||
|
return $return;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
37
app/Support/Facades/Balance.php
Normal file
37
app/Support/Facades/Balance.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Balance.php
|
||||||
|
* Copyright (c) 2024 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\Support\Facades;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Facade;
|
||||||
|
|
||||||
|
class Balance extends Facade
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the registered name of the component.
|
||||||
|
*/
|
||||||
|
protected static function getFacadeAccessor(): string
|
||||||
|
{
|
||||||
|
return 'balance';
|
||||||
|
}
|
||||||
|
}
|
@@ -441,7 +441,7 @@ trait PeriodOverview
|
|||||||
$cache->addProperty('tag-period-entries');
|
$cache->addProperty('tag-period-entries');
|
||||||
$cache->addProperty($tag->id);
|
$cache->addProperty($tag->id);
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
// return $cache->get();
|
return $cache->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var array $dates */
|
/** @var array $dates */
|
||||||
|
43
app/Support/JsonApi/CollectsCustomParameters.php
Normal file
43
app/Support/JsonApi/CollectsCustomParameters.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* CollectsCustomParameters.php
|
||||||
|
* Copyright (c) 2024 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\Support\JsonApi;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
trait CollectsCustomParameters
|
||||||
|
{
|
||||||
|
|
||||||
|
protected function getOtherParams(array $params): array
|
||||||
|
{
|
||||||
|
$return = [];
|
||||||
|
if (array_key_exists('startPeriod', $params)) {
|
||||||
|
$return['start'] = Carbon::parse($params['startPeriod']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('endPeriod', $params)) {
|
||||||
|
$return['end'] = Carbon::parse($params['endPeriod']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
}
|
@@ -24,11 +24,13 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Support\JsonApi\Enrichments;
|
namespace FireflyIII\Support\JsonApi\Enrichments;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Facades\Balance;
|
||||||
|
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
@@ -42,6 +44,10 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
{
|
{
|
||||||
private Collection $collection;
|
private Collection $collection;
|
||||||
private array $currencies;
|
private array $currencies;
|
||||||
|
private array $balances;
|
||||||
|
private TransactionCurrency $default;
|
||||||
|
private ?Carbon $start;
|
||||||
|
private ?Carbon $end;
|
||||||
|
|
||||||
private AccountRepositoryInterface $repository;
|
private AccountRepositoryInterface $repository;
|
||||||
private CurrencyRepositoryInterface $currencyRepository;
|
private CurrencyRepositoryInterface $currencyRepository;
|
||||||
@@ -50,6 +56,8 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
{
|
{
|
||||||
$this->repository = app(AccountRepositoryInterface::class);
|
$this->repository = app(AccountRepositoryInterface::class);
|
||||||
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
||||||
|
$this->start = null;
|
||||||
|
$this->end = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[\Override]
|
#[\Override]
|
||||||
@@ -61,13 +69,15 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
Log::debug(sprintf('Now doing account enrichment for %d account(s)', $collection->count()));
|
Log::debug(sprintf('Now doing account enrichment for %d account(s)', $collection->count()));
|
||||||
// prep local fields
|
// prep local fields
|
||||||
$this->collection = $collection;
|
$this->collection = $collection;
|
||||||
|
$this->default = app('amount')->getDefaultCurrency();
|
||||||
$this->currencies = [];
|
$this->currencies = [];
|
||||||
|
$this->balances = [];
|
||||||
|
|
||||||
// do everything here:
|
// do everything here:
|
||||||
$this->getLastActivity();
|
$this->getLastActivity();
|
||||||
$this->collectAccountTypes();
|
$this->collectAccountTypes();
|
||||||
$this->collectMetaData();
|
$this->collectMetaData();
|
||||||
// $this->getMetaBalances();
|
$this->getMetaBalances();
|
||||||
|
|
||||||
// $this->collection->transform(function (Account $account) {
|
// $this->collection->transform(function (Account $account) {
|
||||||
// $account->user_array = ['id' => 1, 'bla bla' => 'bla'];
|
// $account->user_array = ['id' => 1, 'bla bla' => 'bla'];
|
||||||
@@ -94,22 +104,65 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO this method refers to a single-use method inside Steam that could be moved here.
|
|
||||||
*/
|
|
||||||
private function getMetaBalances(): void
|
private function getMetaBalances(): void
|
||||||
{
|
{
|
||||||
try {
|
$this->balances = Balance::getAccountBalances($this->collection, today());
|
||||||
$array = app('steam')->balancesByAccountsConverted($this->collection, today());
|
$balances = $this->balances;
|
||||||
} catch (FireflyException $e) {
|
$default = $this->default;
|
||||||
Log::error(sprintf('Could not load balances: %s', $e->getMessage()));
|
|
||||||
|
|
||||||
return;
|
// get start and end, so the balance difference can be generated.
|
||||||
|
$start = null;
|
||||||
|
$end = null;
|
||||||
|
if(null !== $this->start) {
|
||||||
|
$start = Balance::getAccountBalances($this->collection, $this->start);
|
||||||
}
|
}
|
||||||
foreach ($array as $accountId => $row) {
|
if(null !== $this->end) {
|
||||||
$this->collection->where('id', $accountId)->first()->balance = $row['balance'];
|
$end = Balance::getAccountBalances($this->collection, $this->end);
|
||||||
$this->collection->where('id', $accountId)->first()->native_balance = $row['native_balance'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$this->collection->transform(function (Account $account) use ($balances, $default) {
|
||||||
|
$converter = new ExchangeRateConverter();
|
||||||
|
$native = [
|
||||||
|
'currency_id' => $this->default->id,
|
||||||
|
'currency_name' => $this->default->name,
|
||||||
|
'currency_code' => $this->default->code,
|
||||||
|
'currency_symbol' => $this->default->symbol,
|
||||||
|
'currency_decimal_places' => $this->default->decimal_places,
|
||||||
|
'balance' => '0',
|
||||||
|
];
|
||||||
|
if (array_key_exists($account->id, $balances)) {
|
||||||
|
$set = [];
|
||||||
|
foreach ($balances[$account->id] as $entry) {
|
||||||
|
$set[] = [
|
||||||
|
'currency_id' => $entry['currency']->id,
|
||||||
|
'currency_name' => $entry['currency']->name,
|
||||||
|
'currency_code' => $entry['currency']->code,
|
||||||
|
'currency_symbol' => $entry['currency']->symbol,
|
||||||
|
'currency_decimal_places' => $entry['currency']->decimal_places,
|
||||||
|
'balance' => $entry['balance'],
|
||||||
|
];
|
||||||
|
$native['balance'] = bcadd($native['balance'], $converter->convert($entry['currency'], $default, today(), $entry['balance']));
|
||||||
|
}
|
||||||
|
$account->balance = $set;
|
||||||
|
$account->native_balance = $native;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $account;
|
||||||
|
});
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// $array = app('steam')->balancesByAccountsConverted($this->collection, today());
|
||||||
|
// } catch (FireflyException $e) {
|
||||||
|
// Log::error(sprintf('Could not load balances: %s', $e->getMessage()));
|
||||||
|
//
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// foreach ($array as $accountId => $row) {
|
||||||
|
// //$this->collection->where('id', $accountId)->first()->balance = $row['balance'];
|
||||||
|
// //$this->collection->where('id', $accountId)->first()->native_balance = $row['native_balance'];
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,7 +186,7 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
|
|
||||||
private function collectMetaData(): void
|
private function collectMetaData(): void
|
||||||
{
|
{
|
||||||
$metaFields = $this->repository->getMetaValues($this->collection, ['currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']);
|
$metaFields = $this->repository->getMetaValues($this->collection, ['is_multi_currency', 'currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']);
|
||||||
$currencyIds = $metaFields->where('name', 'currency_id')->pluck('data')->toArray();
|
$currencyIds = $metaFields->where('name', 'currency_id')->pluck('data')->toArray();
|
||||||
|
|
||||||
$currencies = [];
|
$currencies = [];
|
||||||
@@ -168,4 +221,16 @@ class AccountEnrichment implements EnrichmentInterface
|
|||||||
|
|
||||||
return $collection->first();
|
return $collection->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setStart(?Carbon $start): void
|
||||||
|
{
|
||||||
|
$this->start = $start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setEnd(?Carbon $end): void
|
||||||
|
{
|
||||||
|
$this->end = $end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -108,7 +108,8 @@ class AccountBalanceCalculator
|
|||||||
$balances = [];
|
$balances = [];
|
||||||
$count = 0;
|
$count = 0;
|
||||||
$query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
$query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
|
->whereNull('transactions.deleted_at')
|
||||||
|
->whereNull('transaction_journals.deleted_at')
|
||||||
// this order is the same as GroupCollector, but in the exact reverse.
|
// this order is the same as GroupCollector, but in the exact reverse.
|
||||||
->orderBy('transaction_journals.date', 'asc')
|
->orderBy('transaction_journals.date', 'asc')
|
||||||
->orderBy('transaction_journals.order', 'desc')
|
->orderBy('transaction_journals.order', 'desc')
|
||||||
@@ -116,7 +117,7 @@ class AccountBalanceCalculator
|
|||||||
->orderBy('transaction_journals.description', 'asc')
|
->orderBy('transaction_journals.description', 'asc')
|
||||||
->orderBy('transactions.amount', 'asc')
|
->orderBy('transactions.amount', 'asc')
|
||||||
;
|
;
|
||||||
if (count($accounts) > 0) {
|
if ($accounts->count() > 0) {
|
||||||
$query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray());
|
$query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +132,7 @@ class AccountBalanceCalculator
|
|||||||
// before and after are easy:
|
// before and after are easy:
|
||||||
$before = $balances[$entry->account_id][$entry->transaction_currency_id];
|
$before = $balances[$entry->account_id][$entry->transaction_currency_id];
|
||||||
$after = bcadd($before, $entry->amount);
|
$after = bcadd($before, $entry->amount);
|
||||||
if (true === $entry->balance_dirty) {
|
if (true === $entry->balance_dirty || $accounts->count() > 0) {
|
||||||
// update the transaction:
|
// update the transaction:
|
||||||
$entry->balance_before = $before;
|
$entry->balance_before = $before;
|
||||||
$entry->balance_after = $after;
|
$entry->balance_after = $after;
|
||||||
|
@@ -39,8 +39,12 @@ use Illuminate\Support\Facades\Log;
|
|||||||
*/
|
*/
|
||||||
class Steam
|
class Steam
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
public function balanceIgnoreVirtual(Account $account, Carbon $date): string
|
public function balanceIgnoreVirtual(Account $account, Carbon $date): string
|
||||||
{
|
{
|
||||||
|
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
|
||||||
/** @var AccountRepositoryInterface $repository */
|
/** @var AccountRepositoryInterface $repository */
|
||||||
$repository = app(AccountRepositoryInterface::class);
|
$repository = app(AccountRepositoryInterface::class);
|
||||||
$repository->setUser($account->user);
|
$repository->setUser($account->user);
|
||||||
@@ -89,6 +93,7 @@ class Steam
|
|||||||
*/
|
*/
|
||||||
public function balanceInRange(Account $account, Carbon $start, Carbon $end, ?TransactionCurrency $currency = null): array
|
public function balanceInRange(Account $account, Carbon $start, Carbon $end, ?TransactionCurrency $currency = null): array
|
||||||
{
|
{
|
||||||
|
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($account->id);
|
$cache->addProperty($account->id);
|
||||||
$cache->addProperty('balance-in-range');
|
$cache->addProperty('balance-in-range');
|
||||||
@@ -209,8 +214,7 @@ class Steam
|
|||||||
*/
|
*/
|
||||||
public function balance(Account $account, Carbon $date, ?TransactionCurrency $currency = null): string
|
public function balance(Account $account, Carbon $date, ?TransactionCurrency $currency = null): string
|
||||||
{
|
{
|
||||||
//throw new FireflyException('This method is obsolete.');
|
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
|
||||||
Log::warning('This method is obsolete.');
|
|
||||||
// abuse chart properties:
|
// abuse chart properties:
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($account->id);
|
$cache->addProperty($account->id);
|
||||||
@@ -257,6 +261,7 @@ class Steam
|
|||||||
*/
|
*/
|
||||||
public function balanceInRangeConverted(Account $account, Carbon $start, Carbon $end, TransactionCurrency $native): array
|
public function balanceInRangeConverted(Account $account, Carbon $start, Carbon $end, TransactionCurrency $native): array
|
||||||
{
|
{
|
||||||
|
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($account->id);
|
$cache->addProperty($account->id);
|
||||||
$cache->addProperty('balance-in-range-converted');
|
$cache->addProperty('balance-in-range-converted');
|
||||||
@@ -381,6 +386,7 @@ class Steam
|
|||||||
*/
|
*/
|
||||||
public function balanceConverted(Account $account, Carbon $date, TransactionCurrency $native): string
|
public function balanceConverted(Account $account, Carbon $date, TransactionCurrency $native): string
|
||||||
{
|
{
|
||||||
|
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
|
||||||
Log::debug(sprintf('Now in balanceConverted (%s) for account #%d, converting to %s', $date->format('Y-m-d'), $account->id, $native->code));
|
Log::debug(sprintf('Now in balanceConverted (%s) for account #%d, converting to %s', $date->format('Y-m-d'), $account->id, $native->code));
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($account->id);
|
$cache->addProperty($account->id);
|
||||||
@@ -390,7 +396,7 @@ class Steam
|
|||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
Log::debug('Cached!');
|
Log::debug('Cached!');
|
||||||
|
|
||||||
// return $cache->get();
|
return $cache->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var AccountRepositoryInterface $repository */
|
/** @var AccountRepositoryInterface $repository */
|
||||||
@@ -520,6 +526,7 @@ class Steam
|
|||||||
*/
|
*/
|
||||||
public function balancesByAccounts(Collection $accounts, Carbon $date): array
|
public function balancesByAccounts(Collection $accounts, Carbon $date): array
|
||||||
{
|
{
|
||||||
|
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
|
||||||
$ids = $accounts->pluck('id')->toArray();
|
$ids = $accounts->pluck('id')->toArray();
|
||||||
// cache this property.
|
// cache this property.
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
@@ -550,6 +557,7 @@ class Steam
|
|||||||
*/
|
*/
|
||||||
public function balancesByAccountsConverted(Collection $accounts, Carbon $date): array
|
public function balancesByAccountsConverted(Collection $accounts, Carbon $date): array
|
||||||
{
|
{
|
||||||
|
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
|
||||||
$ids = $accounts->pluck('id')->toArray();
|
$ids = $accounts->pluck('id')->toArray();
|
||||||
// cache this property.
|
// cache this property.
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
@@ -557,7 +565,7 @@ class Steam
|
|||||||
$cache->addProperty('balances-converted');
|
$cache->addProperty('balances-converted');
|
||||||
$cache->addProperty($date);
|
$cache->addProperty($date);
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
// return $cache->get();
|
return $cache->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to do this per account.
|
// need to do this per account.
|
||||||
@@ -583,6 +591,7 @@ class Steam
|
|||||||
*/
|
*/
|
||||||
public function balancesPerCurrencyByAccounts(Collection $accounts, Carbon $date): array
|
public function balancesPerCurrencyByAccounts(Collection $accounts, Carbon $date): array
|
||||||
{
|
{
|
||||||
|
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
|
||||||
$ids = $accounts->pluck('id')->toArray();
|
$ids = $accounts->pluck('id')->toArray();
|
||||||
// cache this property.
|
// cache this property.
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
@@ -608,6 +617,7 @@ class Steam
|
|||||||
|
|
||||||
public function balancePerCurrency(Account $account, Carbon $date): array
|
public function balancePerCurrency(Account $account, Carbon $date): array
|
||||||
{
|
{
|
||||||
|
Log::warning(sprintf('Deprecated method %s, do not use.', __METHOD__));
|
||||||
// abuse chart properties:
|
// abuse chart properties:
|
||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty($account->id);
|
$cache->addProperty($account->id);
|
||||||
|
Reference in New Issue
Block a user