Merge branch 'release/4.8.1.7'

This commit is contained in:
James Cole 2019-10-26 08:07:10 +02:00
commit 64a2f22b13
41 changed files with 570 additions and 31 deletions

View File

@ -1,7 +1,7 @@
sudo: required
language: bash
env:
- VERSION=4.8.1.6
- VERSION=4.8.1.7
dist: xenial

View File

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

View File

@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Requests\TransactionStoreRequest;
use FireflyIII\Api\V1\Requests\TransactionUpdateRequest;
use FireflyIII\Events\StoredTransactionGroup;
use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Exceptions\DuplicateTransactionException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
@ -279,7 +280,20 @@ class TransactionController extends Controller
Log::channel('audit')
->info('Store new transaction over API.', $data);
try {
$transactionGroup = $this->groupRepository->store($data);
} catch (DuplicateTransactionException $e) {
// return bad validation message.
// TODO use Laravel's internal validation thing to do this.
$response = [
'message' => 'The given data was invalid.',
'errors' => [
'transactions.0.description' => [$e->getMessage()],
],
];
return response()->json($response, 422);
}
event(new StoredTransactionGroup($transactionGroup));

View File

@ -0,0 +1,58 @@
<?php
/**
* TransferRequest.php
* Copyright (c) 2019 thegrumpydictator@gmail.com
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Api\V1\Requests\Search;
use FireflyIII\Api\V1\Requests\Request;
use FireflyIII\Rules\IsTransferAccount;
/**
* Class TransferRequest
*/
class TransferRequest extends Request
{
/**
* Authorize logged in users.
*
* @return bool
*/
public function authorize(): bool
{
// Only allow authenticated users
return auth()->check();
}
/**
* @return array
*/
public function rules(): array
{
return [
'source' => ['required', new IsTransferAccount],
'destination' => ['required', new IsTransferAccount],
'amount' => 'required|numeric|more:0',
'description' => 'required|min:1',
'date' => 'required|date',
];
}
}

View File

@ -59,6 +59,7 @@ class TransactionStoreRequest extends Request
{
$data = [
'group_title' => $this->string('group_title'),
'error_if_duplicate_hash' => $this->boolean('error_if_duplicate_hash'),
'transactions' => $this->getTransactionData(),
];
@ -75,6 +76,7 @@ class TransactionStoreRequest extends Request
$rules = [
// basic fields for group:
'group_title' => 'between:1,1000|nullable',
'error_if_duplicate_hash' => [new IsBoolean],
// transaction rules (in array for splits):
'transactions.*.type' => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation',

View File

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

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Factory;
use FireflyIII\Exceptions\DuplicateTransactionException;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\User;
@ -52,10 +53,13 @@ class TransactionGroupFactory
* @param array $data
*
* @return TransactionGroup
* @throws DuplicateTransactionException
*/
public function create(array $data): TransactionGroup
{
$this->journalFactory->setUser($this->user);
$this->journalFactory->setErrorOnHash($data['error_if_duplicate_hash']);
$collection = $this->journalFactory->create($data);
$title = $data['group_title'] ?? null;
$title = '' === $title ? null : $title;

View File

@ -26,10 +26,12 @@ namespace FireflyIII\Factory;
use Carbon\Carbon;
use Exception;
use FireflyIII\Exceptions\DuplicateTransactionException;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionJournalMeta;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
@ -72,6 +74,8 @@ class TransactionJournalFactory
private $typeRepository;
/** @var User The user */
private $user;
/** @var bool */
private $errorOnHash;
/**
* Constructor.
@ -81,6 +85,7 @@ class TransactionJournalFactory
*/
public function __construct()
{
$this->errorOnHash = false;
$this->fields = [
// sepa
'sepa_cc', 'sepa_ct_op', 'sepa_ct_id',
@ -119,6 +124,7 @@ class TransactionJournalFactory
* @param array $data
*
* @return Collection
* @throws DuplicateTransactionException
*/
public function create(array $data): Collection
{
@ -193,11 +199,15 @@ class TransactionJournalFactory
* @param NullArrayObject $row
*
* @return TransactionJournal|null
* @throws Exception
* @throws DuplicateTransactionException
*/
private function createJournal(NullArrayObject $row): ?TransactionJournal
{
$row['import_hash_v2'] = $this->hashArray($row);
$this->errorIfDuplicate($row['import_hash_v2']);
/** Some basic fields */
$type = $this->typeRepository->findTransactionType(null, $row['type']);
$carbon = $row['date'] ?? new Carbon;
@ -376,6 +386,30 @@ class TransactionJournalFactory
return $journal;
}
/**
* If this transaction already exists, throw an error.
*
* @param string $hash
*
* @throws DuplicateTransactionException
*/
private function errorIfDuplicate(string $hash): void
{
if (false === $this->errorOnHash) {
return;
}
$result = null;
if ($this->errorOnHash) {
/** @var TransactionJournalMeta $result */
$result = TransactionJournalMeta::where('data', json_encode($hash, JSON_THROW_ON_ERROR))
->with(['transactionJournal', 'transactionJournal.transactionGroup'])
->first();
}
if (null !== $result) {
throw new DuplicateTransactionException(sprintf('Duplicate of transaction #%d.', $result->transactionJournal->transaction_group_id));
}
}
/**
* @param TransactionCurrency|null $currency
* @param Account $account
@ -485,4 +519,14 @@ class TransactionJournalFactory
throw new FireflyException(sprintf('Destination: %s', $this->accountValidator->destError)); // @codeCoverageIgnore
}
}
/**
* @param bool $errorOnHash
*/
public function setErrorOnHash(bool $errorOnHash): void
{
$this->errorOnHash = $errorOnHash;
}
}

View File

@ -78,7 +78,7 @@ class CreateController extends Controller
$defaultCurrency = app('amount')->getDefaultCurrency();
$previousUri = $this->rememberPreviousUri('transactions.create.uri');
$parts = parse_url($previousUri);
$previousUri = sprintf('%s://%s/%s', $parts['scheme'], $parts['host'], $parts['path']);
$previousUri = sprintf('%s://%s/%s', $parts['scheme'], $parts['host'] ?? '', $parts['path'] ?? '');
session()->put('preFilled', $preFilled);

View File

@ -83,7 +83,7 @@ class EditController extends Controller
$cash = $repository->getCashAccount();
$previousUri = $this->rememberPreviousUri('transactions.edit.uri');
$parts = parse_url($previousUri);
$previousUri = sprintf('%s://%s/%s', $parts['scheme'], $parts['host'], $parts['path']);
$previousUri = sprintf('%s://%s/%s', $parts['scheme'], $parts['host'], $parts['path'] ?? '');
return view('transactions.edit', compact('cash', 'transactionGroup', 'allowedOpposingTypes', 'accountToTypes', 'defaultCurrency', 'previousUri'));

View File

@ -27,6 +27,7 @@ namespace FireflyIII\Repositories\TransactionGroup;
use Carbon\Carbon;
use DB;
use Exception;
use FireflyIII\Exceptions\DuplicateTransactionException;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\TransactionGroupFactory;
use FireflyIII\Models\AccountMeta;
@ -314,6 +315,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface
* @param array $data
*
* @return TransactionGroup
* @throws DuplicateTransactionException
*/
public function store(array $data): TransactionGroup
{

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\TransactionGroup;
use FireflyIII\Exceptions\DuplicateTransactionException;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Support\NullArrayObject;
use FireflyIII\User;
@ -125,6 +126,7 @@ interface TransactionGroupRepositoryInterface
* @param array $data
*
* @return TransactionGroup
* @throws DuplicateTransactionException
*/
public function store(array $data): TransactionGroup;

View File

@ -0,0 +1,73 @@
<?php
/**
* IsTransferAccount.php
* Copyright (c) 2019 thegrumpydictator@gmail.com
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Rules;
use FireflyIII\Models\TransactionType;
use FireflyIII\Validation\AccountValidator;
use Illuminate\Contracts\Validation\Rule;
use Log;
/**
* Class IsTransferAccount
*/
class IsTransferAccount implements Rule
{
/**
* Get the validation error message.
*
* @return string|array
*/
public function message(): string
{
return (string)trans('validation.not_transfer_account');
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
*
* @return bool
*/
public function passes($attribute, $value): bool
{
Log::debug(sprintf('Now in %s(%s)', __METHOD__, $value));
/** @var AccountValidator $validator */
$validator = app(AccountValidator::class);
$validator->setTransactionType(TransactionType::TRANSFER);
$validator->setUser(auth()->user());
$validAccount = $validator->validateSource(null, (string)$value);
if (true === $validAccount) {
Log::debug('Found account based on name. Return true.');
// found by name, use repos to return.
return true;
}
$validAccount = $validator->validateSource((int)$value, null);
Log::debug(sprintf('Search by id (%d), result is %s.', (int)$value, var_export($validAccount, true)));
return !(false === $validAccount);
}
}

View File

@ -22,7 +22,16 @@
namespace FireflyIII\Support\Search;
use Illuminate\Support\Collection;
/**
* Interface GenericSearchInterface
*/
interface GenericSearchInterface
{
/**
* @return Collection
*/
public function search(): Collection;
}

View File

@ -0,0 +1,147 @@
<?php
/**
* TransferSearch.php
* Copyright (c) 2019 thegrumpydictator@gmail.com
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Support\Search;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\User;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
use InvalidArgumentException;
use Log;
/**
* Class TransferSearch
*/
class TransferSearch implements GenericSearchInterface
{
/** @var AccountRepositoryInterface */
private $accountRepository;
/** @var string */
private $amount;
/** @var Carbon */
private $date;
/** @var string */
private $description;
/** @var Account */
private $destination;
/** @var Account */
private $source;
/** @var array */
private $types;
public function __construct()
{
$this->accountRepository = app(AccountRepositoryInterface::class);
$this->types = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
}
/**
* @return Collection
*/
public function search(): Collection
{
/** @var User $user */
$user = auth()->user();
$query = $user->transactionJournals()
->leftJoin(
'transactions as source', static function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'source.transaction_journal_id');
$join->where('source.amount', '<', '0');
}
)
->leftJoin(
'transactions as destination', static function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'destination.transaction_journal_id');
$join->where('destination.amount', '>', '0');
}
)
->where('source.account_id', $this->source->id)
->where('destination.account_id', $this->destination->id)
->where('transaction_journals.description', $this->description)
->where('destination.amount', $this->amount)
->where('transaction_journals.date', $this->date->format('Y-m-d 00:00:00'))
;
return $query->get(['transaction_journals.id', 'transaction_journals.transaction_group_id']);
}
/**
* @param string $amount
*/
public function setAmount(string $amount): void
{
$this->amount = $amount;
}
/**
* @param string $date
*/
public function setDate(string $date): void
{
try {
$carbon = Carbon::createFromFormat('Y-m-d', $date);
} catch (InvalidArgumentException $e) {
Log::error($e->getMessage());
$carbon = Carbon::now();
}
$this->date = $carbon;
}
/**
* @param string $description
*/
public function setDescription(string $description): void
{
$this->description = $description;
}
/**
* @param string $destination
*/
public function setDestination(string $destination): void
{
if (is_numeric($destination)) {
$this->destination = $this->accountRepository->findNull((int)$destination);
}
if (null === $this->destination) {
$this->destination = $this->accountRepository->findByName($destination, $this->types);
}
}
/**
* @param string $source
*/
public function setSource(string $source): void
{
if (is_numeric($source)) {
$this->source = $this->accountRepository->findNull((int)$source);
}
if (null === $this->source) {
$this->source = $this->accountRepository->findByName($source, $this->types);
}
}
}

View File

@ -2,6 +2,15 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [4.8.1.7 (API 0.10.5)] - 2019-10-26
### Fixed
- Error when creating transactions from the index of Firefly III.
### API
- Firefly III can filter duplicate transactions.
- New endpoint that can search for specific transfers.
## [4.8.1.6 (API 0.10.4)] - 2019-10-25
### Fixed

12
composer.lock generated
View File

@ -3213,16 +3213,16 @@
},
{
"name": "psr/log",
"version": "1.1.0",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
"reference": "bf73deb2b3b896a9d9c75f3f0d88185d2faa27e2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
"url": "https://api.github.com/repos/php-fig/log/zipball/bf73deb2b3b896a9d9c75f3f0d88185d2faa27e2",
"reference": "bf73deb2b3b896a9d9c75f3f0d88185d2faa27e2",
"shasum": ""
},
"require": {
@ -3231,7 +3231,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
"dev-master": "1.1.x-dev"
}
},
"autoload": {
@ -3256,7 +3256,7 @@
"psr",
"psr-3"
],
"time": "2018-11-20T15:27:04+00:00"
"time": "2019-10-25T08:06:51+00:00"
},
{
"name": "psr/simple-cache",

View File

@ -125,8 +125,8 @@ return [
'is_demo_site' => false,
],
'encryption' => null === env('USE_ENCRYPTION') || env('USE_ENCRYPTION') === true,
'version' => '4.8.1.6',
'api_version' => '0.10.4',
'version' => '4.8.1.7',
'api_version' => '0.10.5',
'db_version' => 11,
'maxUploadSize' => 15242880,
'send_error_message' => env('SEND_ERROR_MESSAGE', true),

9
resources/lang/.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
ca_ES
da_DK
he_IL
ja_JP
pt_PT
sl_SI
uk_UA
sv_SE
sr_CS

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Potřebujete alespoň jedno opakování.',
'require_repeat_until' => 'Require either a number of repetitions, or an end date (repeat_until). Not both.',
'require_currency_info' => 'Obsah tohoto pole je neplatný bez informace o měně.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'The content of this field is invalid without foreign amount information.',
'equal_description' => 'Popis transakce nesmí být stejný jako globální popis.',
'file_invalid_mime' => 'Soubor ":name" je typu ":mime", který není schválen pro nahrání.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Mindestens eine Wiederholung erforderlich.',
'require_repeat_until' => 'Erfordert entweder eine Anzahl von Wiederholungen oder ein Enddatum (repeat_until). Nicht beides.',
'require_currency_info' => 'Der Inhalt dieses Feldes ist ohne Währungsinformationen ungültig.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'Der Inhalt dieses Feldes ist ohne Fremdbetragsangaben ungültig.',
'equal_description' => 'Die Transaktionsbeschreibung darf nicht der globalen Beschreibung entsprechen.',
'file_invalid_mime' => 'Die Datei „:name” ist vom Typ „:mime”, welcher nicht zum Hochladen zugelassen ist.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Απαιτείται τουλάχιστον μία επανάληψη.',
'require_repeat_until' => 'Απαιτείται είτε ένας αριθμός επαναλήψεων, ή μία ημερομηνία λήξης (repeat_until). Όχι και τα δύο.',
'require_currency_info' => 'Το περιεχόμενο αυτού του πεδίου δεν είναι έγκυρη χωρίς νομισματικές πληροφορίες.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'Το περιεχόμενο αυτού του πεδίου δεν είναι έγκυρο χωρίς πληροφορίες ετερόχθονος ποσού.',
'equal_description' => 'Η περιγραφή της συναλλαγής δεν πρέπει να ισούται με καθολική περιγραφή.',
'file_invalid_mime' => 'Το αρχείο ":name" είναι τύπου ":mime" που δεν είναι αποδεκτός ως νέας μεταφόρτωσης.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Need at least one repetition.',
'require_repeat_until' => 'Require either a number of repetitions, or an end date (repeat_until). Not both.',
'require_currency_info' => 'The content of this field is invalid without currency information.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'The content of this field is invalid without foreign amount information.',
'equal_description' => 'Transaction description should not equal global description.',
'file_invalid_mime' => 'File ":name" is of type ":mime" which is not accepted as a new upload.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Se necesita al menos una repetición.',
'require_repeat_until' => 'Se precisa un número de repeticiones o una fecha de finalización (repeat_until). No ambas.',
'require_currency_info' => 'El contenido de este campo no es válido sin la información montearia.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'El contenido de este campo no es válido sin información de cantidad extranjera.',
'equal_description' => 'La descripción de la transacción no debería ser igual a la descripción global.',
'file_invalid_mime' => 'El archivo ":name" es de tipo ":mime", el cual no se acepta.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Besoin d\'au moins une répétition.',
'require_repeat_until' => 'Besoin dun certain nombre de répétitions ou d\'une date de fin (repeat_until). Pas les deux.',
'require_currency_info' => 'Le contenu de ce champ n\'est pas valide sans informations sur la devise.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'Le contenu de ce champ est invalide sans informations sur le montant étranger.',
'equal_description' => 'La description de la transaction ne doit pas être identique à la description globale.',
'file_invalid_mime' => 'Le fichier ":name" est du type ":mime" ce qui n\'est pas accepté pour un nouvel envoi.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Legalább egy ismétlés szükséges.',
'require_repeat_until' => 'Legalább egy ismétlésszám vagy egy végdátum (repeat_until) kötelező. Csak az egyik.',
'require_currency_info' => 'Ennek a mezőnek a tartalma érvénytelen pénznem információ nélkül.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'The content of this field is invalid without foreign amount information.',
'equal_description' => 'A tranzakció leírása nem egyezhet meg a globális leírással.',
'file_invalid_mime' => '":name" fájl ":mime" típusú ami nem lehet új feltöltés.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Minimal harus ada satu pengulangan.',
'require_repeat_until' => 'Dibutuhkan hanya sebuah angka pengulangan, atau tanggal akhir (repeat_until). Bukan keduanya.',
'require_currency_info' => 'Isi dalam bidang ini tidak valid jika tidak disertai informasi mata uang.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'The content of this field is invalid without foreign amount information.',
'equal_description' => 'Deskripsi transaksi harus berbeda dari deskripsi umum.',
'file_invalid_mime' => 'File ":name" adalah tipe ":mime" yang tidak diterima sebagai upload baru.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'È necessaria almeno una ripetizione.',
'require_repeat_until' => 'Richiede un numero di ripetizioni o una data di fine (ripeti fino al), non entrambi.',
'require_currency_info' => 'Il contenuto di questo campo non è valido senza informazioni sulla valuta.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'Il contenuto di questo campo non è valido senza le informazioni sull\'importo estero.',
'equal_description' => 'La descrizione della transazione non deve essere uguale alla descrizione globale.',
'file_invalid_mime' => 'Il file ":name" è di tipo ":mime" che non è accettato come nuovo caricamento.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Trenger minst en gjentagelse.',
'require_repeat_until' => 'Krever enten et antall repetisjoner eller en slutt dato (gjentas til). Ikke begge.',
'require_currency_info' => 'Innholdet i dette feltet er ugyldig uten valutainformasjon.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'The content of this field is invalid without foreign amount information.',
'equal_description' => 'Transaksjonsbeskrivelsen bør ikke være lik global beskrivelse.',
'file_invalid_mime' => 'Kan ikke akseptere fil ":name" av typen ":mime" for opplasting.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Er is op zijn minst één herhaling nodig.',
'require_repeat_until' => 'Je moet een aantal herhalingen opgeven, of een einddatum (repeat_until). Niet beide.',
'require_currency_info' => 'De inhoud van dit veld is ongeldig zonder valutagegevens.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'De inhoud van dit veld is ongeldig zonder bedrag in vreemde valuta.',
'equal_description' => 'Transactiebeschrijving mag niet gelijk zijn aan globale beschrijving.',
'file_invalid_mime' => 'Bestand ":name" is van het type ":mime", en die kan je niet uploaden.',

View File

@ -258,7 +258,7 @@ return [
'search_modifier_created_on' => 'Transakcja stworzona :value',
'search_modifier_updated_on' => 'Transakcja zaktualizowana :value',
'modifiers_applies_are' => 'Zastosowano także poniższe modyfikatory:',
'general_search_error' => 'An error occurred while searching. Please check the log files for more information.',
'general_search_error' => 'Wystąpił błąd podczas wyszukiwania. Aby uzyskać więcej informacji proszę sprawdzić logi aplikacji.',
'search_box' => 'Szukaj',
'search_box_intro' => 'Witamy w funkcji wyszukiwania Firefly III. Wpisz zapytanie w polu. Upewnij się, że sprawdziłeś plik pomocy, ponieważ wyszukiwanie jest dość zaawansowane.',
'search_error' => 'Błąd podczas wyszukiwania',
@ -666,7 +666,7 @@ return [
'cannot_disable_currency_budget_limits' => 'Cannot disable :name because it is used in budget limits.',
'cannot_disable_currency_current_default' => 'Cannot disable :name because it is the current default currency.',
'cannot_disable_currency_system_fallback' => 'Cannot disable :name because it is the system default currency.',
'disable_EUR_side_effects' => 'The Euro is the system\'s emergency fallback currency. Disabling it may have unintended side-effects and may void your warranty.',
'disable_EUR_side_effects' => 'Euro jest awaryjną walutą w systemie. Deaktywacja może mieć nieprzewidziane skutki i może spowodować wygaśnięcie gwarancji.',
'deleted_currency' => 'Waluta :name została usunięta',
'created_currency' => 'Waluta :name została utworzona',
'could_not_store_currency' => 'Nie można zapisać nowej waluty.',
@ -688,8 +688,8 @@ return [
'options' => 'Opcje',
// budgets:
'total_available_budget' => 'Total available budget (between :start and :end)',
'total_available_budget_in_currency' => 'Total available budget in :currency',
'total_available_budget' => 'Dostępny budżet (pomiędzy :start i :end)',
'total_available_budget_in_currency' => 'Dostępny budżet w :currency',
'see_below' => 'zobacz poniżej',
'create_new_budget' => 'Utwórz nowy budżet',
'store_new_budget' => 'Zapisz nowy budżet',
@ -791,7 +791,7 @@ return [
'asset_accounts' => 'Konta aktywów',
'asset_accounts_inactive' => 'Asset accounts (inactive)',
'expense_accounts' => 'Konta wydatków',
'expense_accounts_inactive' => 'Expense accounts (inactive)',
'expense_accounts_inactive' => 'Konto wydatków (nieaktywne)',
'revenue_accounts' => 'Konta przychodów',
'cash_accounts' => 'Konta gotówkowe',
'Cash account' => 'Konto gotówkowe',
@ -1490,7 +1490,7 @@ return [
'box_spent_in_currency' => 'Wydano (:currency)',
'box_earned_in_currency' => 'Zarobiono (:currency)',
'box_budgeted_in_currency' => 'Zabudżetowano (:currency)',
'box_sum_in_currency' => 'Sum (:currency)',
'box_sum_in_currency' => 'Suma (:currency)',
'box_bill_paid_in_currency' => 'Zapłacone rachunki (:currency)',
'box_bill_unpaid_in_currency' => 'Niezapłacone rachunki (:currency)',
'box_left_to_spend_in_currency' => 'Możliwe do wydania (:currency)',

View File

@ -255,7 +255,7 @@ return [
'withdrawal_destination_id' => 'Konto docelowe',
'deposit_source_id' => 'Konto źródłowe',
'expected_on' => 'Expected on',
'paid' => 'Paid',
'expected_on' => 'Oczekiwany',
'paid' => 'Zapłacone',
];

View File

@ -38,11 +38,11 @@ return [
'active' => 'Jest aktywny?',
'percentage' => 'pct.',
'next_due' => 'Next due',
'transaction_type' => 'Type',
'transaction_type' => 'Typ',
'lastActivity' => 'Ostatnia aktywność',
'balanceDiff' => 'Różnica sald',
'matchesOn' => 'Dopasowanie',
'other_meta_data' => 'Other meta data',
'other_meta_data' => 'Inne dane meta',
'account_type' => 'Typ konta',
'created_at' => 'Utworzono',
'account' => 'Konto',
@ -109,14 +109,14 @@ return [
'account_on_spectre' => 'Konto (Spectre)',
'account_on_ynab' => 'Konto (YNAB)',
'do_import' => 'Importuj z tego konta',
'sepa_ct_id' => 'SEPA End to End Identifier',
'sepa_ct_op' => 'SEPA Opposing Account Identifier',
'sepa_db' => 'SEPA Mandate Identifier',
'sepa_country' => 'SEPA Country',
'sepa_cc' => 'SEPA Clearing Code',
'sepa_ct_id' => 'Identyfikator end-to-end SEPA',
'sepa_ct_op' => 'Identyfikator przeciwnego konta SEPA',
'sepa_db' => 'Identyfikator mandatu SEPA',
'sepa_country' => 'Kraj SEPA',
'sepa_cc' => 'Kod rozliczeniowy SEPA',
'sepa_ep' => 'SEPA External Purpose',
'sepa_ci' => 'SEPA Creditor Identifier',
'sepa_batch_id' => 'SEPA Batch ID',
'sepa_batch_id' => 'ID paczki SEPA',
'external_id' => 'Zewnętrzne ID',
'account_at_bunq' => 'Konto bunq',
'file_name' => 'Nazwa pliku',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Wymaga co najmniej jednego powtórzenia.',
'require_repeat_until' => 'Wymagana jest liczba powtórzeń lub data zakończenia (repeat_until), ale nie obie jednocześnie.',
'require_currency_info' => 'Treść tego pola jest nieprawidłowa bez informacji o walucie.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'Treść tego pola jest nieprawidłowa bez informacji o obcej kwocie.',
'equal_description' => 'Opis transakcji nie powinien być równy globalnemu opisowi.',
'file_invalid_mime' => 'Plik ":name" jest typu ":mime", który nie jest akceptowany jako nowy plik do przekazania.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Precisa de ao menos uma repetição.',
'require_repeat_until' => 'É necessário ou um número de repetições ou uma data de término (repetir até). Não ambos.',
'require_currency_info' => 'O conteúdo deste campo é inválido sem informações de moeda.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'O conteúdo deste campo é inválido sem a informação de moeda estrangeira.',
'equal_description' => 'A descrição da transação não pode ser igual à descrição global.',
'file_invalid_mime' => 'Arquivo ":name" é do tipo ":mime" que não é aceito como um novo upload.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Aveți nevoie de cel puțin o repetare.',
'require_repeat_until' => 'Solicitați fie un număr de repetări, fie o dată de încheiere (repeat_until). Nu amândouă.',
'require_currency_info' => 'Conținutul acestui câmp este nevalid fără informații despre monedă.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'The content of this field is invalid without foreign amount information.',
'equal_description' => 'Descrierea tranzacției nu trebuie să fie egală cu descrierea globală.',
'file_invalid_mime' => 'Fișierul ":name" este de tip ":mime" și nu este acceptat ca o încărcare nouă.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'Необходима как минимум одна транзакция.',
'require_repeat_until' => 'Требуется либо несколько повторений, либо конечная дата (repeat_until). Но не оба параметра разом.',
'require_currency_info' => 'Содержимое этого поля недействительно без информации о валюте.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'Содержимое этого поля недействительно без информации о валюте.',
'equal_description' => 'Описание транзакции не должно совпадать с глобальным описанием.',
'file_invalid_mime' => 'Файл ":name" имеет тип ":mime". Загрузка файлов такого типа невозможна.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => 'En az bir tekrarı gerekir.',
'require_repeat_until' => 'Require either a number of repetitions, or an end date (repeat_until). Not both.',
'require_currency_info' => 'Bu alanın içeriği para birimi bilgileri geçersiz.',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'The content of this field is invalid without foreign amount information.',
'equal_description' => 'İşlem açıklaması genel açıklama eşit değildir.',
'file_invalid_mime' => '":name" dosyası ":mime" türünde olup yeni bir yükleme olarak kabul edilemez.',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => '至少需要一次重复。',
'require_repeat_until' => '仅需重复次数或结束日期 (repeat_until) 即可,不需两者均备。',
'require_currency_info' => '无货币资讯,此栏位内容无效。',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => 'The content of this field is invalid without foreign amount information.',
'equal_description' => '交易描述不应等同全域描述。',
'file_invalid_mime' => '档案 ":name" 的类型为 ":mime",系不被允许上载的类型。',

View File

@ -45,6 +45,7 @@ return [
'at_least_one_repetition' => '至少需要一次重複。',
'require_repeat_until' => '要嘛重複次數,要嘛結束日期 (repeat_until),須二擇其一。',
'require_currency_info' => '此欄位內容須要貨幣資訊。',
'not_transfer_account' => 'This account is not an account that can be used for transfers.',
'require_currency_amount' => '此欄位內容須要外幣資訊。',
'equal_description' => '交易描述不應等同全域描述。',
'file_invalid_mime' => '檔案 ":name" 類型為 ":mime",不允許上載。',

View File

@ -342,6 +342,7 @@ Route::group(
// Attachment API routes:
Route::get('transactions', ['uses' => 'TransactionController@search', 'as' => 'transactions']);
Route::get('accounts', ['uses' => 'AccountController@search', 'as' => 'accounts']);
Route::get('transfers', ['uses' => 'TransferController@search', 'as' => 'transfers']);
}
);