Compare commits

..

31 Commits

Author SHA1 Message Date
github-actions
03be2704ce Auto commit for release 'develop' on 2024-05-16 2024-05-16 05:10:41 +02:00
James Cole
0638d109d0 Clean up code. 2024-05-13 20:31:52 +02:00
github-actions
cb5d856769 Auto commit for release 'develop' on 2024-05-13 2024-05-13 05:10:16 +02:00
James Cole
04fe5d1fc4 Correct account balances better. 2024-05-12 18:24:38 +02:00
James Cole
45e9d4f8de Fix auto complete 2024-05-12 17:50:54 +02:00
James Cole
73fdbb6202 Update API endpoints and account autocomplete. 2024-05-12 13:31:33 +02:00
James Cole
e49dbefddd Make the combined combination unique. 2024-05-12 08:10:12 +02:00
James Cole
fc5143337a Add a title to the table, so multiple balances per account are possible. 2024-05-12 08:09:50 +02:00
James Cole
4b3eb6dace Rename command. 2024-05-12 06:26:50 +02:00
James Cole
c741b2a819 Add related models. 2024-05-12 06:25:13 +02:00
James Cole
cebfaa32bf Add routine that caches account balances. Add it to the /flush routine as well. 2024-05-12 06:24:11 +02:00
James Cole
d356d39d43 add account balances with some random data 2024-05-11 20:32:25 +02:00
James Cole
7d9f22d3f4 Merge branch 'api' into develop
# Conflicts:
#	app/JsonApi/V3/Accounts/AccountRepository.php
#	app/JsonApi/V3/Accounts/AccountResource.php
#	app/JsonApi/V3/Accounts/Capabilities/AccountQuery.php
#	app/JsonApi/V3/Users/UserSchema.php
2024-05-10 12:52:44 +02:00
James Cole
c6c8f282e2 Restore previous stuff 2024-05-10 12:51:02 +02:00
James Cole
6a64420721 Refactor resources 2024-05-10 09:42:09 +02:00
James Cole
fcde4e2488 no message 2024-05-10 09:41:53 +02:00
James Cole
aa5c4c20e9 Various messy code. 2024-05-10 09:17:09 +02:00
James Cole
794e31e487 Add some experimental account endpoints using a package 2024-05-10 06:43:18 +02:00
James Cole
16bf186312 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop
# Conflicts:
#	composer.lock
2024-05-10 06:42:47 +02:00
James Cole
45c722e786 Add config, merge later. 2024-05-10 06:36:57 +02:00
github-actions
36d9e5c3fe Auto commit for release 'develop' on 2024-05-09 2024-05-09 05:10:13 +02:00
James Cole
8d614de67f Possible fix for https://github.com/firefly-iii/firefly-iii/issues/8867 2024-05-08 21:55:14 +02:00
James Cole
d17da670ab Fix connect exception, add some debug logs. 2024-05-06 06:33:12 +02:00
github-actions
5bf4df9ad8 Auto commit for release 'develop' on 2024-05-06 2024-05-06 05:10:30 +02:00
James Cole
07db6b59ce Fix webhooks overview. 2024-05-02 06:15:41 +02:00
github-actions
e16f1cf4ee Auto commit for release 'develop' on 2024-05-02 2024-05-02 05:10:23 +02:00
James Cole
4c80d929ca Possible division by zero? 2024-05-01 06:29:28 +02:00
github-actions
16364d9859 Auto commit for release 'develop' on 2024-04-30 2024-04-30 20:33:00 +02:00
James Cole
c24f6acb2c Fix styles 2024-04-30 20:26:05 +02:00
James Cole
4bd19e0627 Expand and fix sort columns 2024-04-30 20:22:31 +02:00
James Cole
69d839997a Fix sorting and order for account lists. 2024-04-29 20:20:11 +02:00
130 changed files with 4610 additions and 1134 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -28,10 +28,11 @@ use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Autocomplete\AutocompleteRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountBalance;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Http\JsonResponse;
/**
@@ -39,11 +40,13 @@ use Illuminate\Http\JsonResponse;
*/
class AccountController extends Controller
{
use AccountFilter;
// use AccountFilter;
private AdminAccountRepositoryInterface $adminRepository;
private array $balanceTypes;
private AccountRepositoryInterface $repository;
private TransactionCurrency $default;
private ExchangeRateConverter $converter;
// private array $balanceTypes;
// private AccountRepositoryInterface $repository;
/**
* AccountController constructor.
@@ -53,14 +56,20 @@ class AccountController extends Controller
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
$this->adminRepository = app(AdminAccountRepositoryInterface::class);
$this->adminRepository->setUserGroup($this->validateUserGroup($request));
$this->adminRepository->setUserGroup($userGroup);
$this->default = app('amount')->getDefaultCurrency();
$this->converter = app(ExchangeRateConverter::class);
// $this->repository = app(AccountRepositoryInterface::class);
// $this->adminRepository->setUserGroup($this->validateUserGroup($request));
return $next($request);
}
);
$this->balanceTypes = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
// $this->balanceTypes = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
}
/**
@@ -73,59 +82,68 @@ class AccountController extends Controller
* 5. Collector uses user_group_id
*
* @throws FireflyException
* @throws FireflyException
*/
public function accounts(AutocompleteRequest $request): JsonResponse
{
$data = $request->getData();
$types = $data['types'];
$query = $data['query'];
$date = $this->parameters->get('date') ?? today(config('app.timezone'));
$result = $this->adminRepository->searchAccount((string) $query, $types, $data['limit']);
$defaultCurrency = app('amount')->getDefaultCurrency();
$groupedResult = [];
$allItems = [];
$queryParameters = $request->getParameters();
$result = $this->adminRepository->searchAccount((string) $queryParameters['query'], $queryParameters['account_types'], $queryParameters['size']);
$return = [];
/** @var Account $account */
foreach ($result as $account) {
$nameWithBalance = $account->name;
$currency = $this->repository->getAccountCurrency($account) ?? $defaultCurrency;
if (in_array($account->accountType->type, $this->balanceTypes, true)) {
$balance = app('steam')->balance($account, $date);
$nameWithBalance = sprintf('%s (%s)', $account->name, app('amount')->formatAnything($currency, $balance, false));
}
$type = (string) trans(sprintf('firefly.%s', $account->accountType->type));
$groupedResult[$type] ??= [
'group ' => $type,
'items' => [],
];
$allItems[] = [
'id' => (string) $account->id,
'value' => (string) $account->id,
'name' => $account->name,
'name_with_balance' => $nameWithBalance,
'label' => $nameWithBalance,
'type' => $account->accountType->type,
'currency_id' => (string) $currency->id,
'currency_name' => $currency->name,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
];
$return[] = $this->parseAccount($account);
}
usort(
$allItems,
static function (array $left, array $right): int {
$order = [AccountType::ASSET, AccountType::REVENUE, AccountType::EXPENSE];
$posLeft = (int) array_search($left['type'], $order, true);
$posRight = (int) array_search($right['type'], $order, true);
return response()->json($return);
}
return $posLeft - $posRight;
}
);
private function parseAccount(Account $account): array
{
$currency = $this->adminRepository->getAccountCurrency($account);
return response()->json($allItems);
return [
'id' => (string) $account->id,
'title' => $account->name,
'meta' => [
'type' => $account->accountType->type,
'currency_id' => null === $currency ? null : (string) $currency->id,
'currency_code' => $currency?->code,
'currency_symbol' => $currency?->symbol,
'currency_decimal' => $currency?->decimal_places,
'account_balances' => $this->getAccountBalances($account),
],
];
}
private function getAccountBalances(Account $account): array
{
$return = [];
$balances = $this->adminRepository->getAccountBalances($account);
/** @var AccountBalance $balance */
foreach ($balances as $balance) {
$return[] = $this->parseAccountBalance($balance);
}
return $return;
}
private function parseAccountBalance(AccountBalance $balance): array
{
$currency = $balance->transactionCurrency;
return [
'title' => $balance->title,
'native_amount' => $this->converter->convert($currency, $this->default, today(), $balance->balance),
'amount' => app('steam')->bcround($balance->balance, $currency->decimal_places),
'currency_id' => (string) $currency->id,
'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
'native_currency_id' => (string) $this->default->id,
'native_currency_code' => $this->default->code,
'native_currency_symbol' => $this->default->symbol,
'native_currency_decimal' => $this->default->decimal_places,
];
}
}

View File

@@ -30,6 +30,7 @@ use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Transformers\V2\AccountTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Log;
class IndexController extends Controller
{
@@ -63,17 +64,28 @@ class IndexController extends Controller
public function index(IndexRequest $request): JsonResponse
{
$this->repository->resetAccountOrder();
$types = $request->getAccountTypes();
$sorting = $request->getSortInstructions('accounts');
$filters = $request->getFilterInstructions('accounts');
$accounts = $this->repository->getAccountsByType($types, $sorting, $filters);
$pageSize = $this->parameters->get('limit');
$count = $accounts->count();
$accounts = $accounts->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
$transformer = new AccountTransformer();
$types = $request->getAccountTypes();
$sorting = $request->getSortInstructions('accounts');
$filters = $request->getFilterInstructions('accounts');
$accounts = $this->repository->getAccountsByType($types, $sorting, $filters);
$pageSize = $this->parameters->get('limit');
$count = $accounts->count();
// depending on the sort parameters, this list must not be split, because the
// order is calculated in the account transformer and by that time it's too late.
$first = array_key_first($sorting);
$disablePagination = in_array($first, ['last_activity', 'balance', 'balance_difference'], true);
Log::debug(sprintf('Will disable pagination in account index v2? %s', var_export($disablePagination, true)));
if (!$disablePagination) {
$accounts = $accounts->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
}
$paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page'));
$transformer = new AccountTransformer();
$this->parameters->set('disablePagination', $disablePagination);
$this->parameters->set('pageSize', $pageSize);
$this->parameters->set('sort', $sorting);
$this->parameters->set('filters', $filters);
$transformer->setParameters($this->parameters); // give params to transformer

View File

@@ -23,24 +23,59 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Autocomplete;
use FireflyIII\Enums\UserRoleEnum;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException;
use FireflyIII\JsonApi\Rules\IsValidFilter;
use FireflyIII\JsonApi\Rules\IsValidPage;
use FireflyIII\Models\AccountType;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
use LaravelJsonApi\Core\Query\QueryParameters;
use LaravelJsonApi\Validation\Rule as JsonApiRule;
use Illuminate\Support\Facades\Log;
/**
* Class AutocompleteRequest
*/
class AutocompleteRequest extends FormRequest
{
use AccountFilter;
use ChecksLogin;
use ConvertsDataTypes;
protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS];
/**
* Loops over all possible query parameters (these are shared over ALL auto complete requests)
* and returns a validated array of parameters.
*
* The advantage is a single class. But you may also submit "account types" to an endpoint that doesn't use these.
*/
public function getParameters(): array
{
$queryParameters = QueryParameters::cast($this->all());
try {
$date = Carbon::createFromFormat('Y-m-d', $queryParameters->filter()?->value('date', date('Y-m-d')), config('app.timezone'));
} catch (InvalidFormatException $e) {
Log::debug(sprintf('Invalid date format in autocomplete request. Using today: %s', $e->getMessage()));
$date = today();
}
$query = $queryParameters->filter()?->value('query', '') ?? '';
$size = (int) ($queryParameters->page()['size'] ?? 50);
$accountTypes = $this->getAccountTypeParameter($queryParameters->filter()?->value('account_types', '') ?? '');
return [
'date' => $date,
'query' => $query,
'size' => $size,
'account_types' => $accountTypes,
];
}
public function getData(): array
{
return [];
$types = $this->convertString('types');
$array = [];
if ('' !== $types) {
@@ -63,7 +98,27 @@ class AutocompleteRequest extends FormRequest
public function rules(): array
{
return [
'limit' => 'min:0|max:1337',
'fields' => JsonApiRule::notSupported(),
'filter' => ['nullable', 'array', new IsValidFilter(['query', 'date', 'account_types'])],
'include' => JsonApiRule::notSupported(),
'page' => ['nullable', 'array', new IsValidPage(['size'])],
'sort' => JsonApiRule::notSupported(),
];
}
private function getAccountTypeParameter(mixed $types): array
{
if (is_string($types) && str_contains($types, ',')) {
$types = explode(',', $types);
}
if (!is_iterable($types)) {
$types = [$types];
}
$return = [];
foreach ($types as $type) {
$return = array_merge($return, $this->mapAccountTypes($type));
}
return array_unique($return);
}
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Support\Models\AccountBalanceCalculator;
use Illuminate\Console\Command;
/**
* Class CorrectionSkeleton
*/
class CorrectAccountBalance extends Command
{
use ShowsFriendlyMessages;
protected $description = 'Recalculate all account balance amounts';
protected $signature = 'firefly-iii:correct-account-balance';
public function handle(): int
{
$this->correctBalanceAmounts();
return 0;
}
private function correctBalanceAmounts(): void
{
AccountBalanceCalculator::recalculate(null, null);
}
}

View File

@@ -74,6 +74,7 @@ class CorrectDatabase extends Command
'firefly-iii:unify-group-accounts',
'firefly-iii:trigger-credit-recalculation',
'firefly-iii:migrate-preferences',
'firefly-iii:correct-account-balance',
];
foreach ($commands as $command) {
$this->friendlyLine(sprintf('Now executing command "%s"', $command));

View File

@@ -0,0 +1,49 @@
<?php
/*
* AccountBalance.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\Entities;
use FireflyIII\Models\Account;
class AccountBalance
{
public string $id;
public string $amount;
public string $currencyId;
public static function fromArray(): self
{
$balance = new self();
$balance->id = (string) random_int(1, 1000);
$balance->name = (string) random_int(1, 1000);
$balance->amount = (string) random_int(1, 1000);
$balance->currencyId = '1';
return $balance;
}
public function getAccount(): Account
{
return Account::inRandomOrder()->first();
}
}

View File

@@ -36,6 +36,7 @@ use Illuminate\Session\TokenMismatchException;
use Illuminate\Support\Arr;
use Illuminate\Validation\ValidationException as LaravelValidationException;
use Laravel\Passport\Exceptions\OAuthServerException as LaravelOAuthException;
use LaravelJsonApi\Core\Exceptions\JsonApiException;
use League\OAuth2\Server\Exception\OAuthServerException;
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
use Symfony\Component\HttpFoundation\Response;
@@ -63,6 +64,7 @@ class Handler extends ExceptionHandler
HttpException::class,
SuspiciousOperationException::class,
BadHttpHeaderException::class,
JsonApiException::class,
];
/**

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\Transaction;
use FireflyIII\Support\Models\AccountBalanceCalculator;
/**
* Class TransactionObserver
@@ -35,4 +36,16 @@ class TransactionObserver
app('log')->debug('Observe "deleting" of a transaction.');
$transaction?->transactionJournal?->delete();
}
public function updated(Transaction $transaction): void
{
app('log')->debug('Observe "updated" of a transaction.');
AccountBalanceCalculator::recalculateForAccount($transaction->account);
}
public function created(Transaction $transaction): void
{
app('log')->debug('Observe "created" of a transaction.');
AccountBalanceCalculator::recalculateForAccount($transaction->account);
}
}

View File

@@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Api\V3\Controllers;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\JsonApi\V3\AccountBalances\AccountBalanceSchema;
use FireflyIII\Models\Account;
use Illuminate\Contracts\Support\Responsable;
use LaravelJsonApi\Core\Facades\JsonApi;
use LaravelJsonApi\Core\Responses\DataResponse;
use LaravelJsonApi\Laravel\Http\Controllers\Actions;
use LaravelJsonApi\Laravel\Http\Requests\AnonymousQuery;
class AccountController extends Controller
{
use Actions\AttachRelationship;
use Actions\Destroy;
use Actions\DetachRelationship;
use Actions\FetchMany;
use Actions\FetchOne;
use Actions\FetchRelated;
use Actions\FetchRelationship;
use Actions\Store;
use Actions\Update;
use Actions\UpdateRelationship;
public function readAccountBalances(AnonymousQuery $query, AccountBalanceSchema $schema, Account $account): Responsable
{
$schema = JsonApi::server()->schemas()->schemaFor('account-balances');
$models = $schema
->repository()
->queryAll()
->withRequest($query)
->withAccount($account)
->get()
;
return DataResponse::make($models);
}
}

View File

@@ -86,14 +86,15 @@ class DebugController extends Controller
{
app('preferences')->mark();
$request->session()->forget(['start', 'end', '_previous', 'viewRange', 'range', 'is_custom_range', 'temp-mfa-secret', 'temp-mfa-codes']);
app('log')->debug('Call cache:clear...');
Artisan::call('cache:clear');
app('log')->debug('Call config:clear...');
Artisan::call('config:clear');
app('log')->debug('Call route:clear...');
Artisan::call('route:clear');
app('log')->debug('Call twig:clean...');
Artisan::call('view:clear');
// also do some recalculations.
Artisan::call('firefly-iii:correct-account-balance');
Artisan::call('firefly-iii:trigger-credit-recalculation');
try {
Artisan::call('twig:clean');
@@ -101,7 +102,6 @@ class DebugController extends Controller
throw new FireflyException($e->getMessage(), 0, $e);
}
app('log')->debug('Call view:clear...');
Artisan::call('view:clear');
return redirect(route('index'));

View File

@@ -29,6 +29,7 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Bus\Queueable;
@@ -100,7 +101,7 @@ class DownloadExchangeRates implements ShouldQueue
try {
$res = $client->get($url);
} catch (RequestException $e) {
} catch (ConnectException|RequestException $e) {
app('log')->warning(sprintf('Trying to grab "%s" resulted in error "%d".', $url, $e->getMessage()));
return;

View File

@@ -0,0 +1,52 @@
<?php
/*
* IsValidFilter.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\JsonApi\Rules;
use Illuminate\Contracts\Validation\ValidationRule;
class IsValidFilter implements ValidationRule
{
private array $allowed;
public function __construct(array $keys)
{
$this->allowed = $keys;
}
#[\Override]
public function validate(string $attribute, mixed $value, \Closure $fail): void
{
if ('filter' !== $attribute) {
$fail('validation.bad_api_filter')->translate();
}
if (!is_array($value)) {
$value = explode(',', $value);
}
foreach ($value as $key => $val) {
if (!in_array($key, $this->allowed, true)) {
$fail('validation.bad_api_filter')->translate();
}
}
}
}

View File

@@ -0,0 +1,52 @@
<?php
/*
* IsValidFilter.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\JsonApi\Rules;
use Illuminate\Contracts\Validation\ValidationRule;
class IsValidPage implements ValidationRule
{
private array $allowed;
public function __construct(array $keys)
{
$this->allowed = $keys;
}
#[\Override]
public function validate(string $attribute, mixed $value, \Closure $fail): void
{
if ('page' !== $attribute) {
$fail('validation.bad_api_filter')->translate();
}
if (!is_array($value)) {
$value = explode(',', $value);
}
foreach ($value as $key => $val) {
if (!in_array($key, $this->allowed, true)) {
$fail('validation.bad_api_page')->translate();
}
}
}
}

View File

@@ -0,0 +1,45 @@
<?php
/*
* AccountBalanceRepository.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\JsonApi\V3\AccountBalances;
use FireflyIII\Entities\AccountBalance;
use LaravelJsonApi\Contracts\Store\QueriesAll;
use LaravelJsonApi\NonEloquent\AbstractRepository;
class AccountBalanceRepository extends AbstractRepository implements QueriesAll
{
#[\Override]
public function find(string $resourceId): ?object
{
return AccountBalance::fromArray();
}
public function queryAll(): Capabilities\AccountBalanceQuery
{
return Capabilities\AccountBalanceQuery::make()
->withServer($this->server)
->withSchema($this->schema)
;
}
}

View File

@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace FireflyIII\JsonApi\V3\AccountBalances;
use Illuminate\Http\Request;
use LaravelJsonApi\Core\Resources\JsonApiResource;
class AccountBalanceResource extends JsonApiResource
{
/**
* Get the resource id.
*/
public function id(): string
{
return $this->resource->id;
}
/**
* Get the resource's attributes.
*
* @param null|Request $request
*/
public function attributes($request): iterable
{
return [
'name' => $this->resource->amount,
'amount' => $this->resource->amount,
];
}
/**
* Get the resource's relationships.
*
* @param null|Request $request
*/
public function relationships($request): iterable
{
return [
$this->relation('account')->withData($this->resource->getAccount()),
];
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace FireflyIII\JsonApi\V3\AccountBalances;
use FireflyIII\Entities\AccountBalance;
use LaravelJsonApi\Core\Schema\Schema;
use LaravelJsonApi\Eloquent\Fields\Relations\HasOne;
use LaravelJsonApi\NonEloquent\Fields\Attribute;
use LaravelJsonApi\NonEloquent\Fields\ID;
class AccountBalanceSchema extends Schema
{
/**
* The model the schema corresponds to.
*/
public static string $model = AccountBalance::class;
/**
* Get the resource fields.
*/
public function fields(): array
{
return [
ID::make(),
Attribute::make('name'),
Attribute::make('amount'),
HasOne::make('account'),
];
}
/**
* Get the resource filters.
*/
public function filters(): array
{
return [
// Filter::make('id'),
];
}
public function repository(): AccountBalanceRepository
{
return AccountBalanceRepository::make()
->withServer($this->server)
->withSchema($this)
;
}
}

View File

@@ -0,0 +1,58 @@
<?php
/*
* AccountBalanceQuery.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\JsonApi\V3\AccountBalances\Capabilities;
use FireflyIII\Entities\AccountBalance;
use FireflyIII\Models\Account;
use LaravelJsonApi\NonEloquent\Capabilities\QueryAll;
class AccountBalanceQuery extends QueryAll
{
private Account $account;
/**
* QuerySites constructor.
*/
public function __construct()
{
parent::__construct();
}
public function get(): iterable
{
return [
AccountBalance::fromArray(),
AccountBalance::fromArray(),
AccountBalance::fromArray(),
AccountBalance::fromArray(),
];
}
public function withAccount(Account $account): self
{
$this->account = $account;
return $this;
}
}

View File

@@ -0,0 +1,53 @@
<?php
/*
* AccountRepository.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\JsonApi\V3\Accounts;
use FireflyIII\Models\Account;
use FireflyIII\Support\JsonApi\Concerns\UsergroupAware;
use LaravelJsonApi\Contracts\Store\QueriesAll;
use LaravelJsonApi\NonEloquent\AbstractRepository;
class AccountRepository extends AbstractRepository implements QueriesAll
{
use UsergroupAware;
/**
* SiteRepository constructor.
*/
public function __construct() {}
public function find(string $resourceId): ?object
{
return Account::find((int) $resourceId);
}
public function queryAll(): Capabilities\AccountQuery
{
return Capabilities\AccountQuery::make()
->withUserGroup($this->userGroup)
->withServer($this->server)
->withSchema($this->schema)
;
}
}

View File

@@ -0,0 +1,129 @@
<?php
declare(strict_types=1);
namespace FireflyIII\JsonApi\V3\Accounts;
use FireflyIII\Models\Account;
use Illuminate\Http\Request;
use LaravelJsonApi\Core\Resources\JsonApiResource;
/**
* @property Account $resource
*/
class AccountResource extends JsonApiResource
{
/**
* Get the resource's attributes.
*
* @param null|Request $request
*/
public function attributes($request): iterable
{
return [
'created_at' => $this->resource->created_at,
'updated_at' => $this->resource->updated_at,
'name' => $this->resource->name,
'iban' => '' === $this->resource->iban ? null : $this->resource->iban,
'active' => $this->resource->active,
'last_activity' => $this->resource->last_activity,
'type' => $this->resource->type,
'account_role' => $this->resource->account_role,
// 'virtual_balance' => $this->resource->virtual_balance,
// 'native_balance' => $this->resource->native_balance,
// 'user' => $this->resource->user_array,
// 'balances' => []
//
// currency
// 'currency_id' => $this->resource->currency_id,
// 'currency_code' => $this->resource->currency_code,
// 'currency_symbol' => $this->resource->currency_symbol,
// 'currency_decimal_places' => $this->resource->currency_decimal_places,
// balance (in currency, on date)
// 'current_balance' => $this->resource->current_balance,
// 'current_balance' => app('steam')->bcround(app('steam')->balance($account, $date), $decimalPlaces),
// 'current_balance_date' => $date->toAtomString(),
// 'notes' => $this->repository->getNoteText($account),
// 'monthly_payment_date' => $monthlyPaymentDate,
// 'credit_card_type' => $creditCardType,
// 'account_number' => $this->repository->getMetaValue($account, 'account_number'),
// 'bic' => $this->repository->getMetaValue($account, 'BIC'),
// 'opening_balance' => $openingBalance,
// 'opening_balance_date' => $openingBalanceDate,
// 'liability_type' => $liabilityType,
// 'liability_direction' => $liabilityDirection,
// 'interest' => $interest,
// 'interest_period' => $interestPeriod,
// 'current_debt' => $this->repository->getMetaValue($account, 'current_debt'),
// 'include_net_worth' => $includeNetWorth,
// 'longitude' => $longitude,
// 'latitude' => $latitude,
// 'zoom_level' => $zoomLevel,
// 'order' => $order,
// 'currency_id' => (string) $currency->id,
// 'currency_code' => $currency->code,
// 'currency_symbol' => $currency->symbol,
// 'currency_decimal_places' => $currency->decimal_places,
//
// 'native_currency_id' => (string) $this->default->id,
// 'native_currency_code' => $this->default->code,
// 'native_currency_symbol' => $this->default->symbol,
// 'native_currency_decimal_places' => $this->default->decimal_places,
//
// // balance:
// 'current_balance' => $balance,
// 'native_current_balance' => $nativeBalance,
// 'current_balance_date' => $this->getDate()->endOfDay()->toAtomString(),
//
// // balance difference
// 'balance_difference' => $balanceDiff,
// 'native_balance_difference' => $nativeBalanceDiff,
// 'balance_difference_start' => $diffStart,
// 'balance_difference_end' => $diffEnd,
//
// // more meta
// 'last_activity' => array_key_exists($id, $this->lastActivity) ? $this->lastActivity[$id]->toAtomString() : null,
//
// // liability stuff
// 'liability_type' => $liabilityType,
// 'liability_direction' => $liabilityDirection,
// 'interest' => $interest,
// 'interest_period' => $interestPeriod,
// 'current_debt' => $currentDebt,
//
// // object group
// 'object_group_id' => null !== $objectGroupId ? (string) $objectGroupId : null,
// 'object_group_order' => $objectGroupOrder,
// 'object_group_title' => $objectGroupTitle,
// 'notes' => $this->repository->getNoteText($account),
// 'monthly_payment_date' => $monthlyPaymentDate,
// 'credit_card_type' => $creditCardType,
// 'bic' => $this->repository->getMetaValue($account, 'BIC'),
// 'virtual_balance' => number_format((float) $account->virtual_balance, $decimalPlaces, '.', ''),
// 'opening_balance' => $openingBalance,
// 'opening_balance_date' => $openingBalanceDate,
// 'include_net_worth' => $includeNetWorth,
// 'longitude' => $longitude,
// 'latitude' => $latitude,
// 'zoom_level' => $zoomLevel,
];
}
/**
* Get the resource's relationships.
*
* @param null|Request $request
*/
public function relationships($request): iterable
{
return [
$this->relation('user')->withData($this->resource->user),
$this->relation('account_balances')->withData($this->resource->balances),
];
}
}

View File

@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
namespace FireflyIII\JsonApi\V3\Accounts;
use FireflyIII\Models\Account;
use LaravelJsonApi\Eloquent\Contracts\Paginator;
use LaravelJsonApi\Eloquent\Fields\Boolean;
use LaravelJsonApi\Eloquent\Fields\DateTime;
use LaravelJsonApi\Eloquent\Fields\ID;
use LaravelJsonApi\Eloquent\Fields\Number;
use LaravelJsonApi\Eloquent\Fields\Relations\HasMany;
use LaravelJsonApi\Eloquent\Fields\Relations\HasOne;
use LaravelJsonApi\Eloquent\Fields\Str;
use LaravelJsonApi\Eloquent\Filters\WhereIdIn;
use LaravelJsonApi\Eloquent\Pagination\PagePagination;
use LaravelJsonApi\Eloquent\Schema;
class AccountSchema extends Schema
{
/**
* The model the schema corresponds to.
*/
public static string $model = Account::class;
/**
* Get the resource fields.
*/
public function fields(): array
{
return [
ID::make(),
DateTime::make('created_at')->sortable()->readOnly(),
DateTime::make('updated_at')->sortable()->readOnly(),
Str::make('name')->sortable(),
Str::make('account_type'),
Str::make('virtual_balance'),
Str::make('iban'),
Boolean::make('active'),
Number::make('order'),
HasOne::make('user'),
HasMany::make('account_balances'),
];
}
/**
* Get the resource filters.
*/
public function filters(): array
{
return [
WhereIdIn::make($this),
];
}
/**
* Get the resource paginator.
*/
public function pagination(): ?Paginator
{
return PagePagination::make();
}
}

View File

@@ -0,0 +1,73 @@
<?php
/*
* AccountQuery.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\JsonApi\V3\Accounts\Capabilities;
use FireflyIII\Support\JsonApi\Concerns\UsergroupAware;
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
use FireflyIII\Support\JsonApi\ExpandsQuery;
use FireflyIII\Support\JsonApi\FiltersPagination;
use FireflyIII\Support\JsonApi\SortsCollection;
use FireflyIII\Support\JsonApi\ValidateSortParameters;
use LaravelJsonApi\Contracts\Store\HasPagination;
use LaravelJsonApi\NonEloquent\Capabilities\QueryAll;
use LaravelJsonApi\NonEloquent\Concerns\PaginatesEnumerables;
class AccountQuery extends QueryAll implements HasPagination
{
use ExpandsQuery;
use FiltersPagination;
use PaginatesEnumerables;
use SortsCollection;
use UsergroupAware;
use ValidateSortParameters;
#[\Override]
public function get(): iterable
{
$filters = $this->queryParameters->filter();
$sort = $this->queryParameters->sortFields();
$pagination = $this->filtersPagination($this->queryParameters->page());
$needsAll = $this->validateParams('account', $sort);
$query = $this->userGroup->accounts();
if (!$needsAll) {
$query = $this->addPagination($query, $pagination);
}
$query = $this->addSortParams($query, $sort);
$query = $this->addFilterParams('account', $query, $filters);
$collection = $query->get(['accounts.*']);
// enrich data
$enrichment = new AccountEnrichment();
$collection = $enrichment->enrich($collection);
// add filters after the query
// add sort after the query
return $this->sortCollection($collection, $sort);
// var_dump($filters->value('name'));
// exit;
}
}

38
app/JsonApi/V3/Server.php Normal file
View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace FireflyIII\JsonApi\V3;
use FireflyIII\JsonApi\V3\Accounts\AccountSchema;
use FireflyIII\JsonApi\V3\AccountBalances\AccountBalanceSchema;
use FireflyIII\JsonApi\V3\Users\UserSchema;
use LaravelJsonApi\Core\Server\Server as BaseServer;
class Server extends BaseServer
{
/**
* The base URI namespace for this server.
*/
protected string $baseUri = '/api/v3';
/**
* Bootstrap the server when it is handling an HTTP request.
*/
public function serving(): void
{
// no-op
}
/**
* Get the server's list of schemas.
*/
protected function allSchemas(): array
{
return [
AccountSchema::class,
UserSchema::class,
AccountBalanceSchema::class,
];
}
}

View File

@@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace FireflyIII\JsonApi\V3\Users;
use FireflyIII\Models\User;
use Illuminate\Http\Request;
use LaravelJsonApi\Core\Resources\JsonApiResource;
/**
* @property User $resource
*/
class UserResource extends JsonApiResource
{
/**
* Get the resource's attributes.
*
* @param null|Request $request
*/
public function attributes($request): iterable
{
return [
'created_at' => $this->resource->created_at,
'updated_at' => $this->resource->updated_at,
'email' => $this->resource->email,
];
}
/**
* Get the resource's relationships.
*
* @param null|Request $request
*/
public function relationships($request): iterable
{
return [
// @TODO
];
}
}

View File

@@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
namespace FireflyIII\JsonApi\V3\Users;
use FireflyIII\User;
use LaravelJsonApi\Eloquent\Contracts\Paginator;
use LaravelJsonApi\Eloquent\Fields\DateTime;
use LaravelJsonApi\Eloquent\Fields\ID;
use LaravelJsonApi\Eloquent\Fields\Relations\HasMany;
use LaravelJsonApi\Eloquent\Fields\Str;
use LaravelJsonApi\Eloquent\Filters\WhereIdIn;
use LaravelJsonApi\Eloquent\Pagination\PagePagination;
use LaravelJsonApi\Eloquent\Schema;
class UserSchema extends Schema
{
/**
* The model the schema corresponds to.
*/
public static string $model = User::class;
/**
* Get the resource fields.
*/
public function fields(): array
{
return [
ID::make(),
DateTime::make('created_at')->sortable()->readOnly(),
DateTime::make('updated_at')->sortable()->readOnly(),
Str::make('email'),
HasMany::make('accounts'),
];
}
/**
* Get the resource filters.
*/
public function filters(): array
{
return [
WhereIdIn::make($this),
];
}
/**
* Get the resource paginator.
*/
public function pagination(): ?Paginator
{
return PagePagination::make();
}
}

View File

@@ -193,6 +193,11 @@ class Account extends Model
return $this->hasMany(AccountMeta::class);
}
public function accountBalances(): HasMany
{
return $this->hasMany(AccountBalance::class);
}
public function getEditNameAttribute(): string
{
$name = $this->name;

View File

@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class AccountBalance extends Model
{
use HasFactory;
protected $fillable = ['account_id', 'title', 'transaction_currency_id', 'balance'];
public function account(): BelongsTo
{
return $this->belongsTo(Account::class);
}
public function transactionCurrency(): BelongsTo
{
return $this->belongsTo(TransactionCurrency::class);
}
}

View File

@@ -0,0 +1,48 @@
<?php
/*
* AccountPolicy.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\Policies;
use FireflyIII\Entities\AccountBalance;
use FireflyIII\User;
class AccountBalancePolicy
{
/**
* TODO needs better authentication.
*/
public function view(User $user, AccountBalance $accountBalance): bool
{
return true;
}
/**
* Everybody can do this, but selection should limit to user.
*
* @return true
*/
public function viewAny(): bool
{
return true;
}
}

View File

@@ -0,0 +1,67 @@
<?php
/*
* AccountPolicy.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\Policies;
use FireflyIII\Models\Account;
use FireflyIII\User;
class AccountPolicy
{
/**
* TODO needs better authentication.
*/
public function view(User $user, Account $account): bool
{
return true;
return auth()->check() && $user->id === $account->user_id;
}
/**
* Everybody can do this, but selection should limit to user.
*
* @return true
*/
public function viewAny(): bool
{
return true;
return auth()->check();
}
/**
* Everybody can do this, but selection should limit to user.
*
* @return true
*/
public function viewUser(User $user, Account $account): bool
{
return $this->view($user, $account);
}
public function viewAccountBalances(User $user, Account $account): bool
{
return $this->view($user, $account);
}
}

View File

@@ -0,0 +1,48 @@
<?php
/*
* BalancePolicy.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\Policies;
use FireflyIII\Models\Account;
use FireflyIII\User;
class BalancePolicy
{
/**
* TODO needs better authentication.
*/
public function view(User $user, Account $account): bool
{
return auth()->check() && $user->id === $account->user_id;
}
/**
* Everybody can do this, but selection should limit to user.
*
* @return true
*/
public function viewAny(): bool
{
return auth()->check();
}
}

View File

@@ -0,0 +1,58 @@
<?php
/*
* UserPolicy.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\Policies;
use FireflyIII\User;
class UserPolicy
{
/**
* TODO needs better authentication.
*/
public function view(User $user, User $user1): bool
{
return true;
return auth()->check() && $user->id === $account->user_id;
}
/**
* Everybody can do this, but selection should limit to user.
*
* @return true
*/
public function viewAny(): bool
{
return true;
return auth()->check();
}
public function viewAccounts(User $user): bool
{
return true;
return auth()->check();
}
}

View File

@@ -302,6 +302,7 @@ class AccountRepository implements AccountRepositoryInterface
;
if ('' !== $query) {
// split query on spaces just in case:
// TODO this will always fail because it searches for AND.
$parts = explode(' ', $query);
foreach ($parts as $part) {
$search = sprintf('%%%s%%', $part);
@@ -384,4 +385,10 @@ class AccountRepository implements AccountRepositoryInterface
return $return;
}
#[\Override]
public function getAccountBalances(Account $account): Collection
{
return $account->accountBalances;
}
}

View File

@@ -53,6 +53,8 @@ interface AccountRepositoryInterface
public function getAccountCurrency(Account $account): ?TransactionCurrency;
public function getAccountBalances(Account $account): Collection;
public function getAccountsById(array $accountIds): Collection;
public function getAccountsByType(array $types, ?array $sort = [], ?array $filters = []): Collection;

View File

@@ -0,0 +1,48 @@
<?php
/*
* UsergroupAware.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\Concerns;
use FireflyIII\Models\UserGroup;
trait UsergroupAware
{
protected UserGroup $userGroup;
public function getUserGroup(): UserGroup
{
return $this->userGroup;
}
public function setUserGroup(UserGroup $userGroup): void
{
$this->userGroup = $userGroup;
}
public function withUserGroup(UserGroup $userGroup): self
{
$this->userGroup = $userGroup;
return $this;
}
}

View File

@@ -0,0 +1,149 @@
<?php
/*
* AccountEnricher.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\Enrichments;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
class AccountEnrichment implements EnrichmentInterface
{
private Collection $collection;
private array $currencies;
#[\Override]
public function enrich(Collection $collection): Collection
{
$this->collection = $collection;
$this->currencies = [];
// do everything here:
$this->getLastActivity();
// $this->getMetaBalances();
$this->collectAccountTypes();
$this->collectMetaData();
$this->collection->transform(function (Account $account) {
$account->user_array = ['id' => 1, 'bla bla' => 'bla'];
$account->balances = collect([
['balance_id' => 1, 'balance' => 5],
['balance_id' => 2, 'balance' => 5],
['balance_id' => 3, 'balance' => 5],
]);
return $account;
});
return $this->collection;
}
/**
* TODO this method refers to a single-use method inside Steam that could be moved here.
*/
private function getLastActivity(): void
{
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
$lastActivity = $accountRepository->getLastActivity($this->collection);
foreach ($lastActivity as $row) {
$this->collection->where('id', $row['account_id'])->first()->last_activity = Carbon::parse($row['date_max'], config('app.timezone'));
}
}
/**
* TODO this method refers to a single-use method inside Steam that could be moved here.
*/
private function getMetaBalances(): void
{
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'];
}
}
/**
* TODO this method refers to a single-use method inside Steam that could be moved here.
*/
private function collectAccountTypes(): void
{
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
$accountTypes = $accountRepository->getAccountTypes($this->collection);
$types = [];
/** @var AccountType $row */
foreach ($accountTypes as $row) {
$types[$row->id] = $row->type;
}
$this->collection->transform(function (Account $account) use ($types) {
$account->type = $types[$account->id];
return $account;
});
}
private function collectMetaData(): void
{
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
/** @var CurrencyRepositoryInterface $repository */
$repository = app(CurrencyRepositoryInterface::class);
$metaFields = $accountRepository->getMetaValues($this->collection, ['currency_id', 'account_role', 'account_number', 'liability_direction', 'interest', 'interest_period', 'current_debt']);
$currencyIds = $metaFields->where('name', 'currency_id')->pluck('data')->toArray();
$currencies = [];
foreach ($repository->getByIds($currencyIds) as $currency) {
$id = $currency->id;
$currencies[$id] = $currency;
}
$this->collection->transform(function (Account $account) use ($metaFields, $currencies) {
$set = $metaFields->where('account_id', $account->id);
foreach ($set as $entry) {
$account->{$entry->name} = $entry->data;
if ('currency_id' === $entry->name) {
$id = (int) $entry->data;
$account->currency_code = $currencies[$id]?->code;
$account->currency_symbol = $currencies[$id]?->symbol;
$account->currency_decimal_places = $currencies[$id]?->decimal_places;
}
}
return $account;
});
}
}

View File

@@ -0,0 +1,31 @@
<?php
/*
* EnricherInterface.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\Enrichments;
use Illuminate\Support\Collection;
interface EnrichmentInterface
{
public function enrich(Collection $collection): Collection;
}

View File

@@ -0,0 +1,85 @@
<?php
/*
* ExpandsQuery.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 FireflyIII\Support\Http\Api\AccountFilter;
use Illuminate\Contracts\Database\Eloquent\Builder;
use LaravelJsonApi\Core\Query\FilterParameters;
use LaravelJsonApi\Core\Query\SortFields;
trait ExpandsQuery
{
use AccountFilter;
final protected function addPagination(Builder $query, array $pagination): Builder
{
$skip = ($pagination['number'] - 1) * $pagination['size'];
return $query->skip($skip)->take($pagination['size']);
}
final protected function addSortParams(Builder $query, ?SortFields $sort): Builder
{
if (null === $sort) {
return $query;
}
foreach ($sort->all() as $sortField) {
$query->orderBy($sortField->name(), $sortField->isAscending() ? 'ASC' : 'DESC');
}
return $query;
}
final protected function addFilterParams(string $class, Builder $query, ?FilterParameters $filters): Builder
{
if (null === $filters) {
return $query;
}
$config = config(sprintf('firefly.valid_query_filters.%s', $class)) ?? [];
if (0 === count($filters->all())) {
return $query;
}
$query->where(function (Builder $q) use ($config, $filters): void {
foreach ($filters->all() as $filter) {
if (in_array($filter->key(), $config, true)) {
foreach ($filter->value() as $value) {
$q->where($filter->key(), 'LIKE', sprintf('%%%s%%', $value));
}
}
}
});
// some filters are special, i.e. the account type filter.
$typeFilters = $filters->value('type', false);
if (false !== $typeFilters && count($typeFilters) > 0) {
$query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id');
foreach ($typeFilters as $typeFilter) {
$types = $this->mapAccountTypes($typeFilter);
$query->whereIn('account_types.type', $types);
}
}
return $query;
}
}

View File

@@ -0,0 +1,55 @@
<?php
/*
* FiltersPagination.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;
trait FiltersPagination
{
protected function filtersPagination(?array $pagination): array
{
if (null === $pagination) {
return [
'number' => 1,
'size' => $this->getPageSize(),
];
}
// cleanup page number
$pagination['number'] = (int) ($pagination['number'] ?? 1);
$pagination['number'] = min(65536, max($pagination['number'], 1));
// clean up page size
$pagination['size'] = (int) ($pagination['size'] ?? $this->getPageSize());
$pagination['size'] = min(1337, max($pagination['size'], 1));
return $pagination;
}
private function getPageSize(): int
{
if (auth()->check()) {
return (int) app('preferences')->get('listPageSize', 50)->data;
}
return 50;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/*
* SortsCollection.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 Illuminate\Support\Collection;
use LaravelJsonApi\Core\Query\SortFields;
trait SortsCollection
{
protected function sortCollection(Collection $collection, ?SortFields $sortFields): Collection
{
if (null === $sortFields) {
return $collection;
}
foreach ($sortFields->all() as $sortField) {
$collection = $sortField->isAscending() ? $collection->sortBy($sortField->name()) : $collection->sortByDesc($sortField->name());
}
return $collection;
}
}

View File

@@ -0,0 +1,46 @@
<?php
/*
* ValidateSortParameters.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 LaravelJsonApi\Core\Query\SortFields;
trait ValidateSortParameters
{
public function validateParams(string $class, ?SortFields $params): bool
{
if (null === $params) {
return false;
}
$config = config(sprintf('firefly.full_data_set.%s', $class)) ?? [];
foreach ($params->all() as $field) {
if (in_array($field->name(), $config, true)) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,208 @@
<?php
/*
* AccountBalanceCalculator.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\Models;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountBalance;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Facades\Log;
class AccountBalanceCalculator
{
/**
* Recalculate all balances for a given account.
*
* Je moet toch altijd wel alles doen want je weet niet waar een transaction journal invloed op heeft.
* Dus dit aantikken per transaction journal is zinloos, beide accounts moeten gedaan worden.
*/
public static function recalculateForAccount(Account $account): void
{
self::recalculate($account);
}
public static function recalculateForTransactionJournal(TransactionJournal $transactionJournal): void
{
foreach ($transactionJournal->transactions as $transaction) {
self::recalculateForAccount($transaction->account);
}
}
/**
* select account_id, transaction_currency_id, foreign_currency_id, sum(amount), sum(foreign_amount) from
* transactions group by account_id, transaction_currency_id, foreign_currency_id
*/
public static function recalculate(?Account $account): void
{
self::recalculateLatest($account);
// loop all transaction journals and set those amounts too.
self::recalculateJournals($account);
// loop all dates and set those amounts too.
}
private static function getAccountBalanceByAccount(int $account, int $currency): AccountBalance
{
$query = AccountBalance::where('title', 'balance')->where('account_id', $account)->where('transaction_currency_id', $currency);
$entry = $query->first();
if (null !== $entry) {
// Log::debug(sprintf('Found account balance "balance" for account #%d and currency #%d: %s', $account, $currency, $entry->balance));
return $entry;
}
$entry = new AccountBalance();
$entry->title = 'balance';
$entry->account_id = $account;
$entry->transaction_currency_id = $currency;
$entry->balance = '0';
$entry->save();
// Log::debug(sprintf('Created new account balance for account #%d and currency #%d: %s', $account, $currency, $entry->balance));
return $entry;
}
private static function getAccountBalanceByJournal(string $title, int $account, int $journal, int $currency): AccountBalance
{
$query = AccountBalance::where('title', $title)->where('account_id', $account)->where('transaction_journal_id', $journal)->where('transaction_currency_id', $currency);
$entry = $query->first();
if (null !== $entry) {
return $entry;
}
$entry = new AccountBalance();
$entry->title = $title;
$entry->account_id = $account;
$entry->transaction_journal_id = $journal;
$entry->transaction_currency_id = $currency;
$entry->balance = '0';
$entry->save();
return $entry;
}
private static function recalculateLatest(?Account $account): void
{
$query = Transaction::groupBy(['transactions.account_id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id']);
if (null !== $account) {
$query->where('transactions.account_id', $account->id);
}
$result = $query->get(['transactions.account_id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id', \DB::raw('SUM(transactions.amount) as sum_amount'), \DB::raw('SUM(transactions.foreign_amount) as sum_foreign_amount')]);
// reset account balances:
self::resetAccountBalancesByAccount('balance', $account);
/** @var \stdClass $row */
foreach ($result as $row) {
$account = (int) $row->account_id;
$transactionCurrency = (int) $row->transaction_currency_id;
$foreignCurrency = (int) $row->foreign_currency_id;
$sumAmount = $row->sum_amount;
$sumForeignAmount = $row->sum_foreign_amount;
// first create for normal currency:
$entry = self::getAccountBalanceByAccount($account, $transactionCurrency);
$entry->balance = bcadd($entry->balance, $sumAmount);
$entry->save();
// Log::debug(sprintf('Set balance entry #%d ("balance") to amount %s', $entry->id, $entry->balance));
// then do foreign amount, if present:
if ($foreignCurrency > 0) {
$entry = self::getAccountBalanceByAccount($account, $foreignCurrency);
$entry->balance = bcadd($entry->balance, $sumForeignAmount);
$entry->save();
// Log::debug(sprintf('Set balance entry #%d ("balance") to amount %s', $entry->id, $entry->balance));
}
}
}
private static function resetAccountBalancesByAccount(string $title, ?Account $account): void
{
if (null === $account) {
AccountBalance::whereNotNull('updated_at')->where('title', $title)->update(['balance' => '0']);
Log::debug('Set ALL balances to zero.');
return;
}
AccountBalance::where('account_id', $account->id)->where('title', $title)->update(['balance' => '0']);
Log::debug(sprintf('Set balances of account #%d to zero.', $account->id));
}
public static function recalculateByJournal(TransactionJournal $transactionJournal): void
{
Log::debug(sprintf('Recalculate balance after journal #%d', $transactionJournal->id));
// update both account balances, but limit to this transaction or earlier.
foreach ($transactionJournal->transactions as $transaction) {
self::recalculate($transaction->account, $transactionJournal);
}
}
private static function recalculateJournals(?Account $account): void
{
$query = Transaction::groupBy(['transactions.account_id', 'transaction_journals.id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id']);
$query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id');
$query->orderBy('transaction_journals.date', 'asc');
if (null !== $account) {
$query->where('transactions.account_id', $account->id);
}
$result = $query->get(['transactions.account_id', 'transaction_journals.id', 'transactions.transaction_currency_id', 'transactions.foreign_currency_id', \DB::raw('SUM(transactions.amount) as sum_amount'), \DB::raw('SUM(transactions.foreign_amount) as sum_foreign_amount')]);
$amounts = [];
/** @var \stdClass $row */
foreach ($result as $row) {
$account = (int) $row->account_id;
$transactionCurrency = (int) $row->transaction_currency_id;
$foreignCurrency = (int) $row->foreign_currency_id;
$sumAmount = $row->sum_amount;
$sumForeignAmount = $row->sum_foreign_amount;
$journalId = (int) $row->id;
// new amounts:
$amounts[$account][$transactionCurrency] = bcadd($amounts[$account][$transactionCurrency] ?? '0', $sumAmount ?? '0');
$amounts[$account][$foreignCurrency] = bcadd($amounts[$account][$foreignCurrency] ?? '0', $sumForeignAmount ?? '0');
// first create for normal currency:
$entry = self::getAccountBalanceByJournal('balance_after_journal', $account, $journalId, $transactionCurrency);
$entry->balance = $amounts[$account][$transactionCurrency];
$entry->save();
// then do foreign amount, if present:
if ($foreignCurrency > 0) {
$entry = self::getAccountBalanceByJournal('balance_after_journal', $account, $journalId, $foreignCurrency);
$entry->balance = $amounts[$account][$foreignCurrency];
$entry->save();
}
}
// select transactions.account_id, transaction_journals.id, transactions.transaction_currency_id, transactions.foreign_currency_id, sum(transactions.amount), sum(transactions.foreign_amount)
//
// from transactions
//
// left join transaction_journals ON transaction_journals.id = transactions.transaction_journal_id
//
// group by account_id, transaction_journals.id, transaction_currency_id, foreign_currency_id
// order by transaction_journals.date desc
}
}

View File

@@ -63,6 +63,12 @@ class AccountTransformer extends AbstractTransformer
$this->convertedBalances = [];
$this->balanceDifferences = [];
Log::debug(sprintf('collectMetaData on %d object(s)', $objects->count()));
// first collect all the "heavy" stuff that relies on ALL data to be present.
// get last activity:
$this->getLastActivity($objects);
// get balances of all accounts
$this->getMetaBalances($objects);
@@ -75,18 +81,25 @@ class AccountTransformer extends AbstractTransformer
// get account types:
$this->collectAccountTypes($objects);
// get last activity:
$this->getLastActivity($objects);
// add balance difference
if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) {
$this->getBalanceDifference($objects, $this->parameters->get('start'), $this->parameters->get('end'));
}
// get object groups"
// get object groups
$this->getObjectGroups($objects);
return $this->sortAccounts($objects);
// sort:
$objects = $this->sortAccounts($objects);
// if pagination is disabled, do it now:
if (true === $this->parameters->get('disablePagination')) {
$page = (int) $this->parameters->get('page');
$size = (int) $this->parameters->get('pageSize');
$objects = $objects->slice(($page - 1) * $size, $size);
}
return $objects;
}
private function getDate(): Carbon

View File

@@ -87,6 +87,8 @@
"guzzlehttp/guzzle": "^7.8",
"jc5/google2fa-laravel": "^2.0",
"jc5/recovery": "^2",
"laravel-json-api/laravel": "^4.0",
"laravel-json-api/non-eloquent": "^4.0",
"laravel/framework": "^11",
"laravel/passport": "^12",
"laravel/sanctum": "^4",
@@ -101,13 +103,13 @@
"psr/log": "<4",
"ramsey/uuid": "^4.7",
"rcrowe/twigbridge": "^0.14",
"twig/twig": "3.8.0",
"spatie/laravel-html": "^3.2",
"spatie/laravel-ignition": "^2",
"spatie/period": "^2.4",
"symfony/expression-language": "^7.0",
"symfony/http-client": "^7.0",
"symfony/mailgun-mailer": "^7.0"
"symfony/mailgun-mailer": "^7.0",
"twig/twig": "3.8.0"
},
"require-dev": {
"barryvdh/laravel-debugbar": "^3.9",
@@ -116,6 +118,7 @@
"fakerphp/faker": "1.*",
"filp/whoops": "2.*",
"larastan/larastan": "^2",
"laravel-json-api/testing": "^3.0",
"mockery/mockery": "1.*",
"phpstan/extension-installer": "^1.3",
"phpstan/phpstan": "^1.10",

1272
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -117,7 +117,7 @@ return [
'expression_engine' => false,
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2024-04-29',
'version' => 'develop/2024-05-16',
'api_version' => '2.0.14',
'db_version' => 24,
@@ -941,4 +941,10 @@ return [
'accounts' => ['name', 'active', 'iban', 'balance', 'last_activity', 'balance_difference', 'current_debt'],
],
],
'full_data_set' => [
'account' => ['last_activity', 'balance_difference', 'current_balance', 'current_debt'],
],
'valid_query_filters' => [
'account' => ['name', 'iban', 'active'],
],
];

35
config/jsonapi.php Normal file
View File

@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
use FireflyIII\JsonApi\V3\Server;
return [
/*
|--------------------------------------------------------------------------
| Root Namespace
|--------------------------------------------------------------------------
|
| The root JSON:API namespace, within your application's namespace.
| This is used when generating any class that does not sit *within*
| a server's namespace. For example, new servers and filters.
|
| By default this is set to `JsonApi` which means the root namespace
| will be `\App\JsonApi`, if your application's namespace is `App`.
*/
'namespace' => 'JsonApi',
/*
|--------------------------------------------------------------------------
| Servers
|--------------------------------------------------------------------------
|
| A list of the JSON:API compliant APIs in your application, referred to
| as "servers". They must be listed below, with the array key being the
| unique name for each server, and the value being the fully-qualified
| class name of the server class.
*/
'servers' => [
'v3' => Server::class,
],
];

View File

@@ -284,7 +284,7 @@ class CreateMainTables extends Migration
$table->integer('budget_id', false, true);
$table->date('startdate');
$table->decimal('amount', 32, 12);
$table->string('repeat_freq', 30);
$table->string('repeat_freq', 30)->nullable();
$table->boolean('repeats')->default(0);
$table->foreign('budget_id')->references('id')->on('budgets')->onDelete('cascade');
}

View File

@@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class () extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
if (!Schema::hasTable('account_balances')) {
Schema::create('account_balances', function (Blueprint $table): void {
$table->id();
$table->timestamps();
$table->string('title', 100)->nullable();
$table->integer('account_id', false, true);
$table->integer('transaction_currency_id', false, true);
$table->date('date')->nullable();
$table->integer('transaction_journal_id', false, true)->nullable();
$table->decimal('balance', 32, 12);
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade');
$table->unique(['account_id', 'transaction_currency_id', 'transaction_journal_id', 'date', 'title'], 'unique_account_currency');
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('account_balances');
}
};

619
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,17 +10,17 @@
"title": "T\u00edtol"
},
"list": {
"drag_and_drop": "Drag and drop",
"drag_and_drop": "Arrossega i deixa anar",
"active": "Est\u00e0 actiu?",
"name": "Nom",
"type": "Tipus",
"number": "Account number",
"number": "N\u00famero de compte",
"liability_type": "Tipus de passiu",
"current_balance": "Current balance",
"last_activity": "Last activity",
"amount_due": "Amount due",
"balance_difference": "Balance difference",
"menu": "Menu"
"current_balance": "Balan\u00e7 actual",
"last_activity": "Darrera activitat",
"amount_due": "Import pendent",
"balance_difference": "Difer\u00e8ncia de saldo",
"menu": "Men\u00fa"
},
"validation": {
"bad_type_source": "Firefly III no pot determinar el tipus de transacci\u00f3 a partir d'aquest compte font.",

View File

@@ -10,17 +10,17 @@
"title": "T\u00edtol"
},
"list": {
"drag_and_drop": "Drag and drop",
"drag_and_drop": "Arrossega i deixa anar",
"active": "Est\u00e0 actiu?",
"name": "Nom",
"type": "Tipus",
"number": "Account number",
"number": "N\u00famero de compte",
"liability_type": "Tipus de passiu",
"current_balance": "Current balance",
"last_activity": "Last activity",
"amount_due": "Amount due",
"balance_difference": "Balance difference",
"menu": "Menu"
"current_balance": "Balan\u00e7 actual",
"last_activity": "Darrera activitat",
"amount_due": "Import pendent",
"balance_difference": "Difer\u00e8ncia de saldo",
"menu": "Men\u00fa"
},
"validation": {
"bad_type_source": "Firefly III no pot determinar el tipus de transacci\u00f3 a partir d'aquest compte font.",

View File

@@ -4,22 +4,22 @@
"date_time_fns": "do MMMM yyyy @ HH:mm:ss",
"month_and_day_fns": "d MMMM y",
"does_not_exist": "(config.does_not_exist)",
"date_time_fns_short": "MMMM do, yyyy @ HH:mm"
"date_time_fns_short": "D MMMM yyyy [o] HH:mm"
},
"form": {
"title": "Tytu\u0142"
},
"list": {
"drag_and_drop": "Drag and drop",
"drag_and_drop": "Przeci\u0105gnij i upu\u015b\u0107",
"active": "Jest aktywny?",
"name": "Nazwa",
"type": "Typ",
"number": "Account number",
"number": "Numer konta",
"liability_type": "Rodzaj zobowi\u0105zania",
"current_balance": "Current balance",
"last_activity": "Last activity",
"amount_due": "Amount due",
"balance_difference": "Balance difference",
"current_balance": "Bie\u017c\u0105ce saldo",
"last_activity": "Ostatnia aktywno\u015b\u0107",
"amount_due": "Do zap\u0142aty",
"balance_difference": "R\u00f3\u017cnica salda",
"menu": "Menu"
},
"validation": {
@@ -38,20 +38,20 @@
"interest_calc_quarterly": "Kwartalnie",
"spent": "Wydano",
"administration_owner": "Administration owner: {{email}}",
"administration_you": "Your role: {{role}}",
"administration_role_owner": "Owner",
"administration_role_ro": "Read-only",
"administration_role_mng_trx": "Manage transactions",
"administration_role_mng_meta": "Manage classification and meta-data",
"administration_role_mng_budgets": "Manage budgets",
"administration_role_mng_piggies": "Manage piggy banks",
"administration_role_mng_subscriptions": "Manage subscriptions",
"administration_role_mng_rules": "Manage rules",
"administration_role_mng_recurring": "Manage recurring transactions ",
"administration_you": "Twoja rola: {{role}}",
"administration_role_owner": "W\u0142a\u015bciciel",
"administration_role_ro": "Tylko odczyt",
"administration_role_mng_trx": "Zarz\u0105dzanie transakcjami",
"administration_role_mng_meta": "Zarz\u0105dzanie klasyfikacj\u0105 i meta-danymi",
"administration_role_mng_budgets": "Zarz\u0105dzanie bud\u017cetami",
"administration_role_mng_piggies": "Zarz\u0105dzanie skarbonkami",
"administration_role_mng_subscriptions": "Zarz\u0105dzanie subskrypcjami",
"administration_role_mng_rules": "Zarz\u0105dzanie regu\u0142ami",
"administration_role_mng_recurring": "Zarz\u0105dzanie transakcjami cyklicznymi ",
"administration_role_mng_webhooks": "Manage webhooks",
"administration_role_mng_currencies": "Manage currencies",
"administration_role_view_reports": "View reports",
"administration_role_full": "Full access",
"administration_role_mng_currencies": "Zarz\u0105dzanie walutami",
"administration_role_view_reports": "Przegl\u0105danie raport\u00f3w",
"administration_role_full": "Pe\u0142ny dost\u0119p",
"new_administration_created": "New financial administration \"{{title}}\" has been created",
"left": "Pozosta\u0142o",
"paid": "Zap\u0142acone",
@@ -70,10 +70,10 @@
"unknown_dest_plain": "Nieznane konto docelowe",
"unknown_any_plain": "Nieznane konto",
"unknown_budget_plain": "Brak bud\u017cetu",
"stored_journal_js": "Successfully created new transaction \"{{description}}\"",
"stored_journal_js": "Pomy\u015blnie utworzono now\u0105 transakcj\u0119 \"{{description}}\"",
"wait_loading_transaction": "Poczekaj na za\u0142adowanie formularza",
"nothing_found": "(nic nie znaleziono)",
"wait_loading_data": "Please wait for your information to load...",
"wait_loading_data": "Prosz\u0119 poczeka\u0107 na za\u0142adowanie informacji...",
"Transfer": "Transfer",
"Withdrawal": "Wyp\u0142ata",
"Deposit": "Wp\u0142ata",

View File

@@ -4,22 +4,22 @@
"date_time_fns": "do MMMM yyyy @ HH:mm:ss",
"month_and_day_fns": "d MMMM y",
"does_not_exist": "(config.does_not_exist)",
"date_time_fns_short": "MMMM do, yyyy @ HH:mm"
"date_time_fns_short": "D MMMM yyyy [o] HH:mm"
},
"form": {
"title": "Tytu\u0142"
},
"list": {
"drag_and_drop": "Drag and drop",
"drag_and_drop": "Przeci\u0105gnij i upu\u015b\u0107",
"active": "Jest aktywny?",
"name": "Nazwa",
"type": "Typ",
"number": "Account number",
"number": "Numer konta",
"liability_type": "Rodzaj zobowi\u0105zania",
"current_balance": "Current balance",
"last_activity": "Last activity",
"amount_due": "Amount due",
"balance_difference": "Balance difference",
"current_balance": "Bie\u017c\u0105ce saldo",
"last_activity": "Ostatnia aktywno\u015b\u0107",
"amount_due": "Do zap\u0142aty",
"balance_difference": "R\u00f3\u017cnica salda",
"menu": "Menu"
},
"validation": {
@@ -38,20 +38,20 @@
"interest_calc_quarterly": "Kwartalnie",
"spent": "Wydano",
"administration_owner": "Administration owner: {{email}}",
"administration_you": "Your role: {{role}}",
"administration_role_owner": "Owner",
"administration_role_ro": "Read-only",
"administration_role_mng_trx": "Manage transactions",
"administration_role_mng_meta": "Manage classification and meta-data",
"administration_role_mng_budgets": "Manage budgets",
"administration_role_mng_piggies": "Manage piggy banks",
"administration_role_mng_subscriptions": "Manage subscriptions",
"administration_role_mng_rules": "Manage rules",
"administration_role_mng_recurring": "Manage recurring transactions ",
"administration_you": "Twoja rola: {{role}}",
"administration_role_owner": "W\u0142a\u015bciciel",
"administration_role_ro": "Tylko odczyt",
"administration_role_mng_trx": "Zarz\u0105dzanie transakcjami",
"administration_role_mng_meta": "Zarz\u0105dzanie klasyfikacj\u0105 i meta-danymi",
"administration_role_mng_budgets": "Zarz\u0105dzanie bud\u017cetami",
"administration_role_mng_piggies": "Zarz\u0105dzanie skarbonkami",
"administration_role_mng_subscriptions": "Zarz\u0105dzanie subskrypcjami",
"administration_role_mng_rules": "Zarz\u0105dzanie regu\u0142ami",
"administration_role_mng_recurring": "Zarz\u0105dzanie transakcjami cyklicznymi ",
"administration_role_mng_webhooks": "Manage webhooks",
"administration_role_mng_currencies": "Manage currencies",
"administration_role_view_reports": "View reports",
"administration_role_full": "Full access",
"administration_role_mng_currencies": "Zarz\u0105dzanie walutami",
"administration_role_view_reports": "Przegl\u0105danie raport\u00f3w",
"administration_role_full": "Pe\u0142ny dost\u0119p",
"new_administration_created": "New financial administration \"{{title}}\" has been created",
"left": "Pozosta\u0142o",
"paid": "Zap\u0142acone",
@@ -70,10 +70,10 @@
"unknown_dest_plain": "Nieznane konto docelowe",
"unknown_any_plain": "Nieznane konto",
"unknown_budget_plain": "Brak bud\u017cetu",
"stored_journal_js": "Successfully created new transaction \"{{description}}\"",
"stored_journal_js": "Pomy\u015blnie utworzono now\u0105 transakcj\u0119 \"{{description}}\"",
"wait_loading_transaction": "Poczekaj na za\u0142adowanie formularza",
"nothing_found": "(nic nie znaleziono)",
"wait_loading_data": "Please wait for your information to load...",
"wait_loading_data": "Prosz\u0119 poczeka\u0107 na za\u0142adowanie informacji...",
"Transfer": "Transfer",
"Withdrawal": "Wyp\u0142ata",
"Deposit": "Wp\u0142ata",

View File

@@ -10,16 +10,16 @@
"title": "T\u00edtulo"
},
"list": {
"drag_and_drop": "Drag and drop",
"drag_and_drop": "Arrastar e soltar",
"active": "Est\u00e1 ativo?",
"name": "Nome",
"type": "Tipo",
"number": "Account number",
"number": "N\u00famero da conta",
"liability_type": "Tipo de passivo",
"current_balance": "Current balance",
"last_activity": "Last activity",
"amount_due": "Amount due",
"balance_difference": "Balance difference",
"current_balance": "Saldo atual",
"last_activity": "\u00daltima atividade",
"amount_due": "Valor devido",
"balance_difference": "Diferen\u00e7a de saldo",
"menu": "Menu"
},
"validation": {

View File

@@ -10,16 +10,16 @@
"title": "T\u00edtulo"
},
"list": {
"drag_and_drop": "Drag and drop",
"drag_and_drop": "Arrastar e soltar",
"active": "Esta ativo?",
"name": "Nome",
"type": "Tipo",
"number": "Account number",
"number": "N\u00famero de conta",
"liability_type": "Tipo de responsabilidade",
"current_balance": "Current balance",
"last_activity": "Last activity",
"amount_due": "Amount due",
"balance_difference": "Balance difference",
"current_balance": "Saldo atual",
"last_activity": "\u00daltima atividade",
"amount_due": "Valor a pagar",
"balance_difference": "Diferen\u00e7a de saldo",
"menu": "Menu"
},
"validation": {

View File

@@ -10,16 +10,16 @@
"title": "T\u00edtulo"
},
"list": {
"drag_and_drop": "Drag and drop",
"drag_and_drop": "Arrastar e soltar",
"active": "Est\u00e1 ativo?",
"name": "Nome",
"type": "Tipo",
"number": "Account number",
"number": "N\u00famero da conta",
"liability_type": "Tipo de passivo",
"current_balance": "Current balance",
"last_activity": "Last activity",
"amount_due": "Amount due",
"balance_difference": "Balance difference",
"current_balance": "Saldo atual",
"last_activity": "\u00daltima atividade",
"amount_due": "Valor devido",
"balance_difference": "Diferen\u00e7a de saldo",
"menu": "Menu"
},
"validation": {

View File

@@ -10,16 +10,16 @@
"title": "T\u00edtulo"
},
"list": {
"drag_and_drop": "Drag and drop",
"drag_and_drop": "Arrastar e soltar",
"active": "Esta ativo?",
"name": "Nome",
"type": "Tipo",
"number": "Account number",
"number": "N\u00famero de conta",
"liability_type": "Tipo de responsabilidade",
"current_balance": "Current balance",
"last_activity": "Last activity",
"amount_due": "Amount due",
"balance_difference": "Balance difference",
"current_balance": "Saldo atual",
"last_activity": "\u00daltima atividade",
"amount_due": "Valor a pagar",
"balance_difference": "Diferen\u00e7a de saldo",
"menu": "Menu"
},
"validation": {

View File

@@ -10,17 +10,17 @@
"title": "Naslov"
},
"list": {
"drag_and_drop": "Drag and drop",
"drag_and_drop": "Povleci in spusti",
"active": "Aktiviran?",
"name": "ime",
"type": "Vrsta",
"number": "Account number",
"number": "\u0160tevilka ra\u010duna",
"liability_type": "Vrsta obveznost",
"current_balance": "Current balance",
"last_activity": "Last activity",
"amount_due": "Amount due",
"balance_difference": "Balance difference",
"menu": "Menu"
"current_balance": "Trenutno stanje",
"last_activity": "Zadnja aktivnost",
"amount_due": "Dolgovani znesek",
"balance_difference": "Bilan\u010dna razlika",
"menu": "Meni"
},
"validation": {
"bad_type_source": "Na podlagi tega izvornega ra\u010duna Firefly III ne more dolo\u010diti vrste transakcije.",

View File

@@ -10,17 +10,17 @@
"title": "Naslov"
},
"list": {
"drag_and_drop": "Drag and drop",
"drag_and_drop": "Povleci in spusti",
"active": "Aktiviran?",
"name": "ime",
"type": "Vrsta",
"number": "Account number",
"number": "\u0160tevilka ra\u010duna",
"liability_type": "Vrsta obveznost",
"current_balance": "Current balance",
"last_activity": "Last activity",
"amount_due": "Amount due",
"balance_difference": "Balance difference",
"menu": "Menu"
"current_balance": "Trenutno stanje",
"last_activity": "Zadnja aktivnost",
"amount_due": "Dolgovani znesek",
"balance_difference": "Bilan\u010dna razlika",
"menu": "Meni"
},
"validation": {
"bad_type_source": "Na podlagi tega izvornega ra\u010duna Firefly III ne more dolo\u010diti vrste transakcije.",

View File

@@ -4,20 +4,16 @@
"/build/create_transaction.js": "/build/create_transaction.js",
"/build/edit_transaction.js": "/build/edit_transaction.js",
"/build/profile.js": "/build/profile.js",
"/build/index.js": "/build/index.js",
"/build/create.js": "/build/create.js",
"/build/edit.js": "/build/edit.js",
"/build/show.js": "/build/show.js",
"/build/webhooks/index.js": "/build/webhooks/index.js",
"/build/webhooks/create.js": "/build/webhooks/create.js",
"/build/webhooks/edit.js": "/build/webhooks/edit.js",
"/build/webhooks/show.js": "/build/webhooks/show.js",
"/public/v1/js/app.js": "/public/v1/js/app.js",
"/public/v1/js/app.js.LICENSE.txt": "/public/v1/js/app.js.LICENSE.txt",
"/public/v1/js/app_vue.js": "/public/v1/js/app_vue.js",
"/public/v1/js/app_vue.js.LICENSE.txt": "/public/v1/js/app_vue.js.LICENSE.txt",
"/public/v1/js/create.js": "/public/v1/js/create.js",
"/public/v1/js/create.js.LICENSE.txt": "/public/v1/js/create.js.LICENSE.txt",
"/public/v1/js/create_transaction.js": "/public/v1/js/create_transaction.js",
"/public/v1/js/create_transaction.js.LICENSE.txt": "/public/v1/js/create_transaction.js.LICENSE.txt",
"/public/v1/js/edit.js": "/public/v1/js/edit.js",
"/public/v1/js/edit.js.LICENSE.txt": "/public/v1/js/edit.js.LICENSE.txt",
"/public/v1/js/edit_transaction.js": "/public/v1/js/edit_transaction.js",
"/public/v1/js/edit_transaction.js.LICENSE.txt": "/public/v1/js/edit_transaction.js.LICENSE.txt",
"/public/v1/js/ff/accounts/create.js": "/public/v1/js/ff/accounts/create.js",
@@ -88,8 +84,6 @@
"/public/v1/js/ff/transactions/mass/edit-bulk.js": "/public/v1/js/ff/transactions/mass/edit-bulk.js",
"/public/v1/js/ff/transactions/mass/edit.js": "/public/v1/js/ff/transactions/mass/edit.js",
"/public/v1/js/ff/transactions/show.js": "/public/v1/js/ff/transactions/show.js",
"/public/v1/js/index.js": "/public/v1/js/index.js",
"/public/v1/js/index.js.LICENSE.txt": "/public/v1/js/index.js.LICENSE.txt",
"/public/v1/js/lib/Chart.bundle.min.js": "/public/v1/js/lib/Chart.bundle.min.js",
"/public/v1/js/lib/accounting.min.js": "/public/v1/js/lib/accounting.min.js",
"/public/v1/js/lib/bootstrap-multiselect.js": "/public/v1/js/lib/bootstrap-multiselect.js",
@@ -148,6 +142,12 @@
"/public/v1/js/lib/vue.js": "/public/v1/js/lib/vue.js",
"/public/v1/js/profile.js": "/public/v1/js/profile.js",
"/public/v1/js/profile.js.LICENSE.txt": "/public/v1/js/profile.js.LICENSE.txt",
"/public/v1/js/show.js": "/public/v1/js/show.js",
"/public/v1/js/show.js.LICENSE.txt": "/public/v1/js/show.js.LICENSE.txt"
"/public/v1/js/webhooks/create.js": "/public/v1/js/webhooks/create.js",
"/public/v1/js/webhooks/create.js.LICENSE.txt": "/public/v1/js/webhooks/create.js.LICENSE.txt",
"/public/v1/js/webhooks/edit.js": "/public/v1/js/webhooks/edit.js",
"/public/v1/js/webhooks/edit.js.LICENSE.txt": "/public/v1/js/webhooks/edit.js.LICENSE.txt",
"/public/v1/js/webhooks/index.js": "/public/v1/js/webhooks/index.js",
"/public/v1/js/webhooks/index.js.LICENSE.txt": "/public/v1/js/webhooks/index.js.LICENSE.txt",
"/public/v1/js/webhooks/show.js": "/public/v1/js/webhooks/show.js",
"/public/v1/js/webhooks/show.js.LICENSE.txt": "/public/v1/js/webhooks/show.js.LICENSE.txt"
}

View File

@@ -42,7 +42,7 @@ mix.js('src/edit_transaction.js', 'build').vue({version: 2});
mix.js('src/profile.js', 'build').vue({version: 2});
//
// // webhooks
mix.js('src/webhooks/index.js', 'build').vue({version: 2});
mix.js('src/webhooks/create.js', 'build').vue({version: 2});
mix.js('src/webhooks/edit.js', 'build').vue({version: 2});
mix.js('src/webhooks/show.js', 'build').vue({version: 2}).copy('build','../../../public/v1/js')
mix.js('src/webhooks/index.js', 'build/webhooks').vue({version: 2});
mix.js('src/webhooks/create.js', 'build/webhooks').vue({version: 2});
mix.js('src/webhooks/edit.js', 'build/webhooks').vue({version: 2});
mix.js('src/webhooks/show.js', 'build/webhooks').vue({version: 2}).copy('build','../../../public/v1/js')

View File

@@ -486,13 +486,15 @@ let transactions = function () {
// addedSplit, is called from the HTML
// for source account
const renderAccount = function (item, b, c) {
return item.name_with_balance + '<br><small class="text-muted">' + i18next.t('firefly.account_type_' + item.type) + '</small>';
return item.title + '<br><small class="text-muted">' + i18next.t('firefly.account_type_' + item.meta.type) + '</small>';
};
addAutocomplete({
selector: 'input.ac-source',
serverUrl: urls.account,
// filters: this.filters.source,
// onRenderItem: renderAccount,
onRenderItem: renderAccount,
valueField: 'id',
labelField: 'title',
onChange: changeSourceAccount,
onSelectItem: selectSourceAccount,
hiddenValue: this.entries[count].source_account.alpine_name
@@ -500,7 +502,9 @@ let transactions = function () {
addAutocomplete({
selector: 'input.ac-dest',
serverUrl: urls.account,
filters: this.filters.destination,
account_types: this.filters.destination,
valueField: 'id',
labelField: 'title',
onRenderItem: renderAccount,
onChange: changeDestinationAccount,
onSelectItem: selectDestinationAccount

View File

@@ -200,20 +200,23 @@ let transactions = function () {
// addedSplit, is called from the HTML
// for source account
const renderAccount = function (item, b, c) {
return item.name_with_balance + '<br><small class="text-muted">' + i18next.t('firefly.account_type_' + item.type) + '</small>';
console.log(item);
return item.title + '<br><small class="text-muted">' + i18next.t('firefly.account_type_' + item.meta.type) + '</small>';
};
addAutocomplete({
selector: 'input.ac-source',
serverUrl: urls.account,
filters: this.filters.source,
account_types: this.filters.source,
onRenderItem: renderAccount,
valueField: 'id',
labelField: 'title',
onChange: changeSourceAccount,
onSelectItem: selectSourceAccount
});
addAutocomplete({
selector: 'input.ac-dest',
serverUrl: urls.account,
filters: this.filters.destination,
account_types: this.filters.destination,
onRenderItem: renderAccount,
onChange: changeDestinationAccount,
onSelectItem: selectDestinationAccount
@@ -222,7 +225,7 @@ let transactions = function () {
selector: 'input.ac-category',
serverUrl: urls.category,
valueField: 'id',
labelField: 'name',
labelField: 'title',
onChange: changeCategory,
onSelectItem: changeCategory
});

View File

@@ -38,13 +38,14 @@ export function addAutocomplete(options) {
'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content
}
},
queryParam: 'filter[query]',
hiddenInput: true,
// preventBrowserAutocomplete: true,
highlightTyped: true,
liveServer: true,
};
if (typeof options.filters !== 'undefined' && options.filters.length > 0) {
params.serverParams.types = options.filters;
if (typeof options.account_types !== 'undefined' && options.account_types.length > 0) {
params.serverParams['filter[account_types]'] = options.account_types;
}
if (typeof options.onRenderItem !== 'undefined' && null !== options.onRenderItem) {
params.onRenderItem = options.onRenderItem;

View File

@@ -55,13 +55,12 @@ export function changeDestinationAccount(item, ac) {
export function selectDestinationAccount(item, ac) {
const index = parseInt(ac._searchInput.attributes['data-index'].value);
document.querySelector('#form')._x_dataStack[0].$data.entries[index].destination_account = {
id: item.id, name: item.name, alpine_name: item.name, type: item.type, currency_code: item.currency_code,
id: item.id, name: item.title, alpine_name: item.title, type: item.meta.type, currency_code: item.meta.currency_code,
};
document.querySelector('#form')._x_dataStack[0].changedDestinationAccount();
}
export function changeSourceAccount(item, ac) {
// console.log('changeSourceAccount');
if (typeof item === 'undefined') {
const index = parseInt(ac._searchInput.attributes['data-index'].value);
let source = document.querySelector('#form')._x_dataStack[0].$data.entries[index].source_account;
@@ -79,7 +78,7 @@ export function changeSourceAccount(item, ac) {
export function selectSourceAccount(item, ac) {
const index = parseInt(ac._searchInput.attributes['data-index'].value);
document.querySelector('#form')._x_dataStack[0].$data.entries[index].source_account = {
id: item.id, name: item.name, alpine_name: item.name, type: item.type, currency_code: item.currency_code,
id: item.id, name: item.title, alpine_name: item.title, type: item.meta.type, currency_code: item.meta.currency_code,
};
document.querySelector('#form')._x_dataStack[0].changedSourceAccount();
}

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'IP адресът, свързан с тази грешка, е: :ip',
'error_url' => 'URL адресът е: :url',
'error_user_agent' => рaузър агент: :userAgent',
'error_stacktrace' => 'Пълният стак на грешката е отдолу. Ако смятате, че това е грешка в Firefly III, можете да препратите това съобщение до <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii.org</a>. Това може да помогне за отстраняване на грешката, която току-що срещнахте.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'Ако предпочитате, можете също да отворите нов проблем на <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'Ако предпочитате, можете също да отворите нов проблем на https://github.com/firefly-iii/firefly-iii/issues.',
'error_stacktrace_below' => 'Пълният stacktrace е отдолу:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'L\'adreça IP d\'aquest error és: :ip',
'error_url' => 'L\'URL és: :url',
'error_user_agent' => 'Agent d\'usuari: :userAgent',
'error_stacktrace' => 'La traça completa és a continuació. Si creus que és un error de Firefly III, pots reenviar aquest missatge a <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii.org</a>. Podria ajudar a solucionar l\'error que acabes de trobar.',
'error_stacktrace' => 'La traça completa és a continuació. Si creus que és un error de Firefly III, pots reenviar aquest missatge a <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. Podria ajudar a solucionar l\'error que acabes de trobar.',
'error_github_html' => 'Si ho prefereixes, també pots obrir un nou issue a <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'Si ho prefereixes, també pots obrir un nou issue a https://github.com/firefly-iii/firefly-iii/issues.',
'error_stacktrace_below' => 'La traça completa és a continuació:',

View File

@@ -1961,19 +1961,19 @@ return [
'interest_calc_quarterly' => 'Per quadrimestre',
'initial_balance_account' => 'Compte de balanç inicial de :account',
'list_options' => 'Llista opcions',
'account_column_opt_drag_and_drop' => 'Drag and drop',
'account_column_opt_active' => 'Active',
'account_column_opt_name' => 'Name',
'account_column_opt_type' => 'Type',
'account_column_opt_liability_type' => 'Liability type',
'account_column_opt_liability_direction' => 'Liability direction',
'account_column_opt_liability_interest' => 'Liability interest',
'account_column_opt_number' => 'Account number',
'account_column_opt_current_balance' => 'Current balance',
'account_column_opt_amount_due' => 'Amount due',
'account_column_opt_last_activity' => 'Last activity',
'account_column_opt_balance_difference' => 'Balance difference',
'account_column_opt_menu' => 'Menu',
'account_column_opt_drag_and_drop' => 'Arrossega i deixa anar',
'account_column_opt_active' => 'Actiu',
'account_column_opt_name' => 'Nom',
'account_column_opt_type' => 'Tipus',
'account_column_opt_liability_type' => 'Tipus de passiu',
'account_column_opt_liability_direction' => 'Direcció del passiu',
'account_column_opt_liability_interest' => 'Interés del passiu',
'account_column_opt_number' => 'Número de compte',
'account_column_opt_current_balance' => 'Balanç actual',
'account_column_opt_amount_due' => 'Import pendent',
'account_column_opt_last_activity' => 'Darrera activitat',
'account_column_opt_balance_difference' => 'Diferència de saldo',
'account_column_opt_menu' => 'Menú',
// categories:
'new_category' => 'Nova categoria',
@@ -2157,7 +2157,7 @@ return [
'logout' => 'Tanca la sessió',
'logout_other_sessions' => 'Tanca les altres sessions',
'toggleNavigation' => 'Alternar navegació',
'toggle_dropdown' => 'Toggle dropdown',
'toggle_dropdown' => 'Commutar desplegable',
'searchPlaceholder' => 'Cerca...',
'version' => 'Versió',
'dashboard' => 'Panell de control',
@@ -2401,13 +2401,13 @@ return [
// page settings and wizard dialogs
'page_settings_header' => 'Page settings',
'visible_columns' => 'Visible columns',
'accounts_to_show' => 'Accounts to show',
'active_accounts_only' => 'Active accounts only',
'in_active_accounts_only' => 'Inactive accounts only',
'show_all_accounts' => 'Show all accounts',
'group_accounts' => 'Group accounts',
'page_settings_header' => 'Configuració de pàgina',
'visible_columns' => 'Columnes visibles',
'accounts_to_show' => 'Comptes a mostrar',
'active_accounts_only' => 'Només comptes actius',
'in_active_accounts_only' => 'Només comptes inactius',
'show_all_accounts' => 'Mostra tots els comptes',
'group_accounts' => 'Agrupa comptes',
// piggy banks:
'event_history' => 'Historial d\'esdeveniments',

View File

@@ -37,7 +37,7 @@ return [
// new user:
'bank_name' => 'Nom del banc',
'bank_balance' => 'Saldo',
'current_balance' => 'Current balance',
'current_balance' => 'Balanç actual',
'savings_balance' => 'Saldo d\'estalvis',
'credit_card_limit' => 'Límit de la targeta de crèdit',
'automatch' => 'Coincidir automàticament',

View File

@@ -67,13 +67,13 @@ return [
'source' => 'Origen',
'next_expected_match' => 'Pròxima coincidència esperada',
'automatch' => 'Cercar coincidència automàticament?',
'drag_and_drop' => 'Drag and drop',
'number' => 'Account number',
'current_balance' => 'Current balance',
'last_activity' => 'Last activity',
'amount_due' => 'Amount due',
'balance_difference' => 'Balance difference',
'menu' => 'Menu',
'drag_and_drop' => 'Arrossega i deixa anar',
'number' => 'Número de compte',
'current_balance' => 'Balanç actual',
'last_activity' => 'Darrera activitat',
'amount_due' => 'Import pendent',
'balance_difference' => 'Diferència de saldo',
'menu' => 'Menú',
/*
* PLEASE DO NOT EDIT THIS FILE DIRECTLY.

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'IP adresa související s touto chybou je: :ip',
'error_url' => 'Adresa URL je: :url',
'error_user_agent' => 'User agent: :userAgent',
'error_stacktrace' => 'Úplný zásobník je uveden níže. Pokud si myslíte, že se jedná o chybu ve Firefly III, můžete tuto zprávu přeposlat na <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii. rg</a>. To může pomoci opravit chybu, na kterou jste právě narazili.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'Pokud chcete, můžete vytvořit hlášení problému na <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'Pokud chcete, můžete vytvořit hlášení problému na https://github.com/firefly-iii/firefly-iii/issues.',
'error_stacktrace_below' => 'Celý zásobník je níže:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'IP-adressen relateret til denne fejl er: :ip',
'error_url' => 'URL er: :url',
'error_user_agent' => 'Brugeragent: :userAgent',
'error_stacktrace' => 'Den fulde stacktrace er nedenfor. Hvis du tror, at dette er en fejl i Firefly III, kan du videresende denne meddelelse til <a href="mailto:james@firefly-iii.org?subject=BUG!">james@ firefly-iii. rg</a>. Dette kan være behjælpeligt med at rette den fejl, du lige er stødt på.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'Hvis du foretrækker det, kan du også rapportere et nyt problem på <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'Hvis du foretrækker det, kan du også rapportere et nyt problem på https://github.com/firefly-iii/firefly-iii/issues.',
'error_stacktrace_below' => 'Den fulde stacktrace er nedenfor:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'Die IP-Adresse bezogen auf diesen Fehler lautet: :ip',
'error_url' => 'URL ist: :url',
'error_user_agent' => 'User Agent: :userAgent',
'error_stacktrace' => 'Der vollständige Stacktrace ist unten. Wenn Sie denken, dass dies ein Fehler in Firefly III ist, können Sie diese Nachricht an <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii weiterleiten. rg</a>. Dies kann helfen, den Fehler zu beheben, den Sie gerade gefunden haben.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'Wenn Sie es bevorzugen, können Sie auch einen Fehlerbericht auf <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a> eröffnen.',
'error_github_text' => 'Wenn Sie es bevorzugen, können Sie auch einen Fehlerbericht auf https://github.com/firefly-iii/firefly-iii/issues eröffnen.',
'error_stacktrace_below' => 'Der vollständige Stacktrace ist unten:',

View File

@@ -2401,13 +2401,13 @@ return [
// page settings and wizard dialogs
'page_settings_header' => 'Page settings',
'visible_columns' => 'Visible columns',
'accounts_to_show' => 'Accounts to show',
'active_accounts_only' => 'Active accounts only',
'in_active_accounts_only' => 'Inactive accounts only',
'show_all_accounts' => 'Show all accounts',
'group_accounts' => 'Group accounts',
'page_settings_header' => 'Seiteneinstellungen',
'visible_columns' => 'Sichtbare Spalten',
'accounts_to_show' => 'Anzuzeigende Konten',
'active_accounts_only' => 'Nur aktive Konten',
'in_active_accounts_only' => 'Nur inaktive Konten',
'show_all_accounts' => 'Alle Konten anzeigen',
'group_accounts' => 'Konten gruppieren',
// piggy banks:
'event_history' => 'Ereignisverlauf',

View File

@@ -37,7 +37,7 @@ return [
// new user:
'bank_name' => 'Name der Bank',
'bank_balance' => 'Kontostand',
'current_balance' => 'Current balance',
'current_balance' => 'Aktueller Kontostand',
'savings_balance' => 'Sparguthaben',
'credit_card_limit' => 'Kreditkartenlimit',
'automatch' => 'Automatisch reagieren',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'Η διεύθυνση IP που σχετίζεται με αυτό το σφάλμα είναι: :ip',
'error_url' => 'Το URL είναι: :url',
'error_user_agent' => 'User agent: :userAgent',
'error_stacktrace' => 'Το πλήρες stacktrace είναι παρακάτω. Αν νομίζετε ότι αυτό είναι ένα σφάλμα στο Firefly III, μπορείτε να προωθήσετε αυτό το μήνυμα στο <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii.org</a>. Αυτό μπορεί να βοηθήσει στη διόρθωση του σφάλματος που μόλις αντιμετωπίσατε.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'Αν προτιμάτε, μπορείτε επίσης να ανοίξετε ένα νέο ζήτημα στο <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'Αν προτιμάτε, μπορείτε επίσης να ανοίξετε ένα νέο ζήτημα στο https://github.com/firefly-iii/firefly-iii/issues.',
'error_stacktrace_below' => 'Το πλήρες stacktrace είναι παρακάτω:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'The IP address related to this error is: :ip',
'error_url' => 'URL is: :url',
'error_user_agent' => 'User agent: :userAgent',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'If you prefer, you can also open a new issue on <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'If you prefer, you can also open a new issue on https://github.com/firefly-iii/firefly-iii/issues.',
'error_stacktrace_below' => 'The full stacktrace is below:',

View File

@@ -111,7 +111,7 @@ return [
'error_ip' => 'The IP address related to this error is: :ip',
'error_url' => 'URL is: :url',
'error_user_agent' => 'User agent: :userAgent',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'If you prefer, you can also open a new issue on <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'If you prefer, you can also open a new issue on https://github.com/firefly-iii/firefly-iii/issues.',
'error_stacktrace_below' => 'The full stacktrace is below:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'La dirección IP relacionada con este error es: :ip',
'error_url' => 'La URL es: :url',
'error_user_agent' => 'Agente de usuario: :userAgent',
'error_stacktrace' => 'El stacktrace completo está a continuación. Si cree que esto es un error en Firefly III, puede reenviar este mensaje a <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii. rg</a>. Esto puede ayudar a solucionar el error que acaba de encontrar.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'Si prefiere, también puede abrir un nuevo issue en <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'Si prefiere, también puedes abrir un nuevo problema en https://github.com/firefly-iiii/firefly-iiii/issues.',
'error_stacktrace_below' => 'El stacktrace completo está a continuación:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'Tähän virheeseen liittyvä IP-osoite on: :ip',
'error_url' => 'URL on: :url',
'error_user_agent' => 'Käyttäjä-agentti: :userAgent',
'error_stacktrace' => 'Täydellinen stack trace on alla. Jos tämä on bugi Firefly III:ssa, voit lähettää tämän viestin osoitteeseen <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-ii. rg</a>. Tämä voi auttaa korjaamaan juuri kohtaamasi virheen.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'Jos haluat, voit myös avata uuden tiketin <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHubissa</a>.',
'error_github_text' => 'Jos haluat, voit myös avata uuden tiketin osoitteessa https://github.com/firefly-iii/firefly-iii/issues.',
'error_stacktrace_below' => 'Täydellinen stack trace:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'L\'adresse IP liée à cette erreur est : :ip',
'error_url' => 'L\'URL est : :url',
'error_user_agent' => 'User agent : :userAgent',
'error_stacktrace' => 'La stacktrace complète se trouve plus bas. Si vous pensez qu\'il s\'agit d\'un bogue dans Firefly III, vous pouvez transmettre ce message à <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii.org</a> (en anglais). Cela peut aider à corriger le bogue que vous venez de rencontrer.',
'error_stacktrace' => 'La stacktrace complète se trouve plus bas. Si vous pensez qu\'il s\'agit d\'un bogue dans Firefly III, vous pouvez transmettre ce message à <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a> (en anglais). Cela peut aider à corriger le bogue que vous venez de rencontrer.',
'error_github_html' => 'Si vous le préférez, vous pouvez également ouvrir un nouveau ticket sur <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a> (en anglais).',
'error_github_text' => 'Si vous le préférez, vous pouvez également ouvrir un nouveau ticket sur https://github.com/firefly-ii/firefly-iii/issues (en anglais).',
'error_stacktrace_below' => 'La stacktrace complète se trouve ci-dessous :',

View File

@@ -2402,11 +2402,11 @@ return [
// page settings and wizard dialogs
'page_settings_header' => 'Page settings',
'visible_columns' => 'Visible columns',
'accounts_to_show' => 'Accounts to show',
'active_accounts_only' => 'Active accounts only',
'in_active_accounts_only' => 'Inactive accounts only',
'show_all_accounts' => 'Show all accounts',
'visible_columns' => 'Colonnes visibles',
'accounts_to_show' => 'Comptes à afficher',
'active_accounts_only' => 'Comptes actifs uniquement',
'in_active_accounts_only' => 'Comptes inactifs uniquement',
'show_all_accounts' => 'Afficher tous les comptes',
'group_accounts' => 'Group accounts',
// piggy banks:

View File

@@ -37,7 +37,7 @@ return [
// new user:
'bank_name' => 'Nom de la banque',
'bank_balance' => 'Solde',
'current_balance' => 'Current balance',
'current_balance' => 'Solde actuel',
'savings_balance' => 'Solde de l\'épargne',
'credit_card_limit' => 'Limite de carte de crédit',
'automatch' => 'Correspondre automatiquement',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'The IP address related to this error is: :ip',
'error_url' => 'URL is: :url',
'error_user_agent' => 'User agent: :userAgent',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'If you prefer, you can also open a new issue on <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'If you prefer, you can also open a new issue on https://github.com/firefly-iii/firefly-iii/issues.',
'error_stacktrace_below' => 'The full stacktrace is below:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'Alamat IP yang berhubungan dengan kesalahan ini adalah: :ip',
'error_url' => 'URL adalah: :url',
'error_user_agent' => 'User agent: :userAgent',
'error_stacktrace' => 'Jejak tumpukan lengkap ada di bawah. Jika Anda merasa ada kutu di Firefly III, Anda dapat meneruskan pesan ini ke <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii.org</a>. Hal ini dapat membantu memperbaiki kutu yang baru saja Anda alami.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'Jika Anda mau, Anda juga dapat membuka isu baru di <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'Jika Anda mau, Anda juga dapat membuka isu baru di https://github.com/firefly-iii/firefly-iii/issues.',
'error_stacktrace_below' => 'Jejak tumpukan lengkap ada di bawah:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'L\'indirizzo IP relativo a questo errore è: :ip',
'error_url' => 'L\'URL è: :url',
'error_user_agent' => 'User agent: :userAgent',
'error_stacktrace' => 'Lo stacktrace completo è qui sotto. Se pensi che questo sia un bug in Firefly III, puoi inoltrare questo messaggio a <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii. rg</a>. Questo può aiutare a risolvere il bug che hai appena incontrato.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'Se preferisci puoi anche aprire una nuova issue su <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'Se preferisci puoi anche aprire una nuova issue su https://github.com/firefly-iii/firefly-iii/issues.',
'error_stacktrace_below' => 'Lo stacktrace completo è qui sotto:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'このエラーに関連する IP アドレス: :ip',
'error_url' => 'URL: :url',
'error_user_agent' => 'ユーザーエージェント: :userAgent',
'error_stacktrace' => '完全なスタックトレースは以下の通りです。これがバグだと考えるなら、このメッセージを<a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii.org</a>に届けることができます。これは先ほど遭遇したバグの修正に役立ちます。',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'ご希望の場合は、<a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>で新しいissueを作ることもできます。',
'error_github_text' => 'ご希望の場合は、https://github.com/fofoflifly-iii/firelify-ii/issuesで新しいissueを作ることもできます。',
'error_stacktrace_below' => '完全なスタックトレースは以下の通りです:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => '이 오류와 관련된 IP 주소: :ip',
'error_url' => 'URL: :url',
'error_user_agent' => '유저 에이전트: :userAgent',
'error_stacktrace' => '전체 스택 추적은 다음과 같습니다. Firefly III의 버그라고 생각되면 이 메시지를 <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii.org</a> 으로 전달해 주세요. 방금 발생한 버그를 수정하는 데 도움이 될 수 있습니다.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => '원한다면 <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>에 새로운 이슈를 오픈할 수 도 있습니다.',
'error_github_text' => '원한다면 https://github.com/firefly-iii/firefly-iii/issues 에 새로운 이슈를 오픈할 수도 있습니다.',
'error_stacktrace_below' => '전체 스택 추적은 다음과 같습니다:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'IP-adressen relatert til denne feilen er: :ip',
'error_url' => 'URL er: :url',
'error_user_agent' => 'Brukeragent: :userAgent',
'error_stacktrace' => 'Hele informasjonen er under. Hvis du tror dette er en feil i Firefly III, kan du videresende denne meldingen til <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-ii. rg</a>. Dette kan hjelpe med å rette opp feilen du nettopp har funnet.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'Hvis du foretrekker, kan du også åpne et nytt problem på <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'Hvis du foretrekker, kan du også åpne et nytt problem på https://github.com/firefly-ii/firefly-ii/issues.',
'error_stacktrace_below' => 'Hele informasjonen er:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'Het IP-adres met betrekking tot deze fout is: :ip',
'error_url' => 'URL is: :url',
'error_user_agent' => 'User agent: :userAgent',
'error_stacktrace' => 'De volledige stacktrace staat hieronder. Als je denkt dat dit een bug in Firefly III is, kun je dit bericht doorsturen naar <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii.org</a>. Dit kan helpen om de fout te verhelpen waar je net tegenaan bent gelopen.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'Als je wilt, kun je ook een nieuw issue openen op <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'Als je wilt, kun je ook een nieuw issue openen op https://github.com/firefly-iii/firefly-iii/issues.',
'error_stacktrace_below' => 'De volledige stacktrace staat hieronder:',

View File

@@ -138,7 +138,7 @@ return [
'error_ip' => 'IP-adressa relatert til denne feilen er: :ip',
'error_url' => 'URL er: :url',
'error_user_agent' => 'Brukaragent: :userAgent',
'error_stacktrace' => 'Hele informasjonen er under. Om du trur dette er ein feil i Firefly III, kan du videresende denne meldinga til <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-ii. rg</a>. Dette kan hjelpa med å rette opp feilen du nettopp har funne.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'Om du føretrekk, kan du òg åpne eit nytt problem på <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'Om du føretrekk, kan du òg åpne eit nytt problem på https://github.com/firefly-ii/firefly-ii/issues.',
'error_stacktrace_below' => 'Hele informasjonen er:',

View File

@@ -40,7 +40,7 @@ return [
'month_js' => 'MMMM YYYY',
// 'month_and_day' => '%B %e, %Y',
'month_and_day_moment_js' => 'MMM D, YYYY',
'month_and_day_moment_js' => 'D MMM YYYY',
'month_and_day_fns' => 'd MMMM y',
'month_and_day_js' => 'D MMMM YYYY',
@@ -64,7 +64,7 @@ return [
// 'date_time' => '%B %e, %Y, @ %T',
'date_time_js' => 'D MMMM YYYY [o] HH:mm:ss',
'date_time_fns' => 'do MMMM yyyy @ HH:mm:ss',
'date_time_fns_short' => 'MMMM do, yyyy @ HH:mm',
'date_time_fns_short' => 'D MMMM yyyy [o] HH:mm',
// 'specific_day' => '%e %B %Y',
'specific_day_js' => 'D MMMM YYYY',

View File

@@ -36,7 +36,7 @@ declare(strict_types=1);
return [
// common items
'greeting' => 'Cześć,',
'closing' => 'Jestę robotę',
'closing' => 'Bip bip,',
'signature' => 'Robot pocztowy Firefly III',
'footer_ps' => 'PS: Ta wiadomość została wysłana, ponieważ została wywołana przez żądanie z adresu IP :ipAddress .',
@@ -138,7 +138,7 @@ return [
'error_ip' => 'Adres IP związany z tym błędem to: :ip',
'error_url' => 'Adres URL to: :url',
'error_user_agent' => 'Agent użytkownika: :userAgent',
'error_stacktrace' => 'Pełny opis błędu znajduje się poniżej. Jeśli uważasz, że jest to błąd w Firefly III, możesz przesłać tę wiadomość do <a href="mailto:james@firefly-iii.org?subject=BUG!">james@firefly-iii. rg</a>. To może pomóc naprawić napotkany właśnie błąd.',
'error_stacktrace' => 'The full stacktrace is below. If you think this is a bug in Firefly III, you can forward this message to <a href="mailto:james@firefly-iii.org?subject=I%20found%20a%20bug!">james@firefly-iii.org</a>. This can help fix the bug you just encountered.',
'error_github_html' => 'Jeśli wolisz, możesz również otworzyć nowy problem na <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.',
'error_github_text' => 'Jeśli wolisz, możesz również otworzyć nowy problem na https://github.com/firefly-iii/firefly-iii/issues.',
'error_stacktrace_below' => 'Pełny opis błędu znajduje się poniżej:',

View File

@@ -42,7 +42,7 @@ return [
'fatal_error' => 'Wystąpił błąd krytyczny. Sprawdź pliki dziennika w "storage/logs" lub użyj "docker logs -f [container]", aby zobaczyć co się dzieje.',
'maintenance_mode' => 'Firefly III jest w trybie konserwacji.',
'be_right_back' => 'Zaraz wracam!',
'check_back' => 'Firefly III is down for some necessary maintenance. Please check back in a second. If you happen to see this message on the demo site, just wait a few minutes. The database is reset every few hours.',
'check_back' => 'Firefly III jest wyłączony na czas koniecznej konserwacji. Sprawdź ponownie za sekundę. Jeśli ta wiadomość pojawiła się na stronie demo, poczekaj kilka minut. Baza danych jest resetowana co kilka godzin.',
'error_occurred' => 'Ups! Wystąpił błąd.',
'db_error_occurred' => 'Ups! Wystąpił błąd bazy danych.',
'error_not_recoverable' => 'Niestety, nie mogliśmy się pozbierać po tym błędzie :(. Firefly III się popsuło. Błąd to:',

View File

@@ -1203,7 +1203,7 @@ return [
'rule_trigger_not_exists' => 'Transakcja nie istnieje',
'rule_trigger_not_has_attachments' => 'Transakcja nie ma załączników',
'rule_trigger_not_has_any_category' => 'Transakcja nie ma kategorii',
'rule_trigger_not_has_any_budget' => 'Transaction has no budget',
'rule_trigger_not_has_any_budget' => 'Transakcja bez budżetu',
'rule_trigger_not_has_any_bill' => 'Transakcja bez rachunku',
'rule_trigger_not_has_any_tag' => 'Transakcja bez tagów',
'rule_trigger_not_any_notes' => 'Transakcja bez notatek',
@@ -1286,8 +1286,8 @@ return [
'rule_action_append_notes_to_descr' => 'Dołącz notatki do opisu',
'rule_action_move_descr_to_notes' => 'Zastąp notatki opisem',
'rule_action_move_notes_to_descr' => 'Zastąp opis notatkami',
'rule_action_set_amount_choice' => 'Set amount to ..',
'rule_action_set_amount' => 'Set amount to ":action_value"',
'rule_action_set_amount_choice' => 'Ustaw kwotę na ..',
'rule_action_set_amount' => 'Ustaw kwotę na ":action_value"',
'rule_action_set_destination_to_cash_choice' => 'Ustaw konto docelowe na konto gotówkowe',
'rule_action_set_source_to_cash_choice' => 'Ustaw konto źródłowe na konto gotówkowe',
'rulegroup_for_bills_title' => 'Grupa reguł dla rachunków',
@@ -1421,10 +1421,10 @@ return [
'administrations_index_menu' => 'Zarządzanie finansami',
'administrations_breadcrumb' => 'Financial administrations',
'administrations_page_title' => 'Financial administrations',
'administrations_page_sub_title' => 'Overview',
'administrations_page_sub_title' => 'Przegląd',
'create_administration' => 'Create new administration',
'administration_owner' => 'Administration owner: {{email}}',
'administration_you' => 'Your role: {{role}}',
'administration_you' => 'Twoja rola: {{role}}',
'other_users_in_admin' => 'Other users in this administration',
'administrations_create_breadcrumb' => 'Create new financial administration',
'administrations_page_create_sub_title' => 'Create new financial administration',
@@ -1434,19 +1434,19 @@ return [
'administrations_page_edit_sub_title' => 'Edit financial administration ":title"',
// roles
'administration_role_owner' => 'Owner',
'administration_role_ro' => 'Read-only',
'administration_role_mng_trx' => 'Manage transactions',
'administration_role_mng_meta' => 'Manage classification and meta-data',
'administration_role_mng_budgets' => 'Manage budgets',
'administration_role_mng_piggies' => 'Manage piggy banks',
'administration_role_mng_subscriptions' => 'Manage subscriptions',
'administration_role_mng_rules' => 'Manage rules',
'administration_role_mng_recurring' => 'Manage recurring transactions ',
'administration_role_owner' => 'Właściciel',
'administration_role_ro' => 'Tylko odczyt',
'administration_role_mng_trx' => 'Zarządzanie transakcjami',
'administration_role_mng_meta' => 'Zarządzanie klasyfikacją i meta-danymi',
'administration_role_mng_budgets' => 'Zarządzanie budżetami',
'administration_role_mng_piggies' => 'Zarządzanie skarbonkami',
'administration_role_mng_subscriptions' => 'Zarządzanie subskrypcjami',
'administration_role_mng_rules' => 'Zarządzanie regułami',
'administration_role_mng_recurring' => 'Zarządzanie transakcjami cyklicznymi ',
'administration_role_mng_webhooks' => 'Manage webhooks',
'administration_role_mng_currencies' => 'Manage currencies',
'administration_role_view_reports' => 'View reports',
'administration_role_full' => 'Full access',
'administration_role_mng_currencies' => 'Zarządzanie walutami',
'administration_role_view_reports' => 'Przeglądanie raportów',
'administration_role_full' => 'Pełny dostęp',
// profile:
'purge_data_title' => 'Wyczyść dane z Firefly III',
@@ -1775,7 +1775,7 @@ return [
'auto_budget_help' => 'Możesz przeczytać więcej o tej funkcji w pomocy. Kliknij ikonę (?) u góry prawej strony.',
'auto_budget_reset_icon' => 'Ten budżet będzie okresowo ustalany',
'auto_budget_rollover_icon' => 'Kwota budżetu będzie okresowo rosła',
'auto_budget_adjusted_icon' => 'The budget amount will increase periodically and will correct for overspending',
'auto_budget_adjusted_icon' => 'Kwota budżetu będzie okresowo wzrastać i korygować się o nadmierne wydatki',
'remove_budgeted_amount' => 'Usuń zabudżetowaną kwotę w :currency',
// bills:
@@ -1961,18 +1961,18 @@ return [
'interest_calc_quarterly' => 'Kwartalnie',
'initial_balance_account' => 'Początkowe saldo konta :account',
'list_options' => 'Opcje listy',
'account_column_opt_drag_and_drop' => 'Drag and drop',
'account_column_opt_active' => 'Active',
'account_column_opt_name' => 'Name',
'account_column_opt_type' => 'Type',
'account_column_opt_liability_type' => 'Liability type',
'account_column_opt_drag_and_drop' => 'Przeciągnij i upuść',
'account_column_opt_active' => 'Aktywne',
'account_column_opt_name' => 'Nazwa',
'account_column_opt_type' => 'Rodzaj',
'account_column_opt_liability_type' => 'Rodzaj zobowiązania',
'account_column_opt_liability_direction' => 'Liability direction',
'account_column_opt_liability_interest' => 'Liability interest',
'account_column_opt_number' => 'Account number',
'account_column_opt_current_balance' => 'Current balance',
'account_column_opt_amount_due' => 'Amount due',
'account_column_opt_last_activity' => 'Last activity',
'account_column_opt_balance_difference' => 'Balance difference',
'account_column_opt_liability_interest' => 'Odsetki od zobowiązań',
'account_column_opt_number' => 'Numer konta',
'account_column_opt_current_balance' => 'Bieżące saldo',
'account_column_opt_amount_due' => 'Do zapłaty',
'account_column_opt_last_activity' => 'Ostatnia aktywność',
'account_column_opt_balance_difference' => 'Różnica salda',
'account_column_opt_menu' => 'Menu',
// categories:
@@ -2005,12 +2005,12 @@ return [
// transactions:
'wait_loading_transaction' => 'Poczekaj na załadowanie formularza',
'wait_loading_data' => 'Please wait for your information to load...',
'wait_attachments' => 'Please wait for the attachments to upload.',
'wait_loading_data' => 'Proszę poczekać na załadowanie informacji...',
'wait_attachments' => 'Proszę poczekać na przesłanie załączników.',
'errors_upload' => 'The upload has failed. Please check your browser console for the error.',
'amount_foreign_if' => 'Amount in foreign currency, if any',
'amount_destination_account' => 'Amount in the currency of the destination account',
'edit_transaction_title' => 'Edit transaction ":description"',
'edit_transaction_title' => 'Edytuj transakcję ":description"',
'unreconcile' => 'Cofnij uzgodnienie',
'update_withdrawal' => 'Modyfikuj wypłatę',
'update_deposit' => 'Modyfikuj wpłatę',
@@ -2030,7 +2030,7 @@ return [
'deleted_transfer' => 'Pomyślnie usunięto transfer ":description"',
'deleted_reconciliation' => 'Pomyślnie usunięto transakcję uzgadniania ":description"',
'stored_journal' => 'Pomyślnie utworzono nową transakcję ":description"',
'stored_journal_js' => 'Successfully created new transaction "{{description}}"',
'stored_journal_js' => 'Pomyślnie utworzono nową transakcję "{{description}}"',
'stored_journal_no_descr' => 'Pomyślnie utworzono nową transakcję',
'updated_journal_no_descr' => 'Pomyślnie zaktualizowano Twoją transakcję',
'select_transactions' => 'Wybierz transakcje',
@@ -2339,7 +2339,7 @@ return [
'description' => 'Opis',
'sum_of_period' => 'Suma dla tego okresu',
'average_in_period' => 'Średnia dla tego okresu',
'no_account_role' => '(no role)',
'no_account_role' => '(brak roli)',
'account_role_defaultAsset' => 'Domyślne konto aktywów',
'account_role_sharedAsset' => 'Współdzielone konto aktywów',
'account_role_savingAsset' => 'Konto oszczędnościowe',
@@ -2401,12 +2401,12 @@ return [
// page settings and wizard dialogs
'page_settings_header' => 'Page settings',
'visible_columns' => 'Visible columns',
'page_settings_header' => 'Ustawienia strony',
'visible_columns' => 'Widoczne kolumny',
'accounts_to_show' => 'Accounts to show',
'active_accounts_only' => 'Active accounts only',
'in_active_accounts_only' => 'Inactive accounts only',
'show_all_accounts' => 'Show all accounts',
'active_accounts_only' => 'Tylko aktywne konta',
'in_active_accounts_only' => 'Tylko nieaktywne konta',
'show_all_accounts' => 'Pokaż wszystkie konta',
'group_accounts' => 'Group accounts',
// piggy banks:
@@ -2824,7 +2824,7 @@ return [
'ale_action_add_to_piggy' => 'Skarbonka',
'ale_action_remove_from_piggy' => 'Skarbonka',
'ale_action_add_tag' => 'Dodano tag',
'ale_action_update_amount' => 'Updated amount',
'ale_action_update_amount' => 'Zaktualizowano kwotę',
// dashboard
'enable_auto_convert' => 'Włącz przeliczenie walut',

View File

@@ -37,7 +37,7 @@ return [
// new user:
'bank_name' => 'Nazwa banku',
'bank_balance' => 'Saldo',
'current_balance' => 'Current balance',
'current_balance' => 'Bieżące saldo',
'savings_balance' => 'Saldo konta oszczędnościowego',
'credit_card_limit' => 'Limit karty kredytowej',
'automatch' => 'Dopasuj automatycznie',

View File

@@ -78,7 +78,7 @@ return [
'reports_index_intro' => 'Skorzystaj z tych raportów, aby uzyskać szczegółowe informacje o swoich finansach.',
'reports_index_inputReportType' => 'Wybierz typ raportu. Sprawdź stronę pomocy, aby zobaczyć, co pokazuje każdy raport.',
'reports_index_inputAccountsSelect' => 'Możesz wykluczyć lub uwzględnić konta zasobów według własnego uznania.',
'reports_index_inputDateRange' => 'The selected date range is entirely up to you: from one day to 10 years or more.',
'reports_index_inputDateRange' => 'Wybrany zakres dat zależy wyłącznie od Ciebie: od jednego dnia do 10 lub więcej lat.',
'reports_index_extra-options-box' => 'W zależności od wybranego raportu możesz wybrać dodatkowe filtry i opcje tutaj. Obserwuj to pole, gdy zmieniasz typy raportów.',
// reports (reports)

View File

@@ -67,12 +67,12 @@ return [
'source' => 'Źródło',
'next_expected_match' => 'Następne oczekiwane dopasowanie',
'automatch' => 'Auto dopasowanie?',
'drag_and_drop' => 'Drag and drop',
'number' => 'Account number',
'current_balance' => 'Current balance',
'last_activity' => 'Last activity',
'amount_due' => 'Amount due',
'balance_difference' => 'Balance difference',
'drag_and_drop' => 'Przeciągnij i upuść',
'number' => 'Numer konta',
'current_balance' => 'Bieżące saldo',
'last_activity' => 'Ostatnia aktywność',
'amount_due' => 'Do zapłaty',
'balance_difference' => 'Różnica salda',
'menu' => 'Menu',
/*

View File

@@ -70,5 +70,5 @@ return [
'cannot_find_budget' => 'Firefly III nie może znaleźć budżetu ":name"',
'cannot_find_category' => 'Firefly III nie może znaleźć kategorii ":name"',
'cannot_set_budget' => 'Firefly III nie może ustawić budżetu ":name" dla transakcji typu ":type"',
'journal_invalid_amount' => 'Firefly III can\'t set amount ":amount" because it is not a valid number.',
'journal_invalid_amount' => 'Firefly III nie może ustawić kwoty ":amount", ponieważ nie jest to prawidłowa liczba.',
];

View File

@@ -45,8 +45,8 @@ return [
'invalid_query_currency' => 'Twoje zapytanie zawiera konta, które mają różne ustawienia walutowe, co jest niedozwolone.',
'iban' => 'To nie jest prawidłowy IBAN.',
'zero_or_more' => 'Wartość nie może być ujemna.',
'more_than_zero' => 'The value must be more than zero.',
'more_than_zero_correct' => 'The value must be zero or more.',
'more_than_zero' => 'Wartość musi być większa niż zero.',
'more_than_zero_correct' => 'Wartość musi wynosić zero lub więcej.',
'no_asset_account' => 'To nie jest konto aktywów.',
'date_or_time' => 'Wartość musi być prawidłową datą lub czasem (ISO 8601).',
'source_equals_destination' => 'Konto źródłowe jest równe kontu docelowemu.',
@@ -55,11 +55,11 @@ return [
'reconciled_forbidden_field' => 'Ta transakcja jest już uzgodniona, nie można zmienić ":field"',
'deleted_user' => 'Ze względu na zabezpieczenia nie możesz się zarejestrować używając tego adresu e-mail.',
'rule_trigger_value' => 'Ta wartość jest nieprawidłowa dla wybranego wyzwalacza.',
'rule_action_expression' => 'Invalid expression. :error',
'rule_action_expression' => 'Nieprawidłowe wyrażenie. :error',
'rule_action_value' => 'Ta wartość jest nieprawidłowa dla wybranej akcji.',
'file_already_attached' => 'Przesłany plik ":name" jest już dołączony do tego obiektu.',
'file_attached' => 'Pomyślnie wgrano plik ":name".',
'file_zero' => 'The file is zero bytes in size.',
'file_zero' => 'Plik ma rozmiar zero bajtów.',
'must_exist' => 'Identyfikator w polu :attribute nie istnieje w bazie danych.',
'all_accounts_equal' => 'Wszystkie konta w tym polu muszą być takie same.',
'group_title_mandatory' => 'Tytuł grupy jest obowiązkowy, gdy istnieje więcej niż jedna transakcja.',
@@ -68,7 +68,7 @@ return [
'invalid_selection' => 'Twój wybór jest nieprawidłowy.',
'belongs_user' => 'Ta wartość jest powiązana z obiektem, który nie istnieje.',
'belongs_user_or_user_group' => 'This value is linked to an object that does not seem to exist in your current financial administration.',
'no_access_group' => 'The user has no access to this user group.',
'no_access_group' => 'Użytkownik nie ma dostępu do tej grupy użytkowników.',
'no_accepted_roles_defined' => 'No access roles have been defined for this endpoint, access denied.',
'at_least_one_transaction' => 'Wymaga co najmniej jednej transakcji.',
'recurring_transaction_id' => 'Wymaga co najmniej jednej transakcji.',
@@ -199,7 +199,7 @@ return [
*
*/
'secure_password' => 'This is not a secure password. Please try again. For more information, visit https://bit.ly/FF3-password',
'secure_password' => 'To hasło nie jest bezpieczne. Proszę spróbować ponownie. Aby uzyskać więcej informacji odwiedź https://bit.ly/FF3-password',
'valid_recurrence_rep_type' => 'Nieprawidłowy typ powtórzeń dla cyklicznych transakcji.',
'valid_recurrence_rep_moment' => 'Nieprawidłowy moment powtórzenia dla tego typu powtórzenia.',
'invalid_account_info' => 'Nieprawidłowe informacje o koncie.',

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