mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-03 03:00:14 +00:00
Fix sort params
This commit is contained in:
@@ -67,7 +67,6 @@ abstract class Controller extends BaseController
|
||||
protected array $accepts = ['application/json', 'application/vnd.api+json'];
|
||||
|
||||
/** @var array<int, string> */
|
||||
protected array $allowedSort;
|
||||
protected bool $convertToPrimary = false;
|
||||
protected TransactionCurrency $primaryCurrency;
|
||||
protected ParameterBag $parameters;
|
||||
@@ -78,7 +77,6 @@ abstract class Controller extends BaseController
|
||||
public function __construct()
|
||||
{
|
||||
// get global parameters
|
||||
$this->allowedSort = config('firefly.allowed_sort_parameters');
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->parameters = $this->getParameters();
|
||||
@@ -150,13 +148,7 @@ abstract class Controller extends BaseController
|
||||
}
|
||||
if (null !== $value) {
|
||||
$value = (int)$value;
|
||||
if ($value < 1) {
|
||||
$value = 1;
|
||||
}
|
||||
if ($value > 2 ** 16) {
|
||||
$value = 2 ** 16;
|
||||
}
|
||||
|
||||
$value = min(max(1, $value), 2 ** 16);
|
||||
$bag->set($integer, $value);
|
||||
}
|
||||
if (null === $value
|
||||
@@ -173,39 +165,8 @@ abstract class Controller extends BaseController
|
||||
}
|
||||
|
||||
// sort fields:
|
||||
return $this->getSortParameters($bag);
|
||||
}
|
||||
|
||||
private function getSortParameters(ParameterBag $bag): ParameterBag
|
||||
{
|
||||
$sortParameters = [];
|
||||
|
||||
try {
|
||||
$param = (string)request()->query->get('sort');
|
||||
} catch (BadRequestException $e) {
|
||||
Log::error('Request field "sort" contains a non-scalar value. Value set to NULL.');
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
$param = '';
|
||||
}
|
||||
if ('' === $param) {
|
||||
return $bag;
|
||||
}
|
||||
$parts = explode(',', $param);
|
||||
foreach ($parts as $part) {
|
||||
$part = trim($part);
|
||||
$direction = 'asc';
|
||||
if ('-' === $part[0]) {
|
||||
$part = substr($part, 1);
|
||||
$direction = 'desc';
|
||||
}
|
||||
if (in_array($part, $this->allowedSort, true)) {
|
||||
$sortParameters[] = [$part, $direction];
|
||||
}
|
||||
}
|
||||
$bag->set('sort', $sortParameters);
|
||||
|
||||
return $bag;
|
||||
//return $this->getSortParameters($bag);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -82,17 +82,19 @@ class ShowController extends Controller
|
||||
|
||||
// get list of accounts. Count it and split it.
|
||||
$this->repository->resetAccountOrder();
|
||||
// TODO fix sort.
|
||||
$collection = $this->repository->getAccountsByType($types);
|
||||
$collection = $this->repository->getAccountsByType($types, $params['sort']);
|
||||
$count = $collection->count();
|
||||
|
||||
// continue sort:
|
||||
// TODO if the user sorts on DB dependent field there must be no slice before enrichment, only after.
|
||||
// TODO still need to figure out how to do this easily.
|
||||
$accounts = $collection->slice(($this->parameters->get('page') - 1) * $params['limit'], $params['limit']);
|
||||
|
||||
// enrich
|
||||
/** @var User $admin */
|
||||
$admin = auth()->user();
|
||||
$enrichment = new AccountEnrichment();
|
||||
$enrichment->setSort($params['sort']);
|
||||
$enrichment->setDate($this->parameters->get('date'));
|
||||
$enrichment->setStart($this->parameters->get('start'));
|
||||
$enrichment->setEnd($this->parameters->get('end'));
|
||||
|
@@ -24,7 +24,9 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Api\V1\Requests\Models\Account;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Rules\IsValidSortInstruction;
|
||||
use FireflyIII\Support\Facades\Preferences;
|
||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
@@ -55,7 +57,7 @@ class ShowRequest extends FormRequest
|
||||
return [
|
||||
'type' => $this->convertString('type', 'all'),
|
||||
'limit' => $limit,
|
||||
'sort' => $this->convertString('sort', 'order'),
|
||||
'sort' => $this->convertSortParameters('sort',Account::class),
|
||||
'page' => $page,
|
||||
];
|
||||
}
|
||||
@@ -68,7 +70,7 @@ class ShowRequest extends FormRequest
|
||||
'date' => 'date',
|
||||
'start' => 'date|present_with:end|before_or_equal:end|before:2038-01-17|after:1970-01-02',
|
||||
'end' => 'date|present_with:start|after_or_equal:start|before:2038-01-17|after:1970-01-02',
|
||||
'sort' => 'nullable|in:active,iban,name,order,-active,-iban,-name,-order', // TODO improve me.
|
||||
'sort' => ['nullable', new IsValidSortInstruction(Account::class)],
|
||||
'type' => sprintf('in:%s', $keys),
|
||||
'limit' => 'numeric|min:1|max:131337',
|
||||
'page' => 'numeric|min:1|max:131337',
|
||||
|
@@ -484,14 +484,19 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac
|
||||
$query->accountTypeIn($types);
|
||||
}
|
||||
|
||||
// add sort parameters. At this point they're filtered to allowed fields to sort by:
|
||||
// add sort parameters
|
||||
$allowed = config('firefly.allowed_db_sort_parameters.Account', []);
|
||||
$sorted = 0;
|
||||
if (0 !== count($sort)) {
|
||||
foreach ($sort as $param) {
|
||||
$query->orderBy($param[0], $param[1]);
|
||||
if(in_array($param[0], $allowed, true)) {
|
||||
$query->orderBy($param[0], $param[1]);
|
||||
++$sorted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 === count($sort)) {
|
||||
if (0 === $sorted) {
|
||||
if (0 !== count($res)) {
|
||||
$query->orderBy('accounts.order', 'ASC');
|
||||
}
|
||||
|
64
app/Rules/IsValidSortInstruction.php
Normal file
64
app/Rules/IsValidSortInstruction.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/*
|
||||
* IsValidSortInstruction.php
|
||||
* Copyright (c) 2025 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\Rules;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
|
||||
class IsValidSortInstruction implements ValidationRule
|
||||
{
|
||||
private string $class;
|
||||
|
||||
public function __construct(string $class)
|
||||
{
|
||||
$this->class = $class;
|
||||
}
|
||||
|
||||
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||
{
|
||||
$shortClass = str_replace('FireflyIII\\Models\\', '', $this->class);
|
||||
if (!is_string($value)) {
|
||||
$fail('validation.invalid_sort_instruction')->translate(['object' => $shortClass]);
|
||||
return;
|
||||
}
|
||||
$validParameters = config(sprintf('firefly.allowed_sort_parameters.%s', $shortClass));
|
||||
if (!is_array($validParameters)) {
|
||||
$fail('validation.no_sort_instructions')->translate(['object' => $shortClass]);
|
||||
return;
|
||||
}
|
||||
$parts = explode(',', $value);
|
||||
foreach ($parts as $i => $part) {
|
||||
$part = trim($part);
|
||||
if (strlen($part) < 2) {
|
||||
$fail('validation.invalid_sort_instruction_index')->translate(['index' => $i, 'object' => $shortClass]);
|
||||
return;
|
||||
}
|
||||
if ('-' === $part[0]) {
|
||||
$part = substr($part, 1);
|
||||
}
|
||||
if (!in_array($part, $validParameters, true)) {
|
||||
$fail('validation.invalid_sort_instruction_index')->translate(['index' => $i, 'object' => $shortClass]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -75,6 +75,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
private array $endBalances = [];
|
||||
private array $objectGroups = [];
|
||||
private array $mappedObjects = [];
|
||||
private array $sort = [];
|
||||
|
||||
/**
|
||||
* TODO The account enricher must do conversion from and to the primary currency.
|
||||
@@ -115,6 +116,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
$this->collectObjectGroups();
|
||||
$this->collectBalances();
|
||||
$this->appendCollectedData();
|
||||
$this->sortData();
|
||||
|
||||
return $this->collection;
|
||||
}
|
||||
@@ -142,10 +144,9 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
|
||||
private function collectMetaData(): void
|
||||
{
|
||||
$set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'BIC', 'liability_direction', 'interest', 'interest_period', 'current_debt'])
|
||||
->whereIn('account_id', $this->ids)
|
||||
->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray()
|
||||
;
|
||||
$set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'BIC', 'liability_direction', 'interest', 'interest_period', 'current_debt'])
|
||||
->whereIn('account_id', $this->ids)
|
||||
->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray();
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($set as $entry) {
|
||||
@@ -171,10 +172,9 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Account::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Account::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||
}
|
||||
@@ -184,15 +184,14 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
private function collectLocations(): void
|
||||
{
|
||||
$locations = Location::query()->whereIn('locatable_id', $this->ids)
|
||||
->where('locatable_type', Account::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray()
|
||||
;
|
||||
->where('locatable_type', Account::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray();
|
||||
foreach ($locations as $location) {
|
||||
$this->locations[(int)$location['locatable_id']]
|
||||
= [
|
||||
'latitude' => (float)$location['latitude'],
|
||||
'longitude' => (float)$location['longitude'],
|
||||
'zoom_level' => (int)$location['zoom_level'],
|
||||
];
|
||||
'latitude' => (float)$location['latitude'],
|
||||
'longitude' => (float)$location['longitude'],
|
||||
'zoom_level' => (int)$location['zoom_level'],
|
||||
];
|
||||
}
|
||||
Log::debug(sprintf('Enrich with %d locations(s)', count($this->locations)));
|
||||
}
|
||||
@@ -207,20 +206,19 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
->setUserGroup($this->userGroup)
|
||||
->setAccounts($this->collection)
|
||||
->withAccountInformation()
|
||||
->setTypes([TransactionTypeEnum::OPENING_BALANCE->value])
|
||||
;
|
||||
$journals = $collector->getExtractedJournals();
|
||||
->setTypes([TransactionTypeEnum::OPENING_BALANCE->value]);
|
||||
$journals = $collector->getExtractedJournals();
|
||||
foreach ($journals as $journal) {
|
||||
$this->openingBalances[(int)$journal['source_account_id']]
|
||||
= [
|
||||
'amount' => Steam::negative($journal['amount']),
|
||||
'date' => $journal['date'],
|
||||
];
|
||||
'amount' => Steam::negative($journal['amount']),
|
||||
'date' => $journal['date'],
|
||||
];
|
||||
$this->openingBalances[(int)$journal['destination_account_id']]
|
||||
= [
|
||||
'amount' => Steam::positive($journal['amount']),
|
||||
'date' => $journal['date'],
|
||||
];
|
||||
'amount' => Steam::positive($journal['amount']),
|
||||
'date' => $journal['date'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,9 +236,9 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$this->collection = $this->collection->map(function (Account $item) {
|
||||
$id = (int)$item->id;
|
||||
$item->full_account_type = $this->accountTypes[(int)$item->account_type_id] ?? null;
|
||||
$meta = [
|
||||
$id = (int)$item->id;
|
||||
$item->full_account_type = $this->accountTypes[(int)$item->account_type_id] ?? null;
|
||||
$meta = [
|
||||
'currency' => null,
|
||||
'location' => [
|
||||
'latitude' => null,
|
||||
@@ -287,30 +285,30 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
|
||||
// add balances
|
||||
// get currencies:
|
||||
$currency = $this->primaryCurrency; // assume primary currency
|
||||
$currency = $this->primaryCurrency; // assume primary currency
|
||||
if (null !== $meta['currency']) {
|
||||
$currency = $meta['currency'];
|
||||
}
|
||||
|
||||
// get the current balance:
|
||||
$date = $this->getDate();
|
||||
$date = $this->getDate();
|
||||
// $finalBalance = Steam::finalAccountBalance($item, $date, $this->primaryCurrency, $this->convertToPrimary);
|
||||
$finalBalance = $this->balances[$id];
|
||||
$balanceDifference = $this->getBalanceDifference($id, $currency);
|
||||
$finalBalance = $this->balances[$id];
|
||||
$balanceDifference = $this->getBalanceDifference($id, $currency);
|
||||
Log::debug(sprintf('Call finalAccountBalance(%s) with date/time "%s"', var_export($this->convertToPrimary, true), $date->toIso8601String()), $finalBalance);
|
||||
|
||||
// collect current balances:
|
||||
$currentBalance = Steam::bcround($finalBalance[$currency->code] ?? '0', $currency->decimal_places);
|
||||
$openingBalance = Steam::bcround($meta['opening_balance_amount'] ?? '0', $currency->decimal_places);
|
||||
$virtualBalance = Steam::bcround($account->virtual_balance ?? '0', $currency->decimal_places);
|
||||
$debtAmount = $meta['current_debt'] ?? null;
|
||||
$currentBalance = Steam::bcround($finalBalance[$currency->code] ?? '0', $currency->decimal_places);
|
||||
$openingBalance = Steam::bcround($meta['opening_balance_amount'] ?? '0', $currency->decimal_places);
|
||||
$virtualBalance = Steam::bcround($account->virtual_balance ?? '0', $currency->decimal_places);
|
||||
$debtAmount = $meta['current_debt'] ?? null;
|
||||
|
||||
// set some pc_ default values to NULL:
|
||||
$pcCurrentBalance = null;
|
||||
$pcOpeningBalance = null;
|
||||
$pcVirtualBalance = null;
|
||||
$pcDebtAmount = null;
|
||||
$pcBalanceDifference = null;
|
||||
$pcCurrentBalance = null;
|
||||
$pcOpeningBalance = null;
|
||||
$pcVirtualBalance = null;
|
||||
$pcDebtAmount = null;
|
||||
$pcBalanceDifference = null;
|
||||
|
||||
// convert to primary currency if needed:
|
||||
if ($this->convertToPrimary && $currency->id !== $this->primaryCurrency->id) {
|
||||
@@ -349,7 +347,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
'pc_balance_difference' => $pcBalanceDifference,
|
||||
];
|
||||
// end add balances
|
||||
$item->meta = $meta;
|
||||
$item->meta = $meta;
|
||||
|
||||
return $item;
|
||||
});
|
||||
@@ -371,13 +369,12 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
|
||||
private function collectObjectGroups(): void
|
||||
{
|
||||
$set = DB::table('object_groupables')
|
||||
->whereIn('object_groupable_id', $this->ids)
|
||||
->where('object_groupable_type', Account::class)
|
||||
->get(['object_groupable_id', 'object_group_id'])
|
||||
;
|
||||
$set = DB::table('object_groupables')
|
||||
->whereIn('object_groupable_id', $this->ids)
|
||||
->where('object_groupable_type', Account::class)
|
||||
->get(['object_groupable_id', 'object_group_id']);
|
||||
|
||||
$ids = array_unique($set->pluck('object_group_id')->toArray());
|
||||
$ids = array_unique($set->pluck('object_group_id')->toArray());
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$this->mappedObjects[(int)$entry->object_groupable_id] = (int)$entry->object_group_id;
|
||||
@@ -429,9 +426,36 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
if (0 === count($startBalance) || 0 === count($endBalance)) {
|
||||
return null;
|
||||
}
|
||||
$start = $startBalance[$currency->code] ?? '0';
|
||||
$end = $endBalance[$currency->code] ?? '0';
|
||||
$start = $startBalance[$currency->code] ?? '0';
|
||||
$end = $endBalance[$currency->code] ?? '0';
|
||||
|
||||
return bcsub($end, $start);
|
||||
}
|
||||
|
||||
public function setSort(array $sort): void
|
||||
{
|
||||
$this->sort = $sort;
|
||||
}
|
||||
|
||||
private function sortData(): void
|
||||
{
|
||||
$dbParams = config('firefly.allowed_db_sort_parameters.Account', []);
|
||||
/** @var array<string,string> $parameter */
|
||||
foreach ($this->sort as $parameter) {
|
||||
if (in_array($parameter[0], $dbParams, true)) {
|
||||
continue;
|
||||
}
|
||||
switch ($parameter[0]) {
|
||||
default:
|
||||
throw new FireflyException(sprintf('Account enrichment cannot sort on field "%s"', $parameter[0]));
|
||||
case 'current_balance':
|
||||
case 'pc_current_balance':
|
||||
$this->collection = $this->collection->sortBy(static function (Account $account) use ($parameter) {
|
||||
return $account->meta['balances'][$parameter[0]] ?? '0';
|
||||
}, SORT_NUMERIC, 'desc' === $parameter[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -31,7 +31,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use function Safe\preg_replace;
|
||||
|
||||
/**
|
||||
@@ -99,6 +98,24 @@ trait ConvertsDataTypes
|
||||
return Steam::filterSpaces($string);
|
||||
}
|
||||
|
||||
public function convertSortParameters(string $field, string $class): array
|
||||
{
|
||||
// assume this all works, because the validator would have caught any errors.
|
||||
$parameter = (string)request()->query->get($field);
|
||||
$parts = explode(',', $parameter);
|
||||
$sortParameters = [];
|
||||
foreach ($parts as $part) {
|
||||
$part = trim($part);
|
||||
$direction = 'asc';
|
||||
if ('-' === $part[0]) {
|
||||
$part = substr($part, 1);
|
||||
$direction = 'desc';
|
||||
}
|
||||
$sortParameters[] = [$part, $direction];
|
||||
}
|
||||
return $sortParameters;
|
||||
}
|
||||
|
||||
public function clearString(?string $string): ?string
|
||||
{
|
||||
$string = $this->clearStringKeepNewlines($string);
|
||||
@@ -129,7 +146,7 @@ trait ConvertsDataTypes
|
||||
// clear zalgo text (TODO also in API v2)
|
||||
$string = preg_replace('/(\pM{2})\pM+/u', '\1', $string);
|
||||
|
||||
return trim((string) $string);
|
||||
return trim((string)$string);
|
||||
}
|
||||
|
||||
public function convertIban(string $field): string
|
||||
@@ -147,7 +164,7 @@ trait ConvertsDataTypes
|
||||
return $default;
|
||||
}
|
||||
|
||||
return (string) $this->clearString((string) $entry);
|
||||
return (string)$this->clearString((string)$entry);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,7 +178,7 @@ trait ConvertsDataTypes
|
||||
*/
|
||||
public function convertInteger(string $field): int
|
||||
{
|
||||
return (int) $this->get($field);
|
||||
return (int)$this->get($field);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,7 +203,7 @@ trait ConvertsDataTypes
|
||||
$collection = new Collection();
|
||||
if (is_array($set)) {
|
||||
foreach ($set as $accountId) {
|
||||
$account = $repository->find((int) $accountId);
|
||||
$account = $repository->find((int)$accountId);
|
||||
if (null !== $account) {
|
||||
$collection->push($account);
|
||||
}
|
||||
@@ -201,7 +218,7 @@ trait ConvertsDataTypes
|
||||
*/
|
||||
public function stringWithNewlines(string $field): string
|
||||
{
|
||||
return (string) $this->clearStringKeepNewlines((string) ($this->get($field) ?? ''));
|
||||
return (string)$this->clearStringKeepNewlines((string)($this->get($field) ?? ''));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -245,14 +262,14 @@ trait ConvertsDataTypes
|
||||
|
||||
protected function convertDateTime(?string $string): ?Carbon
|
||||
{
|
||||
$value = $this->get((string) $string);
|
||||
$value = $this->get((string)$string);
|
||||
if (null === $value) {
|
||||
return null;
|
||||
}
|
||||
if ('' === $value) {
|
||||
return null;
|
||||
}
|
||||
if (10 === strlen((string) $value)) {
|
||||
if (10 === strlen((string)$value)) {
|
||||
// probably a date format.
|
||||
try {
|
||||
$carbon = Carbon::createFromFormat('Y-m-d', $value, config('app.timezone'));
|
||||
@@ -300,7 +317,7 @@ trait ConvertsDataTypes
|
||||
return null;
|
||||
}
|
||||
|
||||
return (float) $res;
|
||||
return (float)$res;
|
||||
}
|
||||
|
||||
protected function dateFromValue(?string $string): ?Carbon
|
||||
@@ -338,7 +355,7 @@ trait ConvertsDataTypes
|
||||
return null;
|
||||
}
|
||||
|
||||
return (float) $string;
|
||||
return (float)$string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -375,10 +392,10 @@ trait ConvertsDataTypes
|
||||
{
|
||||
$result = null;
|
||||
|
||||
Log::debug(sprintf('Date string is "%s"', (string) $this->get($field)));
|
||||
Log::debug(sprintf('Date string is "%s"', (string)$this->get($field)));
|
||||
|
||||
try {
|
||||
$result = '' !== (string) $this->get($field) ? new Carbon((string) $this->get($field), config('app.timezone')) : null;
|
||||
$result = '' !== (string)$this->get($field) ? new Carbon((string)$this->get($field), config('app.timezone')) : null;
|
||||
} catch (InvalidFormatException) {
|
||||
// @ignoreException
|
||||
Log::debug(sprintf('Exception when parsing date "%s".', $this->get($field)));
|
||||
@@ -399,12 +416,12 @@ trait ConvertsDataTypes
|
||||
return null;
|
||||
}
|
||||
|
||||
$value = (string) $this->get($field);
|
||||
$value = (string)$this->get($field);
|
||||
if ('' === $value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (int) $value;
|
||||
return (int)$value;
|
||||
}
|
||||
|
||||
protected function parseAccounts(mixed $array): array
|
||||
@@ -417,9 +434,9 @@ trait ConvertsDataTypes
|
||||
if (!is_array($entry)) {
|
||||
continue;
|
||||
}
|
||||
$amount = null;
|
||||
$amount = null;
|
||||
if (array_key_exists('current_amount', $entry)) {
|
||||
$amount = $this->clearString((string) ($entry['current_amount'] ?? '0'));
|
||||
$amount = $this->clearString((string)($entry['current_amount'] ?? '0'));
|
||||
if (null === $entry['current_amount']) {
|
||||
$amount = null;
|
||||
}
|
||||
@@ -428,7 +445,7 @@ trait ConvertsDataTypes
|
||||
$amount = null;
|
||||
}
|
||||
$return[] = [
|
||||
'account_id' => $this->integerFromValue((string) ($entry['account_id'] ?? '0')),
|
||||
'account_id' => $this->integerFromValue((string)($entry['account_id'] ?? '0')),
|
||||
'current_amount' => $amount,
|
||||
];
|
||||
}
|
||||
@@ -448,6 +465,6 @@ trait ConvertsDataTypes
|
||||
return null;
|
||||
}
|
||||
|
||||
return (int) $string;
|
||||
return (int)$string;
|
||||
}
|
||||
}
|
||||
|
@@ -182,12 +182,12 @@ return [
|
||||
'darkMode' => 'browser',
|
||||
'list_length' => 10, // to be removed if v1 is cancelled.
|
||||
'default_preferences' => [
|
||||
'frontpageAccounts' => [],
|
||||
'listPageSize' => 50,
|
||||
'currencyPreference' => 'EUR',
|
||||
'language' => 'en_US',
|
||||
'locale' => 'equal',
|
||||
'convertToPrimary' => false,
|
||||
'frontpageAccounts' => [],
|
||||
'listPageSize' => 50,
|
||||
'currencyPreference' => 'EUR',
|
||||
'language' => 'en_US',
|
||||
'locale' => 'equal',
|
||||
'convertToPrimary' => false,
|
||||
],
|
||||
'default_currency' => 'EUR',
|
||||
'default_language' => envNonEmpty('DEFAULT_LANGUAGE', 'en_US'),
|
||||
@@ -407,7 +407,7 @@ return [
|
||||
],
|
||||
|
||||
|
||||
'rule-actions' => [
|
||||
'rule-actions' => [
|
||||
'set_category' => SetCategory::class,
|
||||
'clear_category' => ClearCategory::class,
|
||||
'set_budget' => SetBudget::class,
|
||||
@@ -441,7 +441,7 @@ return [
|
||||
// 'set_foreign_amount' => SetForeignAmount::class,
|
||||
// 'set_foreign_currency' => SetForeignCurrency::class,
|
||||
],
|
||||
'context-rule-actions' => [
|
||||
'context-rule-actions' => [
|
||||
'set_category',
|
||||
'set_budget',
|
||||
'add_tag',
|
||||
@@ -460,13 +460,13 @@ return [
|
||||
'convert_transfer',
|
||||
],
|
||||
|
||||
'test-triggers' => [
|
||||
'test-triggers' => [
|
||||
'limit' => 10,
|
||||
'range' => 200,
|
||||
],
|
||||
|
||||
// expected source types for each transaction type, in order of preference.
|
||||
'expected_source_types' => [
|
||||
'expected_source_types' => [
|
||||
'source' => [
|
||||
TransactionTypeEnum::WITHDRAWAL->value => [AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value],
|
||||
TransactionTypeEnum::DEPOSIT->value => [AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::REVENUE->value, AccountTypeEnum::CASH->value],
|
||||
@@ -511,7 +511,7 @@ return [
|
||||
TransactionTypeEnum::LIABILITY_CREDIT->value => [AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value],
|
||||
],
|
||||
],
|
||||
'allowed_opposing_types' => [
|
||||
'allowed_opposing_types' => [
|
||||
'source' => [
|
||||
AccountTypeEnum::ASSET->value => [
|
||||
AccountTypeEnum::ASSET->value,
|
||||
@@ -601,7 +601,7 @@ return [
|
||||
],
|
||||
],
|
||||
// depending on the account type, return the allowed transaction types:
|
||||
'allowed_transaction_types' => [
|
||||
'allowed_transaction_types' => [
|
||||
'source' => [
|
||||
AccountTypeEnum::ASSET->value => [
|
||||
TransactionTypeEnum::WITHDRAWAL->value,
|
||||
@@ -670,7 +670,7 @@ return [
|
||||
],
|
||||
|
||||
// having the source + dest will tell you the transaction type.
|
||||
'account_to_transaction' => [
|
||||
'account_to_transaction' => [
|
||||
AccountTypeEnum::ASSET->value => [
|
||||
AccountTypeEnum::ASSET->value => TransactionTypeEnum::TRANSFER->value,
|
||||
AccountTypeEnum::CASH->value => TransactionTypeEnum::WITHDRAWAL->value,
|
||||
@@ -735,7 +735,7 @@ return [
|
||||
],
|
||||
|
||||
// allowed source -> destination accounts.
|
||||
'source_dests' => [
|
||||
'source_dests' => [
|
||||
TransactionTypeEnum::WITHDRAWAL->value => [
|
||||
AccountTypeEnum::ASSET->value => [AccountTypeEnum::EXPENSE->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::CASH->value],
|
||||
AccountTypeEnum::LOAN->value => [AccountTypeEnum::EXPENSE->value, AccountTypeEnum::CASH->value],
|
||||
@@ -774,7 +774,7 @@ return [
|
||||
],
|
||||
],
|
||||
// if you add fields to this array, don't forget to update the export routine (ExportDataGenerator).
|
||||
'journal_meta_fields' => [
|
||||
'journal_meta_fields' => [
|
||||
// sepa
|
||||
'sepa_cc',
|
||||
'sepa_ct_op',
|
||||
@@ -808,31 +808,47 @@ return [
|
||||
'recurrence_count',
|
||||
'recurrence_date',
|
||||
],
|
||||
'webhooks' => [
|
||||
'webhooks' => [
|
||||
'max_attempts' => env('WEBHOOK_MAX_ATTEMPTS', 3),
|
||||
],
|
||||
'can_have_virtual_amounts' => [AccountTypeEnum::ASSET->value],
|
||||
'can_have_opening_balance' => [AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value],
|
||||
'dynamic_creation_allowed' => [
|
||||
'can_have_virtual_amounts' => [AccountTypeEnum::ASSET->value],
|
||||
'can_have_opening_balance' => [AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value],
|
||||
'dynamic_creation_allowed' => [
|
||||
AccountTypeEnum::EXPENSE->value,
|
||||
AccountTypeEnum::REVENUE->value,
|
||||
AccountTypeEnum::INITIAL_BALANCE->value,
|
||||
AccountTypeEnum::RECONCILIATION->value,
|
||||
AccountTypeEnum::LIABILITY_CREDIT->value,
|
||||
],
|
||||
'valid_asset_fields' => ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
|
||||
'valid_cc_fields' => ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
|
||||
'valid_account_fields' => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'],
|
||||
'valid_asset_fields' => ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
|
||||
'valid_cc_fields' => ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
|
||||
'valid_account_fields' => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'],
|
||||
|
||||
// dynamic date ranges are as follows:
|
||||
'dynamic_date_ranges' => ['last7', 'last30', 'last90', 'last365', 'MTD', 'QTD', 'YTD'],
|
||||
'dynamic_date_ranges' => ['last7', 'last30', 'last90', 'last365', 'MTD', 'QTD', 'YTD'],
|
||||
|
||||
'allowed_sort_parameters' => [
|
||||
'Account' => ['id', 'order', 'name', 'iban', 'active', 'account_type_id',
|
||||
'current_balance',
|
||||
'pc_current_balance',
|
||||
'opening_balance',
|
||||
'pc_opening_balance',
|
||||
'virtual_balance',
|
||||
'pc_virtual_balance',
|
||||
'debt_amount',
|
||||
'pc_debt_amount',
|
||||
'balance_difference',
|
||||
'pc_balance_difference',
|
||||
],
|
||||
],
|
||||
'allowed_db_sort_parameters' => [
|
||||
'Account' => ['id', 'order', 'name', 'iban', 'active', 'account_type_id'],
|
||||
],
|
||||
|
||||
// only used in v1
|
||||
'allowed_sort_parameters' => ['order', 'name', 'iban'],
|
||||
|
||||
// preselected account lists possibilities:
|
||||
'preselected_accounts' => ['all', 'assets', 'liabilities'],
|
||||
'preselected_accounts' => ['all', 'assets', 'liabilities'],
|
||||
|
||||
// allowed to store a piggy bank in:
|
||||
'piggy_bank_account_types' => [AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value],
|
||||
'piggy_bank_account_types' => [AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value],
|
||||
];
|
||||
|
@@ -24,6 +24,9 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
'invalid_sort_instruction' => 'The sort instruction is invalid for an object of type ":object".',
|
||||
'invalid_sort_instruction_index' => 'The sort instruction at index #:index is invalid for an object of type ":object".',
|
||||
'no_sort_instructions' => 'There are no sort instructions defined for an object of type ":object".',
|
||||
'webhook_budget_info' => 'Cannot deliver budget information for transaction related webhooks.',
|
||||
'webhook_account_info' => 'Cannot deliver account information for budget related webhooks.',
|
||||
'webhook_transaction_info' => 'Cannot deliver transaction information for budget related webhooks.',
|
||||
|
Reference in New Issue
Block a user