Code for 4.1.6

This commit is contained in:
James Cole
2016-11-06 16:17:22 +01:00
parent 124ecb1372
commit 69422cc796
233 changed files with 2307 additions and 1889 deletions

View File

@@ -2,6 +2,20 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/). This project adheres to [Semantic Versioning](http://semver.org/).
## [4.1.6] - 2016-11-06
### Added
- New budget table for multi year report.
### Changed
- Greatly expanded help pages and their function.
- Built a new transaction collector, which I think was the idea of @roberthorlings originally.
- Rebuilt seach engine.
### Fixed
- #375, thanks to @schoentoon which made it impossible to resurrect currencies.
- #370 thanks to @ksmolder
- #378, thanks to @HomelessAvatar
## [4.1.5] - 2016-11-01 ## [4.1.5] - 2016-11-01
### Changed ### Changed
- Report parts are loaded using AJAX, making a lot of code more simple. - Report parts are loaded using AJAX, making a lot of code more simple.

View File

@@ -66,7 +66,7 @@ class Import extends Command
return; return;
} }
$this->line('Going to import job with key "' . $job->key . '" of type ' . $job->file_type); $this->line(sprintf('Going to import job with key "%s" of type "%s"', $job->key, $job->file_type));
$monolog = Log::getMonolog(); $monolog = Log::getMonolog();
$handler = new CommandHandler($this); $handler = new CommandHandler($this);

View File

@@ -0,0 +1,86 @@
<?php
/**
* MoveRepository.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Console\Commands;
use Carbon\Carbon;
use Illuminate\Console\Command;
/**
* Class MoveRepository
*
* @package FireflyIII\Console\Commands
*/
class MoveRepository extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Alerts the user that the Github repository will move, if they are interested to know this.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly:github-move';
/**
* Create a new command instance.
*
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*/
public function handle()
{
$moveDate = new Carbon('2017-01-01');
$final = new Carbon('2017-03-01');
$now = new Carbon;
// display message before 2017-01-01
if ($moveDate > $now) {
$this->line('+------------------------------------------------------------------------------+');
$this->line('');
$this->line('The Github repository for Firefly III will MOVE');
$this->line('This move will be on January 1st 2017');
$this->line('');
$this->error('READ THIS WIKI PAGE FOR MORE INFORMATION');
$this->line('');
$this->info('https://github.com/firefly-iii/help/wiki/New-Github-repository');
$this->line('');
$this->line('+------------------------------------------------------------------------------+');
}
// display message after 2017-01-01 but before 2017-03-01
if ($moveDate <= $now && $now <= $final) {
$this->line('+------------------------------------------------------------------------------+');
$this->line('');
$this->line('The Github repository for Firefly III has MOVED');
$this->line('This move was on January 1st 2017!');
$this->line('');
$this->error('READ THIS WIKI PAGE FOR MORE INFORMATION');
$this->line('');
$this->info('https://github.com/firefly-iii/help/wiki/New-Github-repository');
$this->line('');
$this->line('+------------------------------------------------------------------------------+');
}
}
}

View File

@@ -99,7 +99,7 @@ class UpgradeDatabase extends Command
} catch (QueryException $e) { } catch (QueryException $e) {
Log::error($e->getMessage()); Log::error($e->getMessage());
$this->error('Firefly III could not find the "identifier" field in the "transactions" table.'); $this->error('Firefly III could not find the "identifier" field in the "transactions" table.');
$this->error('This field is required for Firefly III version ' . config('firefly.version') . ' to run.'); $this->error(sprintf('This field is required for Firefly III version %s to run.', config('firefly.version')));
$this->error('Please run "php artisan migrate" to add this field to the table.'); $this->error('Please run "php artisan migrate" to add this field to the table.');
$this->info('Then, run "php artisan firefly:upgrade-database" to try again.'); $this->info('Then, run "php artisan firefly:upgrade-database" to try again.');
break 2; break 2;

View File

@@ -63,21 +63,20 @@ class UpgradeFireflyInstructions extends Command
} }
$this->line('+------------------------------------------------------------------------------+');
$this->line('');
if (is_null($text)) { if (is_null($text)) {
$this->line('Thank you for installing Firefly III, v' . $version); $this->line(sprintf('Thank you for installing Firefly III, v%s', $version));
$this->info('There are no extra upgrade instructions.'); $this->info('There are no extra upgrade instructions.');
$this->line('Firefly III should be ready for use.'); $this->line('Firefly III should be ready for use.');
} else { } else {
$this->line('Thank you for installing Firefly III, v' . $version); $this->line('+------------------------------------------------------------------------------+');
$this->line('If you are upgrading from a previous version,'); $this->line('');
$this->line('please follow these upgrade instructions carefully:'); $this->line(sprintf('Thank you for installing Firefly III, v%s', $version));
$this->info(wordwrap($text)); $this->info(wordwrap($text));
$this->line('');
$this->line('+------------------------------------------------------------------------------+');
} }
$this->line('');
$this->line('+------------------------------------------------------------------------------+');
} }
} }

View File

@@ -127,8 +127,11 @@ class VerifyDatabase extends Command
/** @var stdClass $entry */ /** @var stdClass $entry */
foreach ($set as $entry) { foreach ($set as $entry) {
$line = 'Notice: User #' . $entry->user_id . ' (' . $entry->email . ') has budget #' . $entry->id . ' ("' . Crypt::decrypt($entry->name)
. '") which has no budget limits.'; $line = sprintf(
'Notice: User #%d (%s) has budget #%d ("%s") which has no budget limits.',
$entry->user_id, $entry->email, $entry->id, Crypt::decrypt($entry->name)
);
$this->line($line); $this->line($line);
} }
} }

View File

@@ -16,6 +16,7 @@ namespace FireflyIII\Console;
use FireflyIII\Console\Commands\CreateImport; use FireflyIII\Console\Commands\CreateImport;
use FireflyIII\Console\Commands\EncryptFile; use FireflyIII\Console\Commands\EncryptFile;
use FireflyIII\Console\Commands\Import; use FireflyIII\Console\Commands\Import;
use FireflyIII\Console\Commands\MoveRepository;
use FireflyIII\Console\Commands\ScanAttachments; use FireflyIII\Console\Commands\ScanAttachments;
use FireflyIII\Console\Commands\UpgradeDatabase; use FireflyIII\Console\Commands\UpgradeDatabase;
use FireflyIII\Console\Commands\UpgradeFireflyInstructions; use FireflyIII\Console\Commands\UpgradeFireflyInstructions;
@@ -63,7 +64,7 @@ class Kernel extends ConsoleKernel
EncryptFile::class, EncryptFile::class,
ScanAttachments::class, ScanAttachments::class,
UpgradeDatabase::class, UpgradeDatabase::class,
MoveRepository::class,
]; ];
/** /**

View File

@@ -1,6 +1,6 @@
<?php <?php
/** /**
* JournalCollector.php * JournalExportCollector.php
* Copyright (C) 2016 thegrumpydictator@gmail.com * Copyright (C) 2016 thegrumpydictator@gmail.com
* *
* This software may be modified and distributed under the terms of the * This software may be modified and distributed under the terms of the
@@ -21,11 +21,11 @@ use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
/** /**
* Class JournalCollector * Class JournalExportCollector
* *
* @package FireflyIII\Export\Collector * @package FireflyIII\Export\Collector
*/ */
class JournalCollector extends BasicCollector implements CollectorInterface class JournalExportCollector extends BasicCollector implements CollectorInterface
{ {
/** @var Collection */ /** @var Collection */
private $accounts; private $accounts;

View File

@@ -14,7 +14,6 @@ declare(strict_types = 1);
namespace FireflyIII\Export\Exporter; namespace FireflyIII\Export\Exporter;
use FireflyIII\Export\Entry\Entry; use FireflyIII\Export\Entry\Entry;
use FireflyIII\Export\Entry\EntryAccount;
use FireflyIII\Models\ExportJob; use FireflyIII\Models\ExportJob;
use League\Csv\Writer; use League\Csv\Writer;
use SplFileObject; use SplFileObject;

View File

@@ -15,7 +15,7 @@ namespace FireflyIII\Export;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Export\Collector\AttachmentCollector; use FireflyIII\Export\Collector\AttachmentCollector;
use FireflyIII\Export\Collector\JournalCollector; use FireflyIII\Export\Collector\JournalExportCollector;
use FireflyIII\Export\Collector\UploadCollector; use FireflyIII\Export\Collector\UploadCollector;
use FireflyIII\Export\Entry\Entry; use FireflyIII\Export\Entry\Entry;
use FireflyIII\Models\ExportJob; use FireflyIII\Models\ExportJob;
@@ -45,8 +45,6 @@ class Processor
public $job; public $job;
/** @var array */ /** @var array */
public $settings; public $settings;
/** @var \FireflyIII\Export\ConfigurationFile */
private $configurationMaker;
/** @var Collection */ /** @var Collection */
private $exportEntries; private $exportEntries;
/** @var Collection */ /** @var Collection */
@@ -93,8 +91,8 @@ class Processor
*/ */
public function collectJournals(): bool public function collectJournals(): bool
{ {
/** @var JournalCollector $collector */ /** @var JournalExportCollector $collector */
$collector = app(JournalCollector::class, [$this->job]); $collector = app(JournalExportCollector::class, [$this->job]);
$collector->setDates($this->settings['startDate'], $this->settings['endDate']); $collector->setDates($this->settings['startDate'], $this->settings['endDate']);
$collector->setAccounts($this->settings['accounts']); $collector->setAccounts($this->settings['accounts']);
$collector->run(); $collector->run();

View File

@@ -14,7 +14,7 @@ declare(strict_types = 1);
namespace FireflyIII\Generator\Chart\Bill; namespace FireflyIII\Generator\Chart\Bill;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\Transaction;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
/** /**
@@ -61,13 +61,13 @@ class ChartJsBillChartGenerator implements BillChartGeneratorInterface
$minAmount = []; $minAmount = [];
$maxAmount = []; $maxAmount = [];
$actualAmount = []; $actualAmount = [];
/** @var TransactionJournal $entry */ /** @var Transaction $entry */
foreach ($entries as $entry) { foreach ($entries as $entry) {
$data['labels'][] = $entry->date->formatLocalized($format); $data['labels'][] = $entry->date->formatLocalized($format);
$minAmount[] = round($bill->amount_min, 2); $minAmount[] = round($bill->amount_min, 2);
$maxAmount[] = round($bill->amount_max, 2); $maxAmount[] = round($bill->amount_max, 2);
// journalAmount has been collected in BillRepository::getJournals // journalAmount has been collected in BillRepository::getJournals
$actualAmount[] = round(TransactionJournal::amountPositive($entry), 2); $actualAmount[] = bcmul($entry->transaction_amount, '-1');
} }
$data['datasets'][] = [ $data['datasets'][] = [

View File

@@ -21,6 +21,7 @@ use FireflyIII\Models\RuleGroup;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Rules\Processor; use FireflyIII\Rules\Processor;
use FireflyIII\Support\Events\BillScanner; use FireflyIII\Support\Events\BillScanner;
use Log;
/** /**
* Class StoredJournalEventHandler * Class StoredJournalEventHandler
@@ -42,30 +43,69 @@ class StoredJournalEventHandler
$journal = $event->journal; $journal = $event->journal;
$piggyBankId = $event->piggyBankId; $piggyBankId = $event->piggyBankId;
Log::debug(sprintf('Trying to connect journal %d to piggy bank %d.', $journal->id, $piggyBankId));
/** @var PiggyBank $piggyBank */ /** @var PiggyBank $piggyBank */
$piggyBank = $journal->user->piggyBanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']); $piggyBank = $journal->user->piggyBanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
if (is_null($piggyBank)) { if (is_null($piggyBank)) {
Log::error('No such piggy bank!');
return true; return true;
} }
Log::debug(sprintf('Found piggy bank #%d: "%s"', $piggyBank->id, $piggyBank->name));
// update piggy bank rep for date of transaction journal. // update piggy bank rep for date of transaction journal.
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first(); $repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
if (is_null($repetition)) { if (is_null($repetition)) {
Log::error(sprintf('No piggy bank repetition on %s!', $journal->date->format('Y-m-d')));
return true; return true;
} }
$amount = TransactionJournal::amountPositive($journal); $amount = TransactionJournal::amountPositive($journal);
Log::debug(sprintf('Will add/remove %f to piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
// if piggy account matches source account, the amount is positive // if piggy account matches source account, the amount is positive
$sources = TransactionJournal::sourceAccountList($journal)->pluck('id')->toArray(); $sources = TransactionJournal::sourceAccountList($journal)->pluck('id')->toArray();
if (in_array($piggyBank->account_id, $sources)) { if (in_array($piggyBank->account_id, $sources)) {
$amount = bcmul($amount, '-1'); $amount = bcmul($amount, '-1');
Log::debug(sprintf('Account #%d is the source, so will remove amount from piggy bank.', $piggyBank->account_id));
}
// if the amount is positive:
// make sure it fits in piggy bank:
if (bccomp($amount, '0') === 1) {
// amount is positive
$room = bcsub(strval($piggyBank->targetamount), strval($repetition->currentamount));
Log::debug(sprintf('Room in piggy bank for extra money is %f', $room));
if (bccomp($room, $amount) === -1) {
// $room is smaller than $amount
Log::debug(sprintf('There is NO room to add %f to piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
Log::debug(sprintf('New amount is %f', $room));
$amount = $room;
}
}
if (bccomp($amount, '0') === -1) {
// amount is negative
Log::debug(sprintf('Max amount to remove is %f', $repetition->currentamount));
$compare = bcmul($repetition->currentamount, '-1');
if (bccomp($compare, $amount) === 1) {
// $currentamount is smaller than $amount
Log::debug(sprintf('Cannot remove %f from piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
Log::debug(sprintf('New amount is %f', $compare));
$amount = $compare;
}
} }
$repetition->currentamount = bcadd($repetition->currentamount, $amount); $repetition->currentamount = bcadd($repetition->currentamount, $amount);
$repetition->save(); $repetition->save();
PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]); /** @var PiggyBankEvent $event */
$event = PiggyBankEvent::create(
['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]
);
Log::debug(sprintf('Created piggy bank event #%d', $event->id));
return true; return true;
} }

View File

@@ -15,11 +15,8 @@ namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\UpdatedTransactionJournal; use FireflyIII\Events\UpdatedTransactionJournal;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\Rule; use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleGroup; use FireflyIII\Models\RuleGroup;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Rules\Processor; use FireflyIII\Rules\Processor;
use FireflyIII\Support\Events\BillScanner; use FireflyIII\Support\Events\BillScanner;
@@ -30,50 +27,6 @@ use FireflyIII\Support\Events\BillScanner;
*/ */
class UpdatedJournalEventHandler class UpdatedJournalEventHandler
{ {
/**
* This method will try to reconnect a journal to a piggy bank, updating the piggy bank repetition.
*
* @param UpdatedTransactionJournal $event
*
* @return bool
*/
public function connectToPiggyBank(UpdatedTransactionJournal $event): bool
{
$journal = $event->journal;
if (!$journal->isTransfer()) {
return true;
}
// get the event connected to this journal:
/** @var PiggyBankEvent $event */
$event = PiggyBankEvent::where('transaction_journal_id', $journal->id)->first();
if (is_null($event)) {
return false;
}
$piggyBank = $event->piggyBank()->first();
$repetition = null;
if (!is_null($piggyBank)) {
/** @var PiggyBankRepetition $repetition */
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
}
if (is_null($repetition)) {
return false;
}
$amount = TransactionJournal::amount($journal);
$diff = bcsub($amount, $event->amount); // update current repetition
$repetition->currentamount = bcadd($repetition->currentamount, $diff);
$repetition->save();
$event->amount = $amount;
$event->save();
return true;
}
/** /**
* This method will check all the rules when a journal is updated. * This method will check all the rules when a journal is updated.

View File

@@ -17,10 +17,8 @@ use FireflyIII\Models\Attachment;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\MessageBag; use Illuminate\Support\MessageBag;
use Input; use Input;
use Log;
use Storage; use Storage;
use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\File\UploadedFile;
use TypeError;
/** /**
* Class AttachmentHelper * Class AttachmentHelper
@@ -236,13 +234,8 @@ class AttachmentHelper implements AttachmentHelperInterface
private function getFiles() private function getFiles()
{ {
$files = null; $files = null;
try { if (Input::hasFile('attachments')) {
if (Input::hasFile('attachments')) { $files = Input::file('attachments');
$files = Input::file('attachments');
}
} catch (TypeError $e) {
// Log it, do nothing else.
Log::error($e->getMessage());
} }
return $files; return $files;

View File

@@ -0,0 +1,485 @@
<?php
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collector;
use Carbon\Carbon;
use Crypt;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\Tag;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Log;
/**
* Maybe this is a good idea after all...
*
* Class JournalCollector
*
* @package FireflyIII\Helpers\Collector
*/
class JournalCollector
{
/** @var int */
private $count = 0;
/** @var array */
private $fields
= [
'transaction_journals.id as journal_id',
'transaction_journals.description',
'transaction_journals.date',
'transaction_journals.encrypted',
//'transaction_journals.transaction_currency_id',
'transaction_currencies.code as transaction_currency_code',
//'transaction_currencies.symbol as transaction_currency_symbol',
'transaction_types.type as transaction_type_type',
'transaction_journals.bill_id',
'bills.name as bill_name',
'transactions.id as id',
'transactions.amount as transaction_amount',
'transactions.description as transaction_description',
'transactions.account_id',
'transactions.identifier',
'transactions.transaction_journal_id',
'accounts.name as account_name',
'accounts.encrypted as account_encrypted',
'account_types.type as account_type',
];
/** @var bool */
private $filterTransfers = false;
/** @var bool */
private $joinedBudget = false;
/** @var bool */
private $joinedCategory = false;
/** @var bool */
private $joinedTag = false;
/** @var int */
private $limit;
/** @var int */
private $offset;
/** @var int */
private $page = 1;
/** @var EloquentBuilder */
private $query;
/** @var bool */
private $run = false;
/** @var User */
private $user;
/**
* JournalCollector constructor.
*
* @param User $user
*/
public function __construct(User $user)
{
$this->user = $user;
$this->query = $this->startQuery();
}
/**
* @return int
* @throws FireflyException
*/
public function count(): int
{
if ($this->run === true) {
throw new FireflyException('Cannot count after run in JournalCollector.');
}
$countQuery = clone $this->query;
// dont need some fields:
$countQuery->getQuery()->limit = null;
$countQuery->getQuery()->offset = null;
$countQuery->getQuery()->unionLimit = null;
$countQuery->getQuery()->groups = null;
$countQuery->getQuery()->orders = null;
$countQuery->groupBy('accounts.user_id');
$this->count = $countQuery->count();
return $this->count;
}
/**
* @return Collection
*/
public function getJournals(): Collection
{
$this->run = true;
$set = $this->query->get(array_values($this->fields));
$set = $this->filterTransfers($set);
// loop for decryption.
$set->each(
function (Transaction $transaction) {
$transaction->date = new Carbon($transaction->date);
$transaction->description = intval($transaction->encrypted) === 1 ? Crypt::decrypt($transaction->description) : $transaction->description;
$transaction->bill_name = !is_null($transaction->bill_name) ? Crypt::decrypt($transaction->bill_name) : '';
}
);
return $set;
}
/**
* @return LengthAwarePaginator
* @throws FireflyException
*/
public function getPaginatedJournals():LengthAwarePaginator
{
if ($this->run === true) {
throw new FireflyException('Cannot getPaginatedJournals after run in JournalCollector.');
}
$this->count();
$set = $this->getJournals();
$journals = new LengthAwarePaginator($set, $this->count, $this->limit, $this->page);
return $journals;
}
/**
* @param Collection $accounts
*
* @return JournalCollector
*/
public function setAccounts(Collection $accounts): JournalCollector
{
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
$this->query->whereIn('transactions.account_id', $accountIds);
}
if ($accounts->count() > 1) {
$this->filterTransfers = true;
}
return $this;
}
/**
* @return JournalCollector
*/
public function setAllAssetAccounts(): JournalCollector
{
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class, [$this->user]);
$accounts = $repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT]);
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
$this->query->whereIn('transactions.account_id', $accountIds);
}
if ($accounts->count() > 1) {
$this->filterTransfers = true;
}
return $this;
}
/**
* @param Collection $bills
*
* @return JournalCollector
*/
public function setBills(Collection $bills): JournalCollector
{
if ($bills->count() > 0) {
$billIds = $bills->pluck('id')->toArray();
$this->query->whereIn('transaction_journals.bill_id', $billIds);
}
return $this;
}
/**
* @param Budget $budget
*
* @return JournalCollector
*/
public function setBudget(Budget $budget): JournalCollector
{
$this->joinBudgetTables();
$this->query->where(
function (EloquentBuilder $q) use ($budget) {
$q->where('budget_transaction.budget_id', $budget->id);
$q->orWhere('budget_transaction_journal.budget_id', $budget->id);
}
);
return $this;
}
/**
* @param Category $category
*
* @return JournalCollector
*/
public function setCategory(Category $category): JournalCollector
{
$this->joinCategoryTables();
$this->query->where(
function (EloquentBuilder $q) use ($category) {
$q->where('category_transaction.category_id', $category->id);
$q->orWhere('category_transaction_journal.category_id', $category->id);
}
);
return $this;
}
/**
* @param int $limit
*
* @return JournalCollector
*/
public function setLimit(int $limit): JournalCollector
{
$this->limit = $limit;
$this->query->limit($limit);
Log::debug(sprintf('Set limit to %d', $limit));
return $this;
}
/**
* @param int $offset
*
* @return JournalCollector
*/
public function setOffset(int $offset): JournalCollector
{
$this->offset = $offset;
return $this;
}
/**
* @param int $page
*
* @return JournalCollector
*/
public function setPage(int $page): JournalCollector
{
$this->page = $page;
if ($page > 0) {
$page--;
}
Log::debug(sprintf('Page is %d', $page));
if (!is_null($this->limit)) {
$offset = ($this->limit * $page);
$this->offset = $offset;
$this->query->skip($offset);
Log::debug(sprintf('Changed offset to %d', $offset));
}
if (is_null($this->limit)) {
Log::debug('The limit is zero, cannot set the page.');
}
return $this;
}
/**
* @param Carbon $start
* @param Carbon $end
*
* @return JournalCollector
*/
public function setRange(Carbon $start, Carbon $end): JournalCollector
{
if ($start <= $end) {
$this->query->where('transaction_journals.date', '>=', $start->format('Y-m-d'));
$this->query->where('transaction_journals.date', '<=', $end->format('Y-m-d'));
}
return $this;
}
/**
* @param Tag $tag
*
* @return JournalCollector
*/
public function setTag(Tag $tag): JournalCollector
{
$this->joinTagTables();
$this->query->where('tag_transaction_journal.tag_id', $tag->id);
return $this;
}
/**
* @param array $types
*
* @return JournalCollector
*/
public function setTypes(array $types): JournalCollector
{
if (count($types) > 0) {
$this->query->whereIn('transaction_types.type', $types);
}
return $this;
}
/**
* @return JournalCollector
*/
public function withoutBudget(): JournalCollector
{
$this->joinBudgetTables();
$this->query->where(
function (EloquentBuilder $q) {
$q->whereNull('budget_transaction.budget_id');
$q->whereNull('budget_transaction_journal.budget_id');
}
);
return $this;
}
/**
* @return JournalCollector
*/
public function withoutCategory(): JournalCollector
{
$this->joinCategoryTables();
$this->query->where(
function (EloquentBuilder $q) {
$q->whereNull('category_transaction.category_id');
$q->whereNull('category_transaction_journal.category_id');
}
);
return $this;
}
/**
* If the set of accounts used by the collector includes more than one asset
* account, chances are the set include double entries: transfers get selected
* on both the source, and then again on the destination account.
*
* This method filters them out.
*
* @param Collection $set
*
* @return Collection
*/
private function filterTransfers(Collection $set): Collection
{
if ($this->filterTransfers) {
$set = $set->filter(
function (Transaction $transaction) {
if (!($transaction->transaction_type_type === TransactionType::TRANSFER && bccomp($transaction->transaction_amount, '0') === -1)) {
Log::debug(
sprintf(
'Included journal #%d (transaction #%d) because its a %s with amount %f',
$transaction->transaction_journal_id,
$transaction->id,
$transaction->transaction_type_type,
$transaction->transaction_amount
)
);
return $transaction;
}
Log::debug(
sprintf(
'Removed journal #%d (transaction #%d) because its a %s with amount %f',
$transaction->transaction_journal_id,
$transaction->id,
$transaction->transaction_type_type,
$transaction->transaction_amount
)
);
return false;
}
);
}
return $set;
}
/**
*
*/
private function joinBudgetTables()
{
if (!$this->joinedBudget) {
// join some extra tables:
$this->joinedBudget = true;
$this->query->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
$this->query->leftJoin('budget_transaction', 'budget_transaction.transaction_id', '=', 'transactions.id');
}
}
/**
*
*/
private function joinCategoryTables()
{
if (!$this->joinedCategory) {
// join some extra tables:
$this->joinedCategory = true;
$this->query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
$this->query->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id');
}
}
/**
*
*/
private function joinTagTables()
{
if (!$this->joinedTag) {
// join some extra tables:
$this->joinedTag = true;
$this->query->leftJoin('tag_transaction_journal', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
}
}
/**
* @return EloquentBuilder
*/
private function startQuery(): EloquentBuilder
{
$query = Transaction
::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('transaction_currencies', 'transaction_currencies.id', 'transaction_journals.transaction_currency_id')
->leftJoin('transaction_types', 'transaction_types.id', 'transaction_journals.transaction_type_id')
->leftJoin('bills', 'bills.id', 'transaction_journals.bill_id')
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->leftJoin('account_types', 'accounts.account_type_id', 'account_types.id')
->whereNull('transactions.deleted_at')
->whereNull('transaction_journals.deleted_at')
->where('transaction_journals.user_id', $this->user->id)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC');
return $query;
}
}

View File

@@ -26,6 +26,8 @@ use Route;
*/ */
class Help implements HelpInterface class Help implements HelpInterface
{ {
/** @var string */
protected $userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36';
/** /**
* @param string $route * @param string $route
@@ -35,7 +37,9 @@ class Help implements HelpInterface
*/ */
public function getFromCache(string $route, string $language): string public function getFromCache(string $route, string $language): string
{ {
return Cache::get('help.' . $route . '.' . $language); $line = sprintf('help.%s.%s', $route, $language);
return Cache::get($line);
} }
/** /**
@@ -49,9 +53,10 @@ class Help implements HelpInterface
$uri = sprintf('https://raw.githubusercontent.com/firefly-iii/help/master/%s/%s.md', $language, $route); $uri = sprintf('https://raw.githubusercontent.com/firefly-iii/help/master/%s/%s.md', $language, $route);
Log::debug(sprintf('Trying to get %s...', $uri)); Log::debug(sprintf('Trying to get %s...', $uri));
$opt = ['useragent' => $this->userAgent];
$content = ''; $content = '';
try { try {
$result = Requests::get($uri); $result = Requests::get($uri, [], $opt);
} catch (Requests_Exception $e) { } catch (Requests_Exception $e) {
Log::error($e); Log::error($e);
@@ -69,6 +74,9 @@ class Help implements HelpInterface
$converter = new CommonMarkConverter(); $converter = new CommonMarkConverter();
$content = $converter->convertToHtml($content); $content = $converter->convertToHtml($content);
} }
if (strlen($content) === 0) {
Log::warning('Raw content length is zero.');
}
return $content; return $content;
@@ -93,7 +101,8 @@ class Help implements HelpInterface
*/ */
public function inCache(string $route, string $language):bool public function inCache(string $route, string $language):bool
{ {
$result = Cache::has('help.' . $route . '.' . $language); $line = sprintf('help.%s.%s', $route, $language);
$result = Cache::has($line);
if ($result) { if ($result) {
Log::debug(sprintf('Cache has this entry: %s', 'help.' . $route . '.' . $language)); Log::debug(sprintf('Cache has this entry: %s', 'help.' . $route . '.' . $language));
} }
@@ -115,8 +124,12 @@ class Help implements HelpInterface
*/ */
public function putInCache(string $route, string $language, string $content) public function putInCache(string $route, string $language, string $content)
{ {
$key = 'help.' . $route . '.' . $language; $key = sprintf('help.%s.%s', $route, $language);
Log::debug(sprintf('Will store entry in cache: %s', $key)); if (strlen($content) > 0) {
Cache::put($key, $content, 10080); // a week. Log::debug(sprintf('Will store entry in cache: %s', $key));
Cache::put($key, $content, 10080); // a week.
return;
}
Log::info(sprintf('Will not cache %s because content is empty.', $key));
} }
} }

View File

@@ -49,7 +49,7 @@ interface HelpInterface
* *
* @return bool * @return bool
*/ */
public function inCache(string $route, string $language ): bool; public function inCache(string $route, string $language): bool;
/** /**
* @param string $route * @param string $route

View File

@@ -15,13 +15,17 @@ namespace FireflyIII\Helpers\Report;
use Carbon\Carbon; use Carbon\Carbon;
use DB;
use FireflyIII\Helpers\Collection\Budget as BudgetCollection; use FireflyIII\Helpers\Collection\Budget as BudgetCollection;
use FireflyIII\Helpers\Collection\BudgetLine; use FireflyIII\Helpers\Collection\BudgetLine;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use stdClass;
/** /**
* Class BudgetReportHelper * Class BudgetReportHelper
@@ -97,6 +101,66 @@ class BudgetReportHelper implements BudgetReportHelperInterface
return $return; return $return;
} }
/**
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts
*
* @return array
*/
public function getBudgetMultiYear(Carbon $start, Carbon $end, Collection $accounts): array
{
$accountIds = $accounts->pluck('id')->toArray();
$query = TransactionJournal
::leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
}
)
->whereNull('transaction_journals.deleted_at')
->whereNull('transactions.deleted_at')
->where('transaction_types.type', 'Withdrawal')
->where('transaction_journals.user_id', auth()->user()->id);
if (count($accountIds) > 0) {
$query->whereIn('transactions.account_id', $accountIds);
}
$query->groupBy(['budget_transaction_journal.budget_id', 'the_year']);
$queryResult = $query->get(
[
'budget_transaction_journal.budget_id',
DB::raw('DATE_FORMAT(transaction_journals.date,"%Y") AS the_year'),
DB::raw('SUM(transactions.amount) as sum_of_period'),
]
);
$data = [];
$budgets = $this->repository->getBudgets();
$years = $this->listOfYears($start, $end);
// do budget "zero"
$emptyBudget = new Budget;
$emptyBudget->id = 0;
$emptyBudget->name = strval(trans('firefly.no_budget'));
$budgets->push($emptyBudget);
// get all budgets and years.
foreach ($budgets as $budget) {
$data[$budget->id] = [
'name' => $budget->name,
'entries' => $this->filterAmounts($queryResult, $budget->id, $years),
'sum' => '0',
];
}
// filter out empty ones and fill sum:
$data = $this->getBudgetMultiYearMeta($data);
return $data;
}
/** /**
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
@@ -183,30 +247,21 @@ class BudgetReportHelper implements BudgetReportHelperInterface
} }
/** /**
* Take the array as returned by CategoryRepositoryInterface::spentPerDay and CategoryRepositoryInterface::earnedByDay
* and sum up everything in the array in the given range.
*
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
* @param array $array
* *
* @return string * @return array
*/ */
protected function getSumOfRange(Carbon $start, Carbon $end, array $array) public function listOfYears(Carbon $start, Carbon $end): array
{ {
$sum = '0'; $begin = clone $start;
$currentStart = clone $start; // to not mess with the original one $years = [];
$currentEnd = clone $end; // to not mess with the original one while ($begin < $end) {
$years[] = $begin->year;
while ($currentStart <= $currentEnd) { $begin->addYear();
$date = $currentStart->format('Y-m-d');
if (isset($array[$date])) {
$sum = bcadd($sum, $array[$date]);
}
$currentStart->addDay();
} }
return $sum; return $years;
} }
/** /**
@@ -247,6 +302,59 @@ class BudgetReportHelper implements BudgetReportHelperInterface
return $headers; return $headers;
} }
/**
* @param Collection $set
* @param int $budgetId
* @param array $years
*
* @return array
*/
private function filterAmounts(Collection $set, int $budgetId, array $years):array
{
$arr = [];
foreach ($years as $year) {
/** @var stdClass $object */
$result = $set->filter(
function (TransactionJournal $object) use ($budgetId, $year) {
return intval($object->the_year) === $year && $budgetId === intval($object->budget_id);
}
);
$amount = '0';
if (!is_null($result->first())) {
$amount = $result->first()->sum_of_period;
}
$arr[$year] = $amount;
}
return $arr;
}
/**
* @param array $data
*
* @return array
*/
private function getBudgetMultiYearMeta(array $data): array
{
/**
* @var int $budgetId
* @var array $set
*/
foreach ($data as $budgetId => $set) {
$sum = '0';
foreach ($set['entries'] as $amount) {
$sum = bcadd($amount, $sum);
}
$data[$budgetId]['sum'] = $sum;
if (bccomp('0', $sum) === 0) {
unset($data[$budgetId]);
}
}
return $data;
}
/** /**
* @param Carbon $current * @param Carbon $current
* @param Carbon $end * @param Carbon $end

View File

@@ -34,6 +34,15 @@ interface BudgetReportHelperInterface
*/ */
public function budgetYearOverview(Carbon $start, Carbon $end, Collection $accounts): Collection; public function budgetYearOverview(Carbon $start, Carbon $end, Collection $accounts): Collection;
/**
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts
*
* @return array
*/
public function getBudgetMultiYear(Carbon $start, Carbon $end, Collection $accounts): array;
/** /**
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
@@ -52,4 +61,12 @@ interface BudgetReportHelperInterface
*/ */
public function getBudgetsWithExpenses(Carbon $start, Carbon $end, Collection $accounts): Collection; public function getBudgetsWithExpenses(Carbon $start, Carbon $end, Collection $accounts): Collection;
/**
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function listOfYears(Carbon $start, Carbon $end): array;
} }

View File

@@ -14,18 +14,17 @@ declare(strict_types = 1);
namespace FireflyIII\Helpers\Report; namespace FireflyIII\Helpers\Report;
use Carbon\Carbon; use Carbon\Carbon;
use DB;
use FireflyIII\Helpers\Collection\Bill as BillCollection; use FireflyIII\Helpers\Collection\Bill as BillCollection;
use FireflyIII\Helpers\Collection\BillLine; use FireflyIII\Helpers\Collection\BillLine;
use FireflyIII\Helpers\Collection\Category as CategoryCollection; use FireflyIII\Helpers\Collection\Category as CategoryCollection;
use FireflyIII\Helpers\Collection\Expense; use FireflyIII\Helpers\Collection\Expense;
use FireflyIII\Helpers\Collection\Income; use FireflyIII\Helpers\Collection\Income;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Helpers\FiscalHelperInterface; use FireflyIII\Helpers\FiscalHelperInterface;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Models\Tag; use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\Transaction;
use FireflyIII\Repositories\Account\AccountTaskerInterface; use FireflyIII\Repositories\Account\AccountTaskerInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
@@ -79,7 +78,9 @@ class ReportHelper implements ReportHelperInterface
/** @var BillRepositoryInterface $repository */ /** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class); $repository = app(BillRepositoryInterface::class);
$bills = $repository->getBillsForAccounts($accounts); $bills = $repository->getBillsForAccounts($accounts);
$journals = $repository->getAllJournalsInRange($bills, $start, $end); $collector = new JournalCollector(auth()->user());
$collector->setAccounts($accounts)->setRange($start, $end)->setBills($bills);
$journals = $collector->getJournals();
$collection = new BillCollection; $collection = new BillCollection;
/** @var Bill $bill */ /** @var Bill $bill */
@@ -93,14 +94,14 @@ class ReportHelper implements ReportHelperInterface
// is hit in period? // is hit in period?
$entry = $journals->filter( $entry = $journals->filter(
function (TransactionJournal $journal) use ($bill) { function (Transaction $transaction) use ($bill) {
return $journal->bill_id === $bill->id; return $transaction->bill_id === $bill->id;
} }
); );
$first = $entry->first(); $first = $entry->first();
if (!is_null($first)) { if (!is_null($first)) {
$billLine->setTransactionJournalId($first->id); $billLine->setTransactionJournalId($first->id);
$billLine->setAmount($first->journalAmount); $billLine->setAmount($first->transaction_amount);
$billLine->setHit(true); $billLine->setHit(true);
} }
@@ -113,67 +114,6 @@ class ReportHelper implements ReportHelperInterface
return $collection; return $collection;
} }
/**
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts
*
* @return array
*/
public function getBudgetMultiYear(Carbon $start, Carbon $end, Collection $accounts): array
{
$accountIds = $accounts->pluck('id')->toArray();
$query = TransactionJournal
::leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
}
)
->whereNull('transaction_journals.deleted_at')
->whereNull('transactions.deleted_at')
->where('transaction_types.type', 'Withdrawal')
->where('transaction_journals.user_id', auth()->user()->id);
if (count($accountIds) > 0) {
$query->whereIn('transactions.account_id', $accountIds);
}
$query->groupBy(['budget_transaction_journal.budget_id', 'the_year']);
$queryResult = $query->get(
[
'budget_transaction_journal.budget_id',
DB::raw('DATE_FORMAT(transaction_journals.date,"%Y") AS the_year'),
DB::raw('SUM(transactions.amount) as sum_of_period'),
]
);
$data = [];
$budgets = $this->budgetRepository->getBudgets();
$years = $this->listOfYears($start, $end);
// do budget "zero"
$emptyBudget = new Budget;
$emptyBudget->id = 0;
$emptyBudget->name = strval(trans('firefly.no_budget'));
$budgets->push($emptyBudget);
// get all budgets and years.
foreach ($budgets as $budget) {
$data[$budget->id] = [
'name' => $budget->name,
'entries' => [],
];
foreach ($years as $year) {
// filter query result here!
$data[$budget->id]['entries'][$year] = $this->filterAmount($queryResult, $budget->id, $year);
}
}
return $data;
}
/** /**
* @param Carbon $start * @param Carbon $start
* @param Carbon $end * @param Carbon $end
@@ -294,24 +234,6 @@ class ReportHelper implements ReportHelperInterface
return $months; return $months;
} }
/**
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function listOfYears(Carbon $start, Carbon $end): array
{
$begin = clone $start;
$years = [];
while ($begin < $end) {
$years[] = $begin->year;
$begin->addYear();
}
return $years;
}
/** /**
* Returns an array of tags and their comparitive size with amounts bla bla. * Returns an array of tags and their comparitive size with amounts bla bla.
* *
@@ -386,56 +308,4 @@ class ReportHelper implements ReportHelperInterface
return $collection; return $collection;
} }
/**
* @param Collection $set
* @param int $budgetId
* @param int $year
*
* @return string
*/
protected function filterAmount(Collection $set, int $budgetId, int $year): string
{
/** @var stdClass $object */
$result = $set->filter(
function (TransactionJournal $object) use ($budgetId, $year) {
return intval($object->the_year) === $year && $budgetId === intval($object->budget_id);
}
);
$amount = '0';
if (!is_null($result->first())) {
$amount = $result->first()->sum_of_period;
}
return $amount;
}
/**
* Take the array as returned by CategoryRepositoryInterface::spentPerDay and CategoryRepositoryInterface::earnedByDay
* and sum up everything in the array in the given range.
*
* @param Carbon $start
* @param Carbon $end
* @param array $array
*
* @return string
*/
protected function getSumOfRange(Carbon $start, Carbon $end, array $array)
{
$sum = '0';
$currentStart = clone $start; // to not mess with the original one
$currentEnd = clone $end; // to not mess with the original one
while ($currentStart <= $currentEnd) {
$date = $currentStart->format('Y-m-d');
if (isset($array[$date])) {
$sum = bcadd($sum, $array[$date]);
}
$currentStart->addDay();
}
return $sum;
}
} }

View File

@@ -28,16 +28,6 @@ use Illuminate\Support\Collection;
interface ReportHelperInterface interface ReportHelperInterface
{ {
/**
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts
*
* @return array
*/
public function getBudgetMultiYear(Carbon $start, Carbon $end, Collection $accounts): array;
/** /**
* This method generates a full report for the given period on all * This method generates a full report for the given period on all
* the users bills and their payments. * the users bills and their payments.
@@ -90,14 +80,6 @@ interface ReportHelperInterface
*/ */
public function listOfMonths(Carbon $date): array; public function listOfMonths(Carbon $date): array;
/**
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function listOfYears(Carbon $start, Carbon $end): array;
/** /**
* Returns an array of tags and their comparitive size with amounts bla bla. * Returns an array of tags and their comparitive size with amounts bla bla.
* *

View File

@@ -16,6 +16,7 @@ namespace FireflyIII\Http\Controllers;
use Carbon\Carbon; use Carbon\Carbon;
use ExpandedForm; use ExpandedForm;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Http\Requests\AccountFormRequest; use FireflyIII\Http\Requests\AccountFormRequest;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
@@ -23,7 +24,6 @@ use FireflyIII\Models\Transaction;
use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use FireflyIII\Repositories\Account\AccountTaskerInterface; use FireflyIII\Repositories\Account\AccountTaskerInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Input; use Input;
use Navigation; use Navigation;
@@ -221,13 +221,13 @@ class AccountController extends Controller
$start = session('start', Navigation::startOfPeriod(new Carbon, $range)); $start = session('start', Navigation::startOfPeriod(new Carbon, $range));
/** @var Carbon $end */ /** @var Carbon $end */
$end = session('end', Navigation::endOfPeriod(new Carbon, $range)); $end = session('end', Navigation::endOfPeriod(new Carbon, $range));
$page = intval(Input::get('page')); $page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
$pageSize = Preferences::get('transactionPageSize', 50)->data; $pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$offset = ($page - 1) * $pageSize;
$set = $tasker->getJournalsInPeriod(new Collection([$account]), [], $start, $end); // replace with journal collector:
$count = $set->count(); $collector = new JournalCollector(auth()->user());
$subSet = $set->splice($offset, $pageSize); $collector->setAccounts(new Collection([$account]))->setRange($start, $end)->setLimit($pageSize)->setPage($page);
$journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page); $journals = $collector->getPaginatedJournals();
$journals->setPath('accounts/show/' . $account->id); $journals->setPath('accounts/show/' . $account->id);
// grouped other months thing: // grouped other months thing:
@@ -275,27 +275,25 @@ class AccountController extends Controller
} }
/** /**
* @param AccountTaskerInterface $tasker * @param Account $account
* @param Account $account * @param string $date
* @param string $date
* *
* @return View * @return View
*/ */
public function showWithDate(AccountTaskerInterface $tasker, Account $account, string $date) public function showWithDate(Account $account, string $date)
{ {
$carbon = new Carbon($date); $carbon = new Carbon($date);
$range = Preferences::get('viewRange', '1M')->data; $range = Preferences::get('viewRange', '1M')->data;
$start = Navigation::startOfPeriod($carbon, $range); $start = Navigation::startOfPeriod($carbon, $range);
$end = Navigation::endOfPeriod($carbon, $range); $end = Navigation::endOfPeriod($carbon, $range);
$subTitle = $account->name . ' (' . Navigation::periodShow($start, $range) . ')'; $subTitle = $account->name . ' (' . Navigation::periodShow($start, $range) . ')';
$page = intval(Input::get('page')); $page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
$page = $page === 0 ? 1 : $page; $pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$pageSize = Preferences::get('transactionPageSize', 50)->data;
$offset = ($page - 1) * $pageSize; // replace with journal collector:
$set = $tasker->getJournalsInPeriod(new Collection([$account]), [], $start, $end); $collector = new JournalCollector(auth()->user());
$count = $set->count(); $collector->setAccounts(new Collection([$account]))->setRange($start, $end)->setLimit($pageSize)->setPage($page);
$subSet = $set->splice($offset, $pageSize); $journals = $collector->getPaginatedJournals();
$journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page);
$journals->setPath('accounts/show/' . $account->id . '/' . $date); $journals->setPath('accounts/show/' . $account->id . '/' . $date);
return view('accounts.show_with_date', compact('category', 'date', 'account', 'journals', 'subTitle', 'carbon')); return view('accounts.show_with_date', compact('category', 'date', 'account', 'journals', 'subTitle', 'carbon'));

View File

@@ -14,10 +14,12 @@ declare(strict_types = 1);
namespace FireflyIII\Http\Controllers; namespace FireflyIII\Http\Controllers;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Http\Requests\BillFormRequest; use FireflyIII\Http\Requests\BillFormRequest;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use Illuminate\Support\Collection;
use Input; use Input;
use Preferences; use Preferences;
use Session; use Session;
@@ -200,10 +202,15 @@ class BillController extends Controller
$year = $date->year; $year = $date->year;
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page')); $page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data); $pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$journals = $repository->getJournals($bill, $page, $pageSize);
$yearAverage = $repository->getYearAverage($bill, $date); $yearAverage = $repository->getYearAverage($bill, $date);
$overallAverage = $repository->getOverallAverage($bill); $overallAverage = $repository->getOverallAverage($bill);
// use collector:
$collector = new JournalCollector(auth()->user());
$collector->setAllAssetAccounts()->setBills(new Collection([$bill]))->setPage($page)->setLimit($pageSize);
$journals = $collector->getPaginatedJournals();
$journals->setPath('/bills/show/' . $bill->id); $journals->setPath('/bills/show/' . $bill->id);
$bill->nextExpectedMatch = $repository->nextExpectedMatch($bill, new Carbon); $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill, new Carbon);
$hideBill = true; $hideBill = true;
$subTitle = e($bill->name); $subTitle = e($bill->name);

View File

@@ -17,13 +17,13 @@ use Amount;
use Carbon\Carbon; use Carbon\Carbon;
use Config; use Config;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Http\Requests\BudgetFormRequest; use FireflyIII\Http\Requests\BudgetFormRequest;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Input; use Input;
use Log; use Log;
@@ -247,31 +247,28 @@ class BudgetController extends Controller
} }
/** /**
* @param BudgetRepositoryInterface $repository
*
* @return View * @return View
*/ */
public function noBudget(BudgetRepositoryInterface $repository) public function noBudget()
{ {
/** @var Carbon $start */ /** @var Carbon $start */
$start = session('start', Carbon::now()->startOfMonth()); $start = session('start', Carbon::now()->startOfMonth());
/** @var Carbon $end */ /** @var Carbon $end */
$end = session('end', Carbon::now()->endOfMonth()); $end = session('end', Carbon::now()->endOfMonth());
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page')); $page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
$pageSize = Preferences::get('transactionPageSize', 50)->data; $pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$offset = ($page - 1) * $pageSize;
$journals = $repository->journalsInPeriodWithoutBudget(new Collection, $start, $end); // budget
$count = $journals->count();
$journals = $journals->slice($offset, $pageSize);
$list = new LengthAwarePaginator($journals, $count, $pageSize);
$subTitle = trans( $subTitle = trans(
'firefly.without_budget_between', 'firefly.without_budget_between',
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)] ['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
); );
$list->setPath('/budgets/list/noBudget');
return view('budgets.noBudget', compact('list', 'subTitle')); // collector
$collector = new JournalCollector(auth()->user());
$collector->setAllAssetAccounts()->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withoutBudget();
$journals = $collector->getPaginatedJournals();
$journals->setPath('/budgets/list/noBudget');
return view('budgets.no-budget', compact('journals', 'subTitle'));
} }
/** /**
@@ -305,14 +302,13 @@ class BudgetController extends Controller
$start = session('first', Carbon::create()->startOfYear()); $start = session('first', Carbon::create()->startOfYear());
$end = new Carbon; $end = new Carbon;
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page')); $page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
$pageSize = Preferences::get('transactionPageSize', 50)->data; $pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$offset = ($page - 1) * $pageSize;
$journals = $repository->journalsInPeriod(new Collection([$budget]), new Collection, $start, $end); // budget
$count = $journals->count();
$journals = $journals->slice($offset, $pageSize);
$journals = new LengthAwarePaginator($journals, $count, $pageSize);
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]); $accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
// collector:
$collector = new JournalCollector(auth()->user());
$collector->setAllAssetAccounts()->setRange($start, $end)->setBudget($budget)->setLimit($pageSize)->setPage($page);
$journals = $collector->getPaginatedJournals();
$journals->setPath('/budgets/show/' . $budget->id); $journals->setPath('/budgets/show/' . $budget->id);
@@ -347,16 +343,15 @@ class BudgetController extends Controller
$start = $repetition->startdate; $start = $repetition->startdate;
$end = $repetition->enddate; $end = $repetition->enddate;
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page')); $page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
$pageSize = Preferences::get('transactionPageSize', 50)->data; $pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$offset = ($page - 1) * $pageSize;
$journals = $repository->journalsInPeriod(new Collection([$budget]), new Collection, $start, $end); // budget
$count = $journals->count();
$journals = $journals->slice($offset, $pageSize);
$journals = new LengthAwarePaginator($journals, $count, $pageSize);
$subTitle = trans('firefly.budget_in_month', ['name' => $budget->name, 'month' => $repetition->startdate->formatLocalized($this->monthFormat)]); $subTitle = trans('firefly.budget_in_month', ['name' => $budget->name, 'month' => $repetition->startdate->formatLocalized($this->monthFormat)]);
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]); $accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
// collector:
$collector = new JournalCollector(auth()->user());
$collector->setAllAssetAccounts()->setRange($start, $end)->setBudget($budget)->setLimit($pageSize)->setPage($page);
$journals = $collector->getPaginatedJournals();
$journals->setPath('/budgets/show/' . $budget->id . '/' . $repetition->id); $journals->setPath('/budgets/show/' . $budget->id . '/' . $repetition->id);

View File

@@ -14,13 +14,13 @@ declare(strict_types = 1);
namespace FireflyIII\Http\Controllers; namespace FireflyIII\Http\Controllers;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Http\Requests\CategoryFormRequest; use FireflyIII\Http\Requests\CategoryFormRequest;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI; use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Input; use Input;
use Navigation; use Navigation;
@@ -147,23 +147,25 @@ class CategoryController extends Controller
} }
/** /**
* @param CRI $repository
*
* @return View * @return View
*/ */
public function noCategory(CRI $repository) public function noCategory()
{ {
/** @var Carbon $start */ /** @var Carbon $start */
$start = session('start', Carbon::now()->startOfMonth()); $start = session('start', Carbon::now()->startOfMonth());
/** @var Carbon $end */ /** @var Carbon $end */
$end = session('end', Carbon::now()->startOfMonth()); $end = session('end', Carbon::now()->startOfMonth());
$list = $repository->journalsInPeriodWithoutCategory(new Collection(), [], $start, $end); // category
// new collector:
$collector = new JournalCollector(auth()->user());
$collector->setAllAssetAccounts()->setRange($start, $end)->withoutCategory();//->groupJournals();
$journals = $collector->getJournals();
$subTitle = trans( $subTitle = trans(
'firefly.without_category_between', 'firefly.without_category_between',
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)] ['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
); );
return view('categories.noCategory', compact('list', 'subTitle')); return view('categories.no-category', compact('journals', 'subTitle'));
} }
/** /**
@@ -180,16 +182,17 @@ class CategoryController extends Controller
$start = session('start', Navigation::startOfPeriod(new Carbon, $range)); $start = session('start', Navigation::startOfPeriod(new Carbon, $range));
/** @var Carbon $end */ /** @var Carbon $end */
$end = session('end', Navigation::endOfPeriod(new Carbon, $range)); $end = session('end', Navigation::endOfPeriod(new Carbon, $range));
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
$hideCategory = true; // used in list. $hideCategory = true; // used in list.
$page = intval(Input::get('page')); $page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
$pageSize = Preferences::get('transactionPageSize', 50)->data; $pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$offset = ($page - 1) * $pageSize;
$set = $repository->journalsInPeriod(new Collection([$category]), new Collection, [], $start, $end); // category
$count = $set->count();
$subSet = $set->splice($offset, $pageSize);
$subTitle = $category->name; $subTitle = $category->name;
$subTitleIcon = 'fa-bar-chart'; $subTitleIcon = 'fa-bar-chart';
$journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page);
// use journal collector
$collector = new JournalCollector(auth()->user());
$collector->setPage($page)->setLimit($pageSize)->setAllAssetAccounts()->setRange($start, $end)->setCategory($category);
$journals = $collector->getPaginatedJournals();
$journals->setPath('categories/show/' . $category->id); $journals->setPath('categories/show/' . $category->id);
// oldest transaction in category: // oldest transaction in category:
@@ -218,7 +221,7 @@ class CategoryController extends Controller
$categoryCollection = new Collection([$category]); $categoryCollection = new Collection([$category]);
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
while ($end >= $start) { while ($end >= $start) {
$end = Navigation::startOfPeriod($end, $range); $end = Navigation::startOfPeriod($end, $range);
$currentEnd = Navigation::endOfPeriod($end, $range); $currentEnd = Navigation::endOfPeriod($end, $range);
@@ -233,18 +236,16 @@ class CategoryController extends Controller
} }
$cache->store($entries); $cache->store($entries);
return view('categories.show', compact('category', 'journals', 'entries', 'hideCategory', 'subTitle')); return view('categories.show', compact('category', 'journals', 'entries', 'hideCategory', 'subTitle', 'subTitleIcon'));
} }
/** /**
* @param CRI $repository * @param Category $category
* @param Category $category * @param $date
*
* @param $date
* *
* @return View * @return View
*/ */
public function showWithDate(CRI $repository, Category $category, string $date) public function showWithDate(Category $category, string $date)
{ {
$carbon = new Carbon($date); $carbon = new Carbon($date);
$range = Preferences::get('viewRange', '1M')->data; $range = Preferences::get('viewRange', '1M')->data;
@@ -252,15 +253,16 @@ class CategoryController extends Controller
$end = Navigation::endOfPeriod($carbon, $range); $end = Navigation::endOfPeriod($carbon, $range);
$subTitle = $category->name; $subTitle = $category->name;
$hideCategory = true; // used in list. $hideCategory = true; // used in list.
$page = intval(Input::get('page')); $page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
$pageSize = Preferences::get('transactionPageSize', 50)->data; $pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$offset = ($page - 1) * $pageSize;
$set = $repository->journalsInPeriod(new Collection([$category]), new Collection, [], $start, $end); // category // new collector:
$count = $set->count(); $collector = new JournalCollector(auth()->user());
$subSet = $set->splice($offset, $pageSize); $collector->setPage($page)->setLimit($pageSize)->setAllAssetAccounts()->setRange($start, $end)->setCategory($category);
$journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page); $journals = $collector->getPaginatedJournals();
$journals->setPath('categories/show/' . $category->id . '/' . $date); $journals->setPath('categories/show/' . $category->id . '/' . $date);
return view('categories.show_with_date', compact('category', 'journals', 'hideCategory', 'subTitle', 'carbon')); return view('categories.show_with_date', compact('category', 'journals', 'hideCategory', 'subTitle', 'carbon'));
} }

View File

@@ -15,11 +15,13 @@ namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Generator\Chart\Bill\BillChartGeneratorInterface; use FireflyIII\Generator\Chart\Bill\BillChartGeneratorInterface;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\Transaction;
use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
use Response; use Response;
/** /**
@@ -64,12 +66,11 @@ class BillController extends Controller
/** /**
* Shows the overview for a bill. The min/max amount and matched journals. * Shows the overview for a bill. The min/max amount and matched journals.
* *
* @param BillRepositoryInterface $repository * @param Bill $bill
* @param Bill $bill
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function single(BillRepositoryInterface $repository, Bill $bill) public function single(Bill $bill)
{ {
$cache = new CacheProperties; $cache = new CacheProperties;
$cache->addProperty('single'); $cache->addProperty('single');
@@ -80,12 +81,14 @@ class BillController extends Controller
} }
// get first transaction or today for start: // get first transaction or today for start:
$results = $repository->getJournals($bill, 1, 200); $collector = new JournalCollector(auth()->user());
$collector->setAllAssetAccounts()->setBills(new Collection([$bill]));
$results = $collector->getJournals();
// resort: // resort:
$results = $results->sortBy( $results = $results->sortBy(
function (TransactionJournal $journal) { function (Transaction $transaction) {
return $journal->date->format('U'); return $transaction->date->format('U');
} }
); );

View File

@@ -15,10 +15,12 @@ namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Generator\Chart\Budget\BudgetChartGeneratorInterface; use FireflyIII\Generator\Chart\Budget\BudgetChartGeneratorInterface;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@@ -175,7 +177,7 @@ class BudgetController extends Controller
$allEntries = $allEntries->merge($collection); $allEntries = $allEntries->merge($collection);
} }
$entry = $this->spentInPeriodWithout($repository, $start, $end); $entry = $this->spentInPeriodWithout($start, $end);
$allEntries->push($entry); $allEntries->push($entry);
$data = $this->generator->frontpage($allEntries); $data = $this->generator->frontpage($allEntries);
$cache->store($data); $cache->store($data);
@@ -319,19 +321,22 @@ class BudgetController extends Controller
} }
/** /**
* @param BudgetRepositoryInterface $repository * @param Carbon $start
* @param Carbon $start * @param Carbon $end
* @param Carbon $end
* *
* @return array * @return array
*/ */
private function spentInPeriodWithout(BudgetRepositoryInterface $repository, Carbon $start, Carbon $end):array private function spentInPeriodWithout(Carbon $start, Carbon $end):array
{ {
$list = $repository->journalsInPeriodWithoutBudget(new Collection, $start, $end); // budget // collector
$sum = '0'; $collector = new JournalCollector(auth()->user());
/** @var TransactionJournal $entry */ $types = [TransactionType::WITHDRAWAL];
foreach ($list as $entry) { $collector->setAllAssetAccounts()->setTypes($types)->setRange($start, $end)->withoutBudget();
$sum = bcadd(TransactionJournal::amount($entry), $sum); $journals = $collector->getJournals();
$sum = '0';
/** @var Transaction $entry */
foreach ($journals as $entry) {
$sum = bcadd($entry->transaction_amount, $sum);
} }
return [trans('firefly.no_budget'), '0', '0', $sum, '0', '0']; return [trans('firefly.no_budget'), '0', '0', $sum, '0', '0'];

View File

@@ -13,7 +13,6 @@ declare(strict_types = 1);
namespace FireflyIII\Http\Controllers; namespace FireflyIII\Http\Controllers;
use Carbon\Carbon;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Validation\ValidatesRequests;
@@ -61,31 +60,4 @@ class Controller extends BaseController
} }
/**
* Take the array as returned by CategoryRepositoryInterface::spentPerDay and CategoryRepositoryInterface::earnedByDay
* and sum up everything in the array in the given range.
*
* @param Carbon $start
* @param Carbon $end
* @param array $array
*
* @return string
*/
protected function getSumOfRange(Carbon $start, Carbon $end, array $array)
{
$sum = '0';
$currentStart = clone $start; // to not mess with the original one
$currentEnd = clone $end; // to not mess with the original one
while ($currentStart <= $currentEnd) {
$date = $currentStart->format('Y-m-d');
if (isset($array[$date])) {
$sum = bcadd($sum, $array[$date]);
}
$currentStart->addDay();
}
return $sum;
}
} }

View File

@@ -129,7 +129,7 @@ class CurrencyController extends Controller
Session::flash('success', trans('firefly.deleted_currency', ['name' => $currency->name])); Session::flash('success', trans('firefly.deleted_currency', ['name' => $currency->name]));
if (auth()->user()->hasRole('owner')) { if (auth()->user()->hasRole('owner')) {
$currency->delete(); $currency->forceDelete();
} }
return redirect(session('currency.delete.url')); return redirect(session('currency.delete.url'));

View File

@@ -42,9 +42,8 @@ class HelpController extends Controller
public function show(HelpInterface $help, string $route) public function show(HelpInterface $help, string $route)
{ {
$language = Preferences::get('language', config('firefly.default_language', 'en_US'))->data; $language = Preferences::get('language', config('firefly.default_language', 'en_US'))->data;
$content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>'; $content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
$alternative = false;
if (!$help->hasRoute($route)) { if (!$help->hasRoute($route)) {
Log::error('No such route: ' . $route); Log::error('No such route: ' . $route);
@@ -54,7 +53,7 @@ class HelpController extends Controller
if ($help->inCache($route, $language)) { if ($help->inCache($route, $language)) {
$content = $help->getFromCache($route, $language); $content = $help->getFromCache($route, $language);
Log::debug('Help text was in cache.'); Log::debug(sprintf('Help text %s was in cache.', $language));
return Response::json($content); return Response::json($content);
} }
@@ -63,19 +62,21 @@ class HelpController extends Controller
// get backup language content (try English): // get backup language content (try English):
if (strlen($content) === 0) { if (strlen($content) === 0) {
$language = 'en_US'; $language = 'en_US';
$content = $help->getFromGithub($language, $route); if ($help->inCache($route, $language)) {
$alternative = true; Log::debug(sprintf('Help text %s was in cache.', $language));
} $content = $help->getFromCache($route, $language);
}
if ($alternative && strlen($content) > 0) { if (!$help->inCache($route, $language)) {
$content = '<p><em>' . strval(trans('firefly.help_may_not_be_your_language')) . '</em></p>' . $content; $content = $help->getFromGithub($language, $route);
$content = '<p><em>' . strval(trans('firefly.help_may_not_be_your_language')) . '</em></p>' . $content;
}
} }
if (strlen($content) === 0) { if (strlen($content) === 0) {
$content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>'; $content = '<p>' . strval(trans('firefly.route_has_no_help')) . '</p>';
} }
$help->putInCache($route, $language, $content); $help->putInCache($route, $language, $content);
return Response::json($content); return Response::json($content);

View File

@@ -15,10 +15,10 @@ namespace FireflyIII\Http\Controllers;
use Artisan; use Artisan;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use FireflyIII\Models\Tag; use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use FireflyIII\Repositories\Account\AccountTaskerInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@@ -115,12 +115,11 @@ class HomeController extends Controller
} }
/** /**
* @param ARI $repository * @param ARI $repository
* @param AccountTaskerInterface $tasker
* *
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
*/ */
public function index(ARI $repository, AccountTaskerInterface $tasker) public function index(ARI $repository)
{ {
$types = config('firefly.accountTypesByIdentifier.asset'); $types = config('firefly.accountTypesByIdentifier.asset');
@@ -144,8 +143,9 @@ class HomeController extends Controller
$showDepositsFrontpage = Preferences::get('showDepositsFrontpage', false)->data; $showDepositsFrontpage = Preferences::get('showDepositsFrontpage', false)->data;
foreach ($accounts as $account) { foreach ($accounts as $account) {
$set = $tasker->getJournalsInPeriod(new Collection([$account]), [], $start, $end); $collector = new JournalCollector(auth()->user());
$set = $set->splice(0, 10); $collector->setAccounts(new Collection([$account]))->setRange($start, $end)->setLimit(10)->setPage(1);
$set = $collector->getJournals();
if (count($set) > 0) { if (count($set) > 0) {
$transactions[] = [$set, $account]; $transactions[] = [$set, $account];

View File

@@ -15,12 +15,12 @@ namespace FireflyIII\Http\Controllers;
use Amount; use Amount;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Account\AccountTaskerInterface; use FireflyIII\Repositories\Account\AccountTaskerInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI; use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI;
use FireflyIII\Repositories\Journal\JournalTaskerInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Input; use Input;
@@ -270,17 +270,20 @@ class JsonController extends Controller
} }
/** /**
* @param JournalTaskerInterface $tasker * @param $what
* @param $what
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Illuminate\Http\JsonResponse
*/ */
public function transactionJournals(JournalTaskerInterface $tasker, $what) public function transactionJournals($what)
{ {
$descriptions = []; $descriptions = [];
$type = config('firefly.transactionTypesByWhat.' . $what); $type = config('firefly.transactionTypesByWhat.' . $what);
$types = [$type]; $types = [$type];
$journals = $tasker->getJournals($types, 1, 50);
// use journal collector instead:
$collector = new JournalCollector(auth()->user());
$collector->setTypes($types)->setLimit(100)->setPage(1);
$journals = $collector->getJournals();
foreach ($journals as $j) { foreach ($journals as $j) {
$descriptions[] = $j->description; $descriptions[] = $j->description;
} }

View File

@@ -107,6 +107,12 @@ class PiggyBankController extends Controller
$subTitle = trans('firefly.new_piggy_bank'); $subTitle = trans('firefly.new_piggy_bank');
$subTitleIcon = 'fa-plus'; $subTitleIcon = 'fa-plus';
if (count($accounts) === 0) {
Session::flash('error', strval(trans('firefly.need_at_least_one_account')));
return redirect(route('new-user.index'));
}
// put previous url in session if not redirect from store (not "create another"). // put previous url in session if not redirect from store (not "create another").
if (session('piggy-banks.create.fromStore') !== true) { if (session('piggy-banks.create.fromStore') !== true) {
Session::put('piggy-banks.create.url', URL::previous()); Session::put('piggy-banks.create.url', URL::previous());

View File

@@ -17,12 +17,12 @@ namespace FireflyIII\Http\Controllers\Popup;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collection\BalanceLine; use FireflyIII\Helpers\Collection\BalanceLine;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Account\AccountTaskerInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Support\Binder\AccountList; use FireflyIII\Support\Binder\AccountList;
@@ -98,20 +98,39 @@ class ReportController extends Controller
$repository = app(AccountRepositoryInterface::class); $repository = app(AccountRepositoryInterface::class);
$account = $repository->find(intval($attributes['accountId'])); $account = $repository->find(intval($attributes['accountId']));
$types = [TransactionType::WITHDRAWAL];
switch (true) { switch (true) {
case ($role === BalanceLine::ROLE_DEFAULTROLE && !is_null($budget->id)): case ($role === BalanceLine::ROLE_DEFAULTROLE && !is_null($budget->id)):
$journals = $budgetRepository->journalsInPeriod( $collector = new JournalCollector(auth()->user());
new Collection([$budget]), new Collection([$account]), $attributes['startDate'], $attributes['endDate'] $collector
); ->setAccounts(new Collection([$account]))
->setRange($attributes['startDate'], $attributes['endDate'])
->setBudget($budget);
$journals = $collector->getJournals();
break; break;
case ($role === BalanceLine::ROLE_DEFAULTROLE && is_null($budget->id)): case ($role === BalanceLine::ROLE_DEFAULTROLE && is_null($budget->id)):
$budget->name = strval(trans('firefly.no_budget')); $budget->name = strval(trans('firefly.no_budget'));
$journals = $budgetRepository->journalsInPeriodWithoutBudget($attributes['accounts'], $attributes['startDate'], $attributes['endDate']); // collector
$collector = new JournalCollector(auth()->user());
$collector
->setAccounts(new Collection([$account]))
->setTypes($types)
->setRange($attributes['startDate'], $attributes['endDate'])
->withoutBudget();
$journals = $collector->getJournals();
break; break;
case ($role === BalanceLine::ROLE_DIFFROLE): case ($role === BalanceLine::ROLE_DIFFROLE):
// journals no budget, not corrected by a tag. // journals no budget, not corrected by a tag.
$journals = $budgetRepository->journalsInPeriodWithoutBudget($attributes['accounts'], $attributes['startDate'], $attributes['endDate']); $collector = new JournalCollector(auth()->user());
$collector
->setAccounts(new Collection([$account]))
->setTypes($types)
->setRange($attributes['startDate'], $attributes['endDate'])
->withoutBudget();
$journals = $collector->getJournals();
$budget->name = strval(trans('firefly.leftUnbalanced')); $budget->name = strval(trans('firefly.leftUnbalanced'));
$journals = $journals->filter( $journals = $journals->filter(
function (TransactionJournal $journal) { function (TransactionJournal $journal) {
@@ -148,14 +167,21 @@ class ReportController extends Controller
/** @var BudgetRepositoryInterface $repository */ /** @var BudgetRepositoryInterface $repository */
$repository = app(BudgetRepositoryInterface::class); $repository = app(BudgetRepositoryInterface::class);
$budget = $repository->find(intval($attributes['budgetId'])); $budget = $repository->find(intval($attributes['budgetId']));
if (is_null($budget->id)) { $collector = new JournalCollector(auth()->user());
$journals = $repository->journalsInPeriodWithoutBudget($attributes['accounts'], $attributes['startDate'], $attributes['endDate']);
} else {
// get all expenses in budget in period:
$journals = $repository->journalsInPeriod(new Collection([$budget]), $attributes['accounts'], $attributes['startDate'], $attributes['endDate']);
}
$view = view('popup.report.budget-spent-amount', compact('journals', 'budget'))->render(); $collector
->setAccounts($attributes['accounts'])
->setRange($attributes['startDate'], $attributes['endDate']);
if (is_null($budget->id)) {
$collector->setTypes([TransactionType::WITHDRAWAL])->withoutBudget();
}
if (!is_null($budget->id)) {
// get all expenses in budget in period:
$collector->setBudget($budget);
}
$journals = $collector->getJournals();
$view = view('popup.report.budget-spent-amount', compact('journals', 'budget'))->render();
return $view; return $view;
} }
@@ -174,10 +200,14 @@ class ReportController extends Controller
$repository = app(CategoryRepositoryInterface::class); $repository = app(CategoryRepositoryInterface::class);
$category = $repository->find(intval($attributes['categoryId'])); $category = $repository->find(intval($attributes['categoryId']));
$types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER]; $types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
$journals = $repository->journalsInPeriod( // get journal collector instead:
new Collection([$category]), $attributes['accounts'], $types, $attributes['startDate'], $attributes['endDate'] $collector = new JournalCollector(auth()->user());
); $collector->setAccounts($attributes['accounts'])->setTypes($types)
$view = view('popup.report.category-entry', compact('journals', 'category'))->render(); ->setRange($attributes['startDate'], $attributes['endDate'])
->setCategory($category);
$journals = $collector->getJournals(); // 7193
$view = view('popup.report.category-entry', compact('journals', 'category'))->render();
return $view; return $view;
} }
@@ -192,14 +222,14 @@ class ReportController extends Controller
*/ */
private function expenseEntry(array $attributes): string private function expenseEntry(array $attributes): string
{ {
/** @var AccountTaskerInterface $tasker */
$tasker = app(AccountTaskerInterface::class);
/** @var AccountRepositoryInterface $repository */ /** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class); $repository = app(AccountRepositoryInterface::class);
$account = $repository->find(intval($attributes['accountId'])); $account = $repository->find(intval($attributes['accountId']));
$types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER]; $types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
$journals = $tasker->getJournalsInPeriod(new Collection([$account]), $types, $attributes['startDate'], $attributes['endDate']); $collector = new JournalCollector(auth()->user());
$collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate'])->setTypes($types);
$journals = $collector->getJournals();
$report = $attributes['accounts']->pluck('id')->toArray(); // accounts used in this report $report = $attributes['accounts']->pluck('id')->toArray(); // accounts used in this report
// filter for transfers and withdrawals TO the given $account // filter for transfers and withdrawals TO the given $account
@@ -228,14 +258,14 @@ class ReportController extends Controller
*/ */
private function incomeEntry(array $attributes): string private function incomeEntry(array $attributes): string
{ {
/** @var AccountTaskerInterface $tasker */
$tasker = app(AccountTaskerInterface::class);
/** @var AccountRepositoryInterface $repository */ /** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class); $repository = app(AccountRepositoryInterface::class);
$account = $repository->find(intval($attributes['accountId'])); $account = $repository->find(intval($attributes['accountId']));
$types = [TransactionType::DEPOSIT, TransactionType::TRANSFER]; $types = [TransactionType::DEPOSIT, TransactionType::TRANSFER];
$journals = $tasker->getJournalsInPeriod(new Collection([$account]), $types, $attributes['startDate'], $attributes['endDate']); $collector = new JournalCollector(auth()->user());
$report = $attributes['accounts']->pluck('id')->toArray(); // accounts used in this report $collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate'])->setTypes($types);
$journals = $collector->getJournals();
$report = $attributes['accounts']->pluck('id')->toArray(); // accounts used in this report
// filter the set so the destinations outside of $attributes['accounts'] are not included. // filter the set so the destinations outside of $attributes['accounts'] are not included.
$journals = $journals->filter( $journals = $journals->filter(

View File

@@ -13,7 +13,6 @@ declare(strict_types = 1);
namespace FireflyIII\Http\Controllers; namespace FireflyIII\Http\Controllers;
use FireflyIII\Events\DeletedUser;
use FireflyIII\Http\Requests\DeleteAccountFormRequest; use FireflyIII\Http\Requests\DeleteAccountFormRequest;
use FireflyIII\Http\Requests\ProfileFormRequest; use FireflyIII\Http\Requests\ProfileFormRequest;
use FireflyIII\User; use FireflyIII\User;

View File

@@ -28,6 +28,35 @@ use Illuminate\Support\Collection;
class BudgetController extends Controller class BudgetController extends Controller
{ {
/**
* @param BudgetReportHelperInterface $helper
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts
*
* @return mixed|string
*/
public function budgetMultiYear(BudgetReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
{
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('budget-mult-year-report');
$cache->addProperty($accounts->pluck('id')->toArray());
if ($cache->has()) {
return $cache->get();
}
$years = $helper->listOfYears($start, $end);
$budgetMultiYear = $helper->getBudgetMultiYear($start, $end, $accounts);
$result = view('reports.partials.budget-multi-year', compact('budgetMultiYear', 'years'))->render();
$cache->store($result);
return $result;
}
/** /**
* @param BudgetReportHelperInterface $helper * @param BudgetReportHelperInterface $helper
* @param Carbon $start * @param Carbon $start

View File

@@ -19,7 +19,6 @@ use FireflyIII\Helpers\Report\ReportHelperInterface;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Response;
/** /**
* Class InOutController * Class InOutController
@@ -37,29 +36,83 @@ class InOutController extends Controller
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function inOutReport(ReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts) public function expenseReport(ReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
{ {
// chart properties for cache: // chart properties for cache:
$cache = new CacheProperties; $cache = new CacheProperties;
$cache->addProperty($start); $cache->addProperty($start);
$cache->addProperty($end); $cache->addProperty($end);
$cache->addProperty('in-out-report'); $cache->addProperty('expense-report');
$cache->addProperty($accounts->pluck('id')->toArray()); $cache->addProperty($accounts->pluck('id')->toArray());
if ($cache->has()) { if ($cache->has()) {
return Response::json($cache->get()); return $cache->get();
}
$expenses = $helper->getExpenseReport($start, $end, $accounts);
$result = view('reports.partials.expenses', compact('expenses'))->render();
$cache->store($result);
return $result;
}
/**
* @param ReportHelperInterface $helper
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts
*
* @return \Illuminate\Http\JsonResponse
*/
public function incExpReport(ReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
{
// chart properties for cache:
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('inc-exp-report');
$cache->addProperty($accounts->pluck('id')->toArray());
if ($cache->has()) {
return $cache->get();
} }
$incomes = $helper->getIncomeReport($start, $end, $accounts); $incomes = $helper->getIncomeReport($start, $end, $accounts);
$expenses = $helper->getExpenseReport($start, $end, $accounts); $expenses = $helper->getExpenseReport($start, $end, $accounts);
$result = [ $result = view('reports.partials.income-vs-expenses', compact('expenses', 'incomes'))->render();
'income' => view('reports.partials.income', compact('incomes'))->render(),
'expenses' => view('reports.partials.expenses', compact('expenses'))->render(),
'incomes_expenses' => view('reports.partials.income-vs-expenses', compact('expenses', 'incomes'))->render(),
];
$cache->store($result); $cache->store($result);
return Response::json($result); return $result;
}
/**
* @param ReportHelperInterface $helper
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts
*
* @return \Illuminate\Http\JsonResponse
*/
public function incomeReport(ReportHelperInterface $helper, Carbon $start, Carbon $end, Collection $accounts)
{
// chart properties for cache:
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('income-report');
$cache->addProperty($accounts->pluck('id')->toArray());
if ($cache->has()) {
return $cache->get();
}
$incomes = $helper->getIncomeReport($start, $end, $accounts);
$result = view('reports.partials.income', compact('incomes'))->render();
$cache->store($result);
return $result;
} }

View File

@@ -15,12 +15,12 @@ namespace FireflyIII\Http\Controllers;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Helpers\Report\ReportHelperInterface; use FireflyIII\Helpers\Report\ReportHelperInterface;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Account\AccountTaskerInterface;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Preferences; use Preferences;
use Session; use Session;
@@ -150,8 +150,6 @@ class ReportController extends Controller
*/ */
private function auditReport(Carbon $start, Carbon $end, Collection $accounts) private function auditReport(Carbon $start, Carbon $end, Collection $accounts)
{ {
/** @var AccountTaskerInterface $tasker */
$tasker = app(AccountTaskerInterface::class);
$auditData = []; $auditData = [];
$dayBefore = clone $start; $dayBefore = clone $start;
$dayBefore->subDay(); $dayBefore->subDay();
@@ -160,9 +158,11 @@ class ReportController extends Controller
// balance the day before: // balance the day before:
$id = $account->id; $id = $account->id;
$dayBeforeBalance = Steam::balance($account, $dayBefore); $dayBeforeBalance = Steam::balance($account, $dayBefore);
$journals = $tasker->getJournalsInPeriod(new Collection([$account]), [], $start, $end); $collector = new JournalCollector(auth()->user());
$journals = $journals->reverse(); $collector->setAccounts(new Collection([$account]))->setRange($start, $end);
$startBalance = $dayBeforeBalance; $journals = $collector->getJournals();
$journals = $journals->reverse();
$startBalance = $dayBeforeBalance;
/** @var Transaction $journal */ /** @var Transaction $journal */
@@ -244,8 +244,6 @@ class ReportController extends Controller
{ {
// need all budgets // need all budgets
// need all years. // need all years.
$years = $this->helper->listOfYears($start, $end);
$budgetMultiYear = $this->helper->getBudgetMultiYear($start, $end, $accounts);
// and some id's, joined: // and some id's, joined:
@@ -259,8 +257,7 @@ class ReportController extends Controller
return view( return view(
'reports.default.multi-year', 'reports.default.multi-year',
compact( compact(
'accounts', 'start', 'end', 'accountIds', 'reportType', 'accounts', 'start', 'end', 'accountIds', 'reportType'
'years', 'budgetMultiYear'
) )
); );
} }

View File

@@ -306,7 +306,7 @@ class RuleController extends Controller
} }
// Return json response // Return json response
$view = view('list.journals-tiny', ['transactions' => $matchingTransactions])->render(); $view = view('list.journals-tiny-tasker', ['transactions' => $matchingTransactions])->render();
return Response::json(['html' => $view, 'warning' => $warning]); return Response::json(['html' => $view, 'warning' => $warning]);
} }

View File

@@ -14,7 +14,7 @@ declare(strict_types = 1);
namespace FireflyIII\Http\Controllers; namespace FireflyIII\Http\Controllers;
use FireflyIII\Support\Search\SearchInterface; use FireflyIII\Support\Search\SearchInterface;
use Input; use Illuminate\Http\Request;
/** /**
* Class SearchController * Class SearchController
@@ -30,12 +30,6 @@ class SearchController extends Controller
{ {
parent::__construct(); parent::__construct();
$this->middleware(
function ($request, $next) {
return $next($request);
}
);
} }
/** /**
@@ -45,16 +39,21 @@ class SearchController extends Controller
* *
* @return $this * @return $this
*/ */
public function index(SearchInterface $searcher) public function index(Request $request, SearchInterface $searcher)
{ {
$minSearchLen = 1;
$subTitle = null; $subTitle = null;
$query = null; $query = null;
$result = []; $result = [];
$title = trans('firefly.search'); $title = trans('firefly.search');
$limit = 20;
$mainTitleIcon = 'fa-search'; $mainTitleIcon = 'fa-search';
if (!is_null(Input::get('q')) && strlen(Input::get('q')) > 0) {
$query = trim(Input::get('q')); // set limit for search:
$searcher->setLimit($limit);
if (!is_null($request->get('q')) && strlen($request->get('q')) >= $minSearchLen) {
$query = trim(strtolower($request->get('q')));
$words = explode(' ', $query); $words = explode(' ', $query);
$subTitle = trans('firefly.search_results_for', ['query' => $query]); $subTitle = trans('firefly.search_results_for', ['query' => $query]);
@@ -67,7 +66,7 @@ class SearchController extends Controller
} }
return view('search.index', compact('title', 'subTitle', 'mainTitleIcon', 'query', 'result')); return view('search.index', compact('title', 'subTitle', 'limit', 'mainTitleIcon', 'query', 'result'));
} }
} }

View File

@@ -13,10 +13,11 @@ declare(strict_types = 1);
namespace FireflyIII\Http\Controllers; namespace FireflyIII\Http\Controllers;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Http\Requests\TagFormRequest; use FireflyIII\Http\Requests\TagFormRequest;
use FireflyIII\Models\Preference; use FireflyIII\Models\Preference;
use FireflyIII\Models\Tag; use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\Transaction;
use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Input; use Input;
@@ -226,19 +227,27 @@ class TagController extends Controller
} }
/** /**
* @param Tag $tag * @param Tag $tag
* @param TagRepositoryInterface $repository
* *
* @return View * @return View
*/ */
public function show(Tag $tag, TagRepositoryInterface $repository) public function show(Tag $tag)
{ {
$subTitle = $tag->tag; $subTitle = $tag->tag;
$subTitleIcon = 'fa-tag'; $subTitleIcon = 'fa-tag';
$journals = $repository->getJournals($tag); $page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
$sum = $journals->sum( $pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
function (TransactionJournal $journal) {
return TransactionJournal::amount($journal); // use collector:
// replace with journal collector:
$collector = new JournalCollector(auth()->user());
$collector->setAllAssetAccounts()->setLimit($pageSize)->setPage($page)->setTag($tag);
$journals = $collector->getPaginatedJournals();
$journals->setPath('tags/show/' . $tag->id);
$sum = $journals->sum(
function (Transaction $transaction) {
return $transaction->transaction_amount;
} }
); );

View File

@@ -206,7 +206,6 @@ class ConvertController extends Controller
$sourceAccount = TransactionJournal::sourceAccountList($journal)->first(); $sourceAccount = TransactionJournal::sourceAccountList($journal)->first();
$destinationAccount = TransactionJournal::destinationAccountList($journal)->first(); $destinationAccount = TransactionJournal::destinationAccountList($journal)->first();
$sourceType = $journal->transactionType; $sourceType = $journal->transactionType;
$source = new Account;
$joined = $sourceType->type . '-' . $destinationType->type; $joined = $sourceType->type . '-' . $destinationType->type;
switch ($joined) { switch ($joined) {
default: default:

View File

@@ -171,7 +171,6 @@ class SingleController extends Controller
$assetAccounts = ExpandedForm::makeSelectList($this->accounts->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET])); $assetAccounts = ExpandedForm::makeSelectList($this->accounts->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]));
$budgetList = ExpandedForm::makeSelectListWithEmpty($this->budgets->getActiveBudgets()); $budgetList = ExpandedForm::makeSelectListWithEmpty($this->budgets->getActiveBudgets());
$piggyBankList = ExpandedForm::makeSelectListWithEmpty($this->piggyBanks->getPiggyBanks());
// view related code // view related code
$subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]); $subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]);
@@ -188,7 +187,6 @@ class SingleController extends Controller
'process_date' => TransactionJournal::dateAsString($journal, 'process_date'), 'process_date' => TransactionJournal::dateAsString($journal, 'process_date'),
'category' => TransactionJournal::categoryAsString($journal), 'category' => TransactionJournal::categoryAsString($journal),
'budget_id' => TransactionJournal::budgetId($journal), 'budget_id' => TransactionJournal::budgetId($journal),
'piggy_bank_id' => TransactionJournal::piggyBankId($journal),
'tags' => join(',', $journal->tags->pluck('tag')->toArray()), 'tags' => join(',', $journal->tags->pluck('tag')->toArray()),
'source_account_id' => $sourceAccounts->first()->id, 'source_account_id' => $sourceAccounts->first()->id,
'source_account_name' => $sourceAccounts->first()->name, 'source_account_name' => $sourceAccounts->first()->name,
@@ -225,7 +223,7 @@ class SingleController extends Controller
return view( return view(
'transactions.edit', 'transactions.edit',
compact('journal', 'optionalFields', 'assetAccounts', 'what', 'budgetList', 'piggyBankList', 'subTitle') compact('journal', 'optionalFields', 'assetAccounts', 'what', 'budgetList', 'subTitle')
)->with('data', $preFilled); )->with('data', $preFilled);
} }

View File

@@ -14,6 +14,7 @@ declare(strict_types = 1);
namespace FireflyIII\Http\Controllers; namespace FireflyIII\Http\Controllers;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalTaskerInterface; use FireflyIII\Repositories\Journal\JournalTaskerInterface;
@@ -49,21 +50,22 @@ class TransactionController extends Controller
} }
/** /**
* @param Request $request * @param Request $request
* @param JournalTaskerInterface $tasker * @param string $what
* @param string $what
* *
* @return View * @return View
*/ */
public function index(Request $request, JournalTaskerInterface $tasker, string $what) public function index(Request $request, string $what)
{ {
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data); $pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$subTitleIcon = config('firefly.transactionIconsByWhat.' . $what); $subTitleIcon = config('firefly.transactionIconsByWhat.' . $what);
$types = config('firefly.transactionTypesByWhat.' . $what); $types = config('firefly.transactionTypesByWhat.' . $what);
$subTitle = trans('firefly.title_' . $what); $subTitle = trans('firefly.title_' . $what);
$page = intval($request->get('page')); $page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
$journals = $tasker->getJournals($types, $page, $pageSize); $collector = new JournalCollector(auth()->user());
$collector->setTypes($types)->setLimit($pageSize)->setPage($page)->setAllAssetAccounts();
$journals = $collector->getPaginatedJournals();
$journals->setPath('transactions/' . $what); $journals->setPath('transactions/' . $what);
return view('transactions.index', compact('subTitle', 'what', 'subTitleIcon', 'journals')); return view('transactions.index', compact('subTitle', 'what', 'subTitleIcon', 'journals'));

View File

@@ -14,8 +14,8 @@ declare(strict_types = 1);
namespace FireflyIII\Jobs; namespace FireflyIII\Jobs;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Models\RuleGroup; use FireflyIII\Models\RuleGroup;
use FireflyIII\Repositories\Journal\JournalTaskerInterface;
use FireflyIII\Rules\Processor; use FireflyIII\Rules\Processor;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@@ -129,16 +129,16 @@ class ExecuteRuleGroupOnExistingTransactions extends Job implements ShouldQueue
public function handle() public function handle()
{ {
// Lookup all journals that match the parameters specified // Lookup all journals that match the parameters specified
$journals = $this->collectJournals(); $transactions = $this->collectJournals();
// Find processors for each rule within the current rule group // Find processors for each rule within the current rule group
$processors = $this->collectProcessors(); $processors = $this->collectProcessors();
// Execute the rules for each transaction // Execute the rules for each transaction
foreach ($journals as $journal) { foreach ($transactions as $transaction) {
/** @var Processor $processor */ /** @var Processor $processor */
foreach ($processors as $processor) { foreach ($processors as $processor) {
$processor->handleTransactionJournal($journal); $processor->handleTransaction($transaction);
// Stop processing this group if the rule specifies 'stop_processing' // Stop processing this group if the rule specifies 'stop_processing'
if ($processor->getRule()->stop_processing) { if ($processor->getRule()->stop_processing) {
@@ -155,10 +155,10 @@ class ExecuteRuleGroupOnExistingTransactions extends Job implements ShouldQueue
*/ */
protected function collectJournals() protected function collectJournals()
{ {
/** @var JournalTaskerInterface $tasker */ $collector = new JournalCollector(auth()->user());
$tasker = app(JournalTaskerInterface::class); $collector->setAccounts($this->accounts)->setRange($this->startDate, $this->endDate);
return $tasker->getJournalsInRange($this->accounts, $this->startDate, $this->endDate); return $collector->getJournals();
} }
/** /**

View File

@@ -46,13 +46,12 @@ class Note extends Model
/** /**
* @param $value
*
* @return string * @return string
*/ */
public function getMarkdownAttribute(): string public function getMarkdownAttribute(): string
{ {
$converter = new CommonMarkConverter; $converter = new CommonMarkConverter;
return $converter->convertToHtml($this->text); return $converter->convertToHtml($this->text);
} }

View File

@@ -23,22 +23,22 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/** /**
* FireflyIII\Models\PiggyBank * FireflyIII\Models\PiggyBank
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property \Carbon\Carbon $deleted_at * @property \Carbon\Carbon $deleted_at
* @property integer $account_id * @property integer $account_id
* @property string $name * @property string $name
* @property float $targetamount * @property float $targetamount
* @property \Carbon\Carbon $startdate * @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $targetdate * @property \Carbon\Carbon $targetdate
* @property integer $order * @property integer $order
* @property boolean $encrypted * @property boolean $encrypted
* @property-read Account $account * @property-read Account $account
* @property-read \Illuminate\Database\Eloquent\Collection|PiggyBankRepetition[] $piggyBankRepetitions * @property-read \Illuminate\Database\Eloquent\Collection|PiggyBankRepetition[] $piggyBankRepetitions
* @property-read \Illuminate\Database\Eloquent\Collection|PiggyBankEvent[] $piggyBankEvents * @property-read \Illuminate\Database\Eloquent\Collection|PiggyBankEvent[] $piggyBankEvents
* @property string $reminder * @property string $reminder
* @property PiggyBankRepetition $currentRep * @property PiggyBankRepetition $currentRep
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereId($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereUpdatedAt($value)
@@ -54,7 +54,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereDeletedAt($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereDeletedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereEncrypted($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereEncrypted($value)
* @mixin \Eloquent * @mixin \Eloquent
* @property boolean $active * @property boolean $active
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereActive($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereActive($value)
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Note[] $notes * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Note[] $notes
*/ */

View File

@@ -70,7 +70,6 @@ class EventServiceProvider extends ServiceProvider
'FireflyIII\Events\UpdatedTransactionJournal' => // is a Transaction Journal related event. 'FireflyIII\Events\UpdatedTransactionJournal' => // is a Transaction Journal related event.
[ [
'FireflyIII\Handlers\Events\UpdatedJournalEventHandler@scanBills', 'FireflyIII\Handlers\Events\UpdatedJournalEventHandler@scanBills',
'FireflyIII\Handlers\Events\UpdatedJournalEventHandler@connectToPiggyBank',
'FireflyIII\Handlers\Events\UpdatedJournalEventHandler@processRules', 'FireflyIII\Handlers\Events\UpdatedJournalEventHandler@processRules',
], ],

View File

@@ -94,7 +94,6 @@ class FireflyServiceProvider extends ServiceProvider
); );
$this->app->bind('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface', 'FireflyIII\Repositories\Currency\CurrencyRepository'); $this->app->bind('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface', 'FireflyIII\Repositories\Currency\CurrencyRepository');
$this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search');
$this->app->bind('FireflyIII\Repositories\User\UserRepositoryInterface', 'FireflyIII\Repositories\User\UserRepository'); $this->app->bind('FireflyIII\Repositories\User\UserRepositoryInterface', 'FireflyIII\Repositories\User\UserRepository');
$this->app->bind('FireflyIII\Helpers\Attachments\AttachmentHelperInterface', 'FireflyIII\Helpers\Attachments\AttachmentHelper'); $this->app->bind('FireflyIII\Helpers\Attachments\AttachmentHelperInterface', 'FireflyIII\Helpers\Attachments\AttachmentHelper');
$this->app->bind( $this->app->bind(

View File

@@ -0,0 +1,59 @@
<?php
/**
* AccountServiceProvider.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Providers;
use FireflyIII\Exceptions\FireflyException;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;
/**
* Class SearchServiceProvider
*
* @package FireflyIII\Providers
*/
class SearchServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
//
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
$this->app->bind(
'FireflyIII\Support\Search\SearchInterface',
function (Application $app, array $arguments) {
if (!isset($arguments[0]) && $app->auth->check()) {
return app('FireflyIII\Support\Search\Search', [auth()->user()]);
}
if (!isset($arguments[0]) && !$app->auth->check()) {
throw new FireflyException('There is no user present.');
}
return app('FireflyIII\Support\Search\Search', $arguments);
}
);
}
}

View File

@@ -190,77 +190,6 @@ class AccountTasker implements AccountTaskerInterface
return $object; return $object;
} }
/**
* It might be worth it to expand this query to include all account information required.
*
* @param Collection $accounts
* @param array $types
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getJournalsInPeriod(Collection $accounts, array $types, Carbon $start, Carbon $end): Collection
{
$accountIds = $accounts->pluck('id')->toArray();
$query = Transaction
::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('transaction_currencies', 'transaction_currencies.id', 'transaction_journals.transaction_currency_id')
->leftJoin('transaction_types', 'transaction_types.id', 'transaction_journals.transaction_type_id')
->leftJoin('bills', 'bills.id', 'transaction_journals.bill_id')
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->leftJoin('account_types', 'accounts.account_type_id', 'account_types.id')
->whereIn('transactions.account_id', $accountIds)
->whereNull('transactions.deleted_at')
->whereNull('transaction_journals.deleted_at')
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->where('transaction_journals.user_id', $this->user->id)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC');
if (count($types) > 0) {
$query->whereIn('transaction_types.type', $types);
}
$set = $query->get(
[
'transaction_journals.id as journal_id',
'transaction_journals.description',
'transaction_journals.date',
'transaction_journals.encrypted',
//'transaction_journals.transaction_currency_id',
'transaction_currencies.code as transaction_currency_code',
//'transaction_currencies.symbol as transaction_currency_symbol',
'transaction_types.type as transaction_type_type',
'transaction_journals.bill_id',
'bills.name as bill_name',
'transactions.id as id',
'transactions.amount as transaction_amount',
'transactions.description as transaction_description',
'transactions.account_id',
'transactions.identifier',
'transactions.transaction_journal_id',
'accounts.name as account_name',
'accounts.encrypted as account_encrypted',
'account_types.type as account_type',
]
);
// loop for decryption.
$set->each(
function (Transaction $transaction) {
$transaction->date = new Carbon($transaction->date);
$transaction->description = intval($transaction->encrypted) === 1 ? Crypt::decrypt($transaction->description) : $transaction->description;
$transaction->bill_name = !is_null($transaction->bill_name) ? Crypt::decrypt($transaction->bill_name) : '';
}
);
return $set;
}
/** /**
* @param Collection $accounts * @param Collection $accounts
* @param Collection $excluded * @param Collection $excluded
@@ -328,7 +257,6 @@ class AccountTasker implements AccountTaskerInterface
$join->on('transaction_journals.id', '=', 'other_side.transaction_journal_id')->where('other_side.amount', $joinModifier, 0); $join->on('transaction_journals.id', '=', 'other_side.transaction_journal_id')->where('other_side.amount', $joinModifier, 0);
} }
) )
->where('transaction_journals.date', '>=', $start->format('Y-m-d')) ->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d')) ->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->where('transaction_journals.user_id', $this->user->id) ->where('transaction_journals.user_id', $this->user->id)
@@ -384,7 +312,7 @@ class AccountTasker implements AccountTaskerInterface
} }
) )
->leftJoin('accounts as other_account', 'other_account.id', '=', 'other_side.account_id') ->leftJoin('accounts as other_account', 'other_account.id', '=', 'other_side.account_id')
->where('transaction_types.type','!=', TransactionType::OPENING_BALANCE) ->where('transaction_types.type', '!=', TransactionType::OPENING_BALANCE)
->where('transaction_journals.date', '>=', $start->format('Y-m-d')) ->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d')) ->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->where('transaction_journals.user_id', $this->user->id) ->where('transaction_journals.user_id', $this->user->id)

View File

@@ -71,18 +71,6 @@ interface AccountTaskerInterface
*/ */
public function getAccountReport(Carbon $start, Carbon $end, Collection $accounts): AccountCollection; public function getAccountReport(Carbon $start, Carbon $end, Collection $accounts): AccountCollection;
/**
* Experimental getJournals method.
*
* @param Collection $accounts
* @param array $types
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getJournalsInPeriod(Collection $accounts, array $types, Carbon $start, Carbon $end): Collection;
/** /**
* @param Collection $accounts * @param Collection $accounts
* @param Collection $excluded * @param Collection $excluded

View File

@@ -22,7 +22,6 @@ use FireflyIII\Models\TransactionType;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Database\Query\JoinClause; use Illuminate\Database\Query\JoinClause;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Log; use Log;
use Navigation; use Navigation;
@@ -116,41 +115,6 @@ class BillRepository implements BillRepositoryInterface
return $set; return $set;
} }
/**
* Returns all journals connected to these bills in the given range. Amount paid
* is stored in "journalAmount" as a negative number.
*
* @param Collection $bills
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getAllJournalsInRange(Collection $bills, Carbon $start, Carbon $end): Collection
{
$ids = $bills->pluck('id')->toArray();
$set = $this->user->transactionJournals()
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0);
}
)
->whereIn('bill_id', $ids)
->before($end)
->after($start)
->groupBy(['transaction_journals.bill_id', 'transaction_journals.id'])
->get(
[
'transaction_journals.bill_id',
'transaction_journals.id',
DB::raw('SUM(transactions.amount) AS journalAmount'),
]
);
return $set;
}
/** /**
* @return Collection * @return Collection
*/ */
@@ -287,30 +251,6 @@ class BillRepository implements BillRepositoryInterface
return $sum; return $sum;
} }
/**
* This method also returns the amount of the journal in "journalAmount"
* for easy access.
*
* @param Bill $bill
*
* @param int $page
* @param int $pageSize
*
* @return LengthAwarePaginator|Collection
*/
public function getJournals(Bill $bill, int $page, int $pageSize = 50): LengthAwarePaginator
{
$offset = ($page - 1) * $pageSize;
$query = $bill->transactionJournals()
->expanded()
->sortCorrectly();
$count = $query->count();
$set = $query->take($pageSize)->offset($offset)->get(TransactionJournal::queryFields());
$paginator = new LengthAwarePaginator($set, $count, $pageSize, $page);
return $paginator;
}
/** /**
* @param Bill $bill * @param Bill $bill
* *

View File

@@ -16,7 +16,6 @@ namespace FireflyIII\Repositories\Bill;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
/** /**
@@ -57,18 +56,6 @@ interface BillRepositoryInterface
*/ */
public function getActiveBills(): Collection; public function getActiveBills(): Collection;
/**
* Returns all journals connected to these bills in the given range. Amount paid
* is stored in "journalAmount" as a negative number.
*
* @param Collection $bills
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getAllJournalsInRange(Collection $bills, Carbon $start, Carbon $end): Collection;
/** /**
* @return Collection * @return Collection
*/ */
@@ -103,16 +90,6 @@ interface BillRepositoryInterface
*/ */
public function getBillsUnpaidInRange(Carbon $start, Carbon $end): string; public function getBillsUnpaidInRange(Carbon $start, Carbon $end): string;
/**
* @param Bill $bill
*
* @param int $page
* @param int $pageSize
*
* @return LengthAwarePaginator
*/
public function getJournals(Bill $bill, int $page, int $pageSize = 50): LengthAwarePaginator;
/** /**
* @param Bill $bill * @param Bill $bill
* *

View File

@@ -24,7 +24,6 @@ use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Query\JoinClause; use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Log; use Log;
@@ -210,135 +209,6 @@ class BudgetRepository implements BudgetRepositoryInterface
return $set; return $set;
} }
/**
* @param Collection $budgets
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function journalsInPeriod(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): Collection
{
$return = new Collection;
$accountIds = [];
// expand the number of grabbed fields:
$fields = TransactionJournal::queryFields();
$fields[] = 'source.account_id';
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
}
// first get all journals for all budget(s):
$journalQuery = $this->user->transactionJournals()
->expanded()
->sortCorrectly()
->before($end)
->after($start)
->leftJoin(
'transactions as source',
function (JoinClause $join) {
$join->on('source.transaction_journal_id', '=', 'transaction_journals.id')->where('source.amount', '<', '0');
}
)
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->whereIn('budget_transaction_journal.budget_id', $budgets->pluck('id')->toArray());
// add account id's, if relevant:
if (count($accountIds) > 0) {
$journalQuery->whereIn('source.account_id', $accountIds);
}
// get them:
$journals = $journalQuery->get(TransactionJournal::queryFields());
// then get transactions themselves.
$transactionQuery = $this->user->transactionJournals()
->expanded()
->before($end)
->sortCorrectly()
->after($start)
->leftJoin('transactions as related', 'related.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budget_transaction', 'budget_transaction.transaction_id', '=', 'related.id')
->leftJoin(
'transactions as source',
function (JoinClause $join) {
$join->on('source.transaction_journal_id', '=', 'transaction_journals.id')->where('source.amount', '<', '0');
}
)
->groupBy(['source.account_id'])
->whereIn('budget_transaction.budget_id', $budgets->pluck('id')->toArray());
if (count($accountIds) > 0) {
$transactionQuery->whereIn('source.account_id', $accountIds);
}
$transactions = $transactionQuery->get($fields);
// return complete set:
$return = $return->merge($transactions);
$return = $return->merge($journals);
return $return;
}
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function journalsInPeriodWithoutBudget(Collection $accounts, Carbon $start, Carbon $end): Collection
{
$accountIds = [];
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
}
/** @var Collection $set */
$query = $this->user
->transactionJournals()
->expanded()
->sortCorrectly()
->transactionTypes([TransactionType::WITHDRAWAL])
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->whereNull('budget_transaction_journal.id')
->leftJoin(
'transactions as source',
function (JoinClause $join) {
$join->on('source.transaction_journal_id', '=', 'transaction_journals.id')->where('source.amount', '<', '0');
}
)
->before($end)
->after($start)->with(
[
'transactions' => function (HasMany $query) {
$query->where('transactions.amount', '<', 0);
},
'transactions.budgets',
]
);
// add account id's, if relevant:
if (count($accountIds) > 0) {
$query->whereIn('source.account_id', $accountIds);
}
$set = $query->get(TransactionJournal::queryFields());
$set = $set->filter(
function (TransactionJournal $journal) {
foreach ($journal->transactions as $t) {
if ($t->budgets->count() === 0) {
return true;
}
}
return false;
}
);
return $set;
}
/** /**
* @param Collection $budgets * @param Collection $budgets
* @param Collection $accounts * @param Collection $accounts
@@ -350,8 +220,8 @@ class BudgetRepository implements BudgetRepositoryInterface
public function spentInPeriod(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end) : string public function spentInPeriod(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end) : string
{ {
// collect amount of transaction journals, which is easy: // collect amount of transaction journals, which is easy:
$budgetIds = $budgets->pluck('id')->toArray(); $budgetIds = $budgets->pluck('id')->toArray();
$accountIds = $accounts->pluck('id')->toArray(); $accountIds = $accounts->pluck('id')->toArray();
Log::debug('spentInPeriod: Now in spentInPeriod for these budgets: ', $budgetIds); Log::debug('spentInPeriod: Now in spentInPeriod for these budgets: ', $budgetIds);
Log::debug('spentInPeriod: and these accounts: ', $accountIds); Log::debug('spentInPeriod: and these accounts: ', $accountIds);

View File

@@ -89,25 +89,6 @@ interface BudgetRepositoryInterface
*/ */
public function getInactiveBudgets(): Collection; public function getInactiveBudgets(): Collection;
/**
* @param Collection $budgets
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function journalsInPeriod(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): Collection;
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function journalsInPeriodWithoutBudget(Collection $accounts, Carbon $start, Carbon $end): Collection;
/** /**
* @param Collection $budgets * @param Collection $budgets
* @param Collection $accounts * @param Collection $accounts

View File

@@ -20,7 +20,6 @@ use FireflyIII\Models\TransactionType;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\JoinClause; use Illuminate\Database\Query\JoinClause;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
/** /**
@@ -174,176 +173,6 @@ class CategoryRepository implements CategoryRepositoryInterface
return $set; return $set;
} }
/**
* @param Category $category
* @param int $page
* @param int $pageSize
*
* @return LengthAwarePaginator
*/
public function getJournals(Category $category, int $page, int $pageSize): LengthAwarePaginator
{
$complete = new Collection;
// first collect actual transaction journals (fairly easy)
$query = $this->user->transactionJournals()->expanded()->sortCorrectly();
$query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
$query->where('category_transaction_journal.category_id', $category->id);
$first = $query->get(TransactionJournal::queryFields());
// then collection transactions (harder)
$query = $this->user->transactionJournals()->distinct()
->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id')
->where('category_transaction.category_id', $category->id);
$second = $query->get(['transaction_journals.*']);
$complete = $complete->merge($first);
$complete = $complete->merge($second);
// sort:
/** @var Collection $complete */
$complete = $complete->sortByDesc(
function ($model) {
$date = new Carbon($model->date);
return intval($date->format('U'));
}
);
// create paginator
$offset = ($page - 1) * $pageSize;
$subSet = $complete->slice($offset, $pageSize)->all();
$paginator = new LengthAwarePaginator($subSet, $complete->count(), $pageSize, $page);
return $paginator;
}
/**
* Get all transactions in a category in a range.
*
* @param Collection $categories
* @param Collection $accounts
* @param array $types
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function journalsInPeriod(Collection $categories, Collection $accounts, array $types, Carbon $start, Carbon $end): Collection
{
$complete = new Collection;
// first collect actual transaction journals (fairly easy)
$query = $this->user->transactionJournals()->expanded()->sortCorrectly();
if ($end >= $start) {
$query->before($end)->after($start);
}
if (count($types) > 0) {
$query->transactionTypes($types);
}
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
$query->leftJoin('transactions as t', 't.transaction_journal_id', '=', 'transaction_journals.id');
$query->whereIn('t.account_id', $accountIds);
}
if ($categories->count() > 0) {
$categoryIds = $categories->pluck('id')->toArray();
$query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
$query->whereIn('category_transaction_journal.category_id', $categoryIds);
}
// that should do it:
$first = $query->get(TransactionJournal::queryFields());
// then collection transactions (harder)
$query = $this->user->transactionJournals()->distinct()
->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id');
if (count($types) > 0) {
$query->whereIn('transaction_types.type', $types);
}
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
$query->whereIn('transactions.account_id', $accountIds);
}
if ($categories->count() > 0) {
$categoryIds = $categories->pluck('id')->toArray();
$query->whereIn('category_transaction.category_id', $categoryIds);
}
$second = $query->get(['transaction_journals.*', 'transaction_types.type as transaction_type_type']);
$complete = $complete->merge($first);
$complete = $complete->merge($second);
return $complete;
}
/**
* @param Collection $accounts
* @param array $types
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function journalsInPeriodWithoutCategory(Collection $accounts, array $types, Carbon $start, Carbon $end) : Collection
{
/** @var Collection $set */
$query = $this->user
->transactionJournals();
if (count($types) > 0) {
$query->transactionTypes($types);
}
$query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->whereNull('category_transaction_journal.id')
->before($end)
->after($start);
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
$query->leftJoin('transactions as t', 't.transaction_journal_id', '=', 'transaction_journals.id');
$query->whereIn('t.account_id', $accountIds);
}
$set = $query->get(['transaction_journals.*']);
if ($set->count() == 0) {
return new Collection;
}
// grab all the transactions from this set.
// take only the journals with transactions that all have no category.
// select transactions left join journals where id in this set
// and left join transaction-category where null category
$journalIds = $set->pluck('id')->toArray();
$secondQuery = $this->user->transactions()
->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id')
->whereNull('category_transaction.id')
->whereIn('transaction_journals.id', $journalIds);
if ($accounts->count() > 0) {
$accountIds = $accounts->pluck('id')->toArray();
$secondQuery->whereIn('transactions.account_id', $accountIds);
}
// this second set REALLY doesn't have any categories.
$secondSet = $secondQuery->get(['transactions.transaction_journal_id']);
$allIds = $secondSet->pluck('transaction_journal_id')->toArray();
$return = $this->user->transactionJournals()->sortCorrectly()->expanded()->whereIn('transaction_journals.id', $allIds)->get(
TransactionJournal::queryFields()
);
return $return;
}
/** /**
* @param Category $category * @param Category $category
* @param Collection $accounts * @param Collection $accounts

View File

@@ -15,7 +15,6 @@ namespace FireflyIII\Repositories\Category;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
/** /**
@@ -84,36 +83,6 @@ interface CategoryRepositoryInterface
*/ */
public function getCategories(): Collection; public function getCategories(): Collection;
/**
* @param Category $category
* @param int $page
* @param int $pageSize
*
* @return LengthAwarePaginator
*/
public function getJournals(Category $category, int $page, int $pageSize): LengthAwarePaginator;
/**
* @param Collection $categories
* @param Collection $accounts
* @param array $types
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function journalsInPeriod(Collection $categories, Collection $accounts, array $types, Carbon $start, Carbon $end): Collection;
/**
* @param Collection $accounts
* @param array $types
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function journalsInPeriodWithoutCategory(Collection $accounts, array $types, Carbon $start, Carbon $end) : Collection;
/** /**
* Return most recent transaction(journal) date. * Return most recent transaction(journal) date.
* *

View File

@@ -458,7 +458,7 @@ class JournalRepository implements JournalRepositoryInterface
*/ */
private function storeBudgetWithJournal(TransactionJournal $journal, int $budgetId) private function storeBudgetWithJournal(TransactionJournal $journal, int $budgetId)
{ {
if (intval($budgetId) > 0 && $journal->transactionType->type !== TransactionType::TRANSFER) { if (intval($budgetId) > 0 && $journal->transactionType->type === TransactionType::WITHDRAWAL) {
/** @var \FireflyIII\Models\Budget $budget */ /** @var \FireflyIII\Models\Budget $budget */
$budget = Budget::find($budgetId); $budget = Budget::find($budgetId);
$journal->budgets()->save($budget); $journal->budgets()->save($budget);

View File

@@ -26,6 +26,16 @@ use Illuminate\Support\MessageBag;
interface JournalRepositoryInterface interface JournalRepositoryInterface
{ {
/**
* @param TransactionJournal $journal
* @param TransactionType $type
* @param Account $source
* @param Account $destination
*
* @return MessageBag
*/
public function convert(TransactionJournal $journal, TransactionType $type, Account $source, Account $destination): MessageBag;
/** /**
* Deletes a journal. * Deletes a journal.
* *
@@ -35,15 +45,6 @@ interface JournalRepositoryInterface
*/ */
public function delete(TransactionJournal $journal): bool; public function delete(TransactionJournal $journal): bool;
/**
* @param TransactionJournal $journal
* @param TransactionType $type
* @param array $data
*
* @return MessageBag
*/
public function convert(TransactionJournal $journal, TransactionType $type, Account $source, Account $destination): MessageBag;
/** /**
* Find a specific journal * Find a specific journal
* *

View File

@@ -46,73 +46,6 @@ class JournalTasker implements JournalTaskerInterface
$this->user = $user; $this->user = $user;
} }
/**
* Returns a page of a specific type(s) of journal.
*
* @param array $types
* @param int $page
* @param int $pageSize
*
* @return LengthAwarePaginator
*/
public function getJournals(array $types, int $page, int $pageSize = 50): LengthAwarePaginator
{
$offset = ($page - 1) * $pageSize;
$query = $this->user->transactionJournals()->expanded()->sortCorrectly();
$query->where('transaction_journals.completed', 1);
if (count($types) > 0) {
$query->transactionTypes($types);
}
$count = $this->user->transactionJournals()->transactionTypes($types)->count();
$set = $query->take($pageSize)->offset($offset)->get(TransactionJournal::queryFields());
$journals = new LengthAwarePaginator($set, $count, $pageSize, $page);
return $journals;
}
/**
* Returns a collection of ALL journals, given a specific account and a date range.
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getJournalsInRange(Collection $accounts, Carbon $start, Carbon $end): Collection
{
$query = $this->user->transactionJournals()->expanded()->sortCorrectly();
$query->where('transaction_journals.completed', 1);
$query->before($end);
$query->after($start);
if ($accounts->count() > 0) {
$ids = $accounts->pluck('id')->toArray();
// join source and destination:
$query->leftJoin(
'transactions as source', function (JoinClause $join) {
$join->on('source.transaction_journal_id', '=', 'transaction_journals.id')->where('source.amount', '<', 0);
}
);
$query->leftJoin(
'transactions as destination', function (JoinClause $join) {
$join->on('destination.transaction_journal_id', '=', 'transaction_journals.id')->where('destination.amount', '>', 0);
}
);
$query->where(
function (Builder $q) use ($ids) {
$q->whereIn('destination.account_id', $ids);
$q->orWhereIn('source.account_id', $ids);
}
);
}
$set = $query->get(TransactionJournal::queryFields());
return $set;
}
/** /**
* @param TransactionJournal $journal * @param TransactionJournal $journal
* *

View File

@@ -26,27 +26,6 @@ use Illuminate\Support\Collection;
*/ */
interface JournalTaskerInterface interface JournalTaskerInterface
{ {
/**
* Returns a page of a specific type(s) of journal.
*
* @param array $types
* @param int $page
* @param int $pageSize
*
* @return LengthAwarePaginator
*/
public function getJournals(array $types, int $page, int $pageSize = 50): LengthAwarePaginator;
/**
* Returns a collection of ALL journals, given a specific account and a date range.
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getJournalsInRange(Collection $accounts, Carbon $start, Carbon $end): Collection;
/** /**
* @param TransactionJournal $journal * @param TransactionJournal $journal

View File

@@ -133,24 +133,6 @@ class TagRepository implements TagRepositoryInterface
return $tags; return $tags;
} }
/**
* @param Tag $tag
*
* @return Collection
*/
public function getJournals(Tag $tag) : Collection
{
/** @var Collection $journals */
$journals = $tag
->transactionJournals()
->sortCorrectly()
->expanded()
->groupBy(['tag_transaction_journal.tag_id', 'tag_transaction_journal.transaction_journal_id'])
->get(TransactionJournal::queryFields());
return $journals;
}
/** /**
* @param array $data * @param array $data
* *

View File

@@ -65,13 +65,6 @@ interface TagRepositoryInterface
*/ */
public function get(): Collection; public function get(): Collection;
/**
* @param Tag $tag
*
* @return Collection
*/
public function getJournals(Tag $tag) : Collection;
/** /**
* This method stores a tag. * This method stores a tag.
* *

View File

@@ -16,6 +16,7 @@ namespace FireflyIII\Rules\Actions;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use Log;
/** /**
* Class ClearCategory * Class ClearCategory

View File

@@ -16,6 +16,7 @@ namespace FireflyIII\Rules;
use FireflyIII\Models\Rule; use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Models\RuleTrigger; use FireflyIII\Models\RuleTrigger;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Rules\Actions\ActionInterface; use FireflyIII\Rules\Actions\ActionInterface;
use FireflyIII\Rules\Factory\ActionFactory; use FireflyIII\Rules\Factory\ActionFactory;
@@ -144,6 +145,36 @@ final class Processor
return $this->rule; return $this->rule;
} }
/**
* This method will scan the given transaction journal and check if it matches the triggers found in the Processor
* If so, it will also attempt to run the given actions on the journal. It returns a bool indicating if the transaction journal
* matches all of the triggers (regardless of whether the Processor could act on it).
*
* @param Transaction $transaction
*
* @return bool
*/
public function handleTransaction(Transaction $transaction): bool
{
Log::debug(sprintf('handleTransactionJournal for journal #%d (transaction #%d)', $transaction->transaction_journal_id, $transaction->id));
// grab the actual journal.
$journal = $transaction->transactionJournal()->first();
$this->journal = $journal;
// get all triggers:
$triggered = $this->triggered();
if ($triggered) {
if ($this->actions->count() > 0) {
$this->actions();
}
return true;
}
return false;
}
/** /**
* This method will scan the given transaction journal and check if it matches the triggers found in the Processor * This method will scan the given transaction journal and check if it matches the triggers found in the Processor
* If so, it will also attempt to run the given actions on the journal. It returns a bool indicating if the transaction journal * If so, it will also attempt to run the given actions on the journal. It returns a bool indicating if the transaction journal

View File

@@ -13,7 +13,8 @@ declare(strict_types = 1);
namespace FireflyIII\Rules; namespace FireflyIII\Rules;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Journal\JournalTaskerInterface; use FireflyIII\Repositories\Journal\JournalTaskerInterface;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@@ -62,7 +63,7 @@ class TransactionMatcher
if (count($this->triggers) === 0) { if (count($this->triggers) === 0) {
return new Collection; return new Collection;
} }
$pagesize = min($this->range / 2, $this->limit * 2); $pageSize = min($this->range / 2, $this->limit * 2);
// Variables used within the loop // Variables used within the loop
$processed = 0; $processed = 0;
@@ -76,31 +77,42 @@ class TransactionMatcher
// - the maximum number of transactions to search in have been searched // - the maximum number of transactions to search in have been searched
do { do {
// Fetch a batch of transactions from the database // Fetch a batch of transactions from the database
$paginator = $this->tasker->getJournals($this->transactionTypes, $page, $pagesize); $collector = new JournalCollector(auth()->user());
$set = $paginator->getCollection(); $collector->setAllAssetAccounts()->setLimit($pageSize)->setPage($page)->setTypes($this->transactionTypes);
$set = $collector->getPaginatedJournals();
Log::debug(sprintf('Found %d journals to check. ', $set->count()));
// Filter transactions that match the given triggers. // Filter transactions that match the given triggers.
$filtered = $set->filter( $filtered = $set->filter(
function (TransactionJournal $journal) use ($processor) { function (Transaction $transaction) use ($processor) {
Log::debug(sprintf('Test these triggers on #%d', $journal->id)); Log::debug(sprintf('Test these triggers on journal #%d (transaction #%d)', $transaction->transaction_journal_id, $transaction->id));
return $processor->handleTransactionJournal($journal); return $processor->handleTransaction($transaction);
} }
); );
Log::debug(sprintf('Found %d journals that match.', $filtered->count()));
// merge: // merge:
/** @var Collection $result */ /** @var Collection $result */
$result = $result->merge($filtered); $result = $result->merge($filtered);
Log::debug(sprintf('Total count is now %d', $result->count()));
// Update counters // Update counters
$page++; $page++;
$processed += count($set); $processed += count($set);
Log::debug(sprintf('Page is now %d, processed is %d', $page, $processed));
// Check for conditions to finish the loop // Check for conditions to finish the loop
$reachedEndOfList = $set->count() < $pagesize; $reachedEndOfList = $set->count() < 1;
$foundEnough = $result->count() >= $this->limit; $foundEnough = $result->count() >= $this->limit;
$searchedEnough = ($processed >= $this->range); $searchedEnough = ($processed >= $this->range);
Log::debug(sprintf('reachedEndOfList: %s', var_export($reachedEndOfList, true)));
Log::debug(sprintf('foundEnough: %s', var_export($foundEnough, true)));
Log::debug(sprintf('searchedEnough: %s', var_export($searchedEnough, true)));
} while (!$reachedEndOfList && !$foundEnough && !$searchedEnough); } while (!$reachedEndOfList && !$foundEnough && !$searchedEnough);
// If the list of matchingTransactions is larger than the maximum number of results // If the list of matchingTransactions is larger than the maximum number of results

View File

@@ -59,14 +59,14 @@ class Amount
if ($coloured === true) { if ($coloured === true) {
if ($amount > 0) { if ($amount > 0) {
return '<span class="text-success" title="' . e($float) . '">' . $result . '</span>'; return sprintf('<span class="text-success">%s</span>', $result);
} else { } else {
if ($amount < 0) { if ($amount < 0) {
return '<span class="text-danger" title="' . e($float) . '">' . $result . '</span>'; return sprintf('<span class="text-danger">%s</span>', $result);
} }
} }
return '<span style="color:#999" title="' . e($float) . '">' . $result . '</span>'; return sprintf('<span style="color:#999">%s</span>', $result);
} }
@@ -139,14 +139,14 @@ class Amount
if ($coloured === true) { if ($coloured === true) {
if ($amount > 0) { if ($amount > 0) {
return '<span class="text-success" title="' . e($float) . '">' . $result . '</span>'; return sprintf('<span class="text-success">%s</span>', $result);
} else { } else {
if ($amount < 0) { if ($amount < 0) {
return '<span class="text-danger" title="' . e($float) . '">' . $result . '</span>'; return sprintf('<span class="text-danger">%s</span>', $result);
} }
} }
return '<span style="color:#999" title="' . e($float) . '">' . $result . '</span>'; return sprintf('<span style="color:#999">%s</span>', $result);
} }

View File

@@ -54,7 +54,7 @@ class Navigation
]; ];
if (!isset($functionMap[$repeatFreq])) { if (!isset($functionMap[$repeatFreq])) {
throw new FireflyException('Cannot do addPeriod for $repeat_freq "' . $repeatFreq . '"'); throw new FireflyException(sprintf('Cannot do addPeriod for $repeat_freq "%s"', $repeatFreq));
} }
if (isset($modifierMap[$repeatFreq])) { if (isset($modifierMap[$repeatFreq])) {
$add = $add * $modifierMap[$repeatFreq]; $add = $add * $modifierMap[$repeatFreq];
@@ -108,7 +108,7 @@ class Navigation
} }
if (!isset($functionMap[$repeatFreq])) { if (!isset($functionMap[$repeatFreq])) {
throw new FireflyException('Cannot do endOfPeriod for $repeat_freq "' . $repeatFreq . '"'); throw new FireflyException(sprintf('Cannot do endOfPeriod for $repeat_freq "%s"', $repeatFreq));
} }
$function = $functionMap[$repeatFreq]; $function = $functionMap[$repeatFreq];
if (isset($modifierMap[$repeatFreq])) { if (isset($modifierMap[$repeatFreq])) {
@@ -202,7 +202,7 @@ class Navigation
if (isset($formatMap[$repeatFrequency])) { if (isset($formatMap[$repeatFrequency])) {
return $date->formatLocalized(strval($formatMap[$repeatFrequency])); return $date->formatLocalized(strval($formatMap[$repeatFrequency]));
} }
throw new FireflyException('No date formats for frequency "' . $repeatFrequency . '"!'); throw new FireflyException(sprintf('No date formats for frequency "%s"!', $repeatFrequency));
} }
/** /**
@@ -252,7 +252,7 @@ class Navigation
} }
throw new FireflyException('Cannot do startOfPeriod for $repeat_freq "' . $repeatFreq . '"'); throw new FireflyException(sprintf('Cannot do startOfPeriod for $repeat_freq "%s"', $repeatFreq));
} }
/** /**
@@ -313,7 +313,7 @@ class Navigation
return $date; return $date;
} }
throw new FireflyException('Cannot do subtractPeriod for $repeat_freq "' . $repeatFreq . '"'); throw new FireflyException(sprintf('Cannot do subtractPeriod for $repeat_freq "%s"', $repeatFreq));
} }
/** /**
@@ -350,7 +350,7 @@ class Navigation
return $end; return $end;
} }
throw new FireflyException('updateEndDate cannot handle $range "' . $range . '"'); throw new FireflyException(sprintf('updateEndDate cannot handle range "%s"', $range));
} }
/** /**
@@ -387,7 +387,7 @@ class Navigation
} }
throw new FireflyException('updateStartDate cannot handle $range "' . $range . '"'); throw new FireflyException(sprintf('updateStartDate cannot handle range "%s"', $range));
} }

View File

@@ -32,7 +32,7 @@ class Preferences
*/ */
public function delete($name): bool public function delete($name): bool
{ {
$fullName = 'preference' . auth()->user()->id . $name; $fullName = sprintf('preference%s%s', auth()->user()->id, $name);
if (Cache::has($fullName)) { if (Cache::has($fullName)) {
Cache::forget($fullName); Cache::forget($fullName);
} }
@@ -66,7 +66,7 @@ class Preferences
*/ */
public function getForUser(User $user, $name, $default = null) public function getForUser(User $user, $name, $default = null)
{ {
$fullName = 'preference' . $user->id . $name; $fullName = sprintf('preference%s%s', $user->id, $name);
if (Cache::has($fullName)) { if (Cache::has($fullName)) {
return Cache::get($fullName); return Cache::get($fullName);
} }
@@ -138,7 +138,7 @@ class Preferences
*/ */
public function setForUser(User $user, $name, $value): Preference public function setForUser(User $user, $name, $value): Preference
{ {
$fullName = 'preference' . $user->id . $name; $fullName = sprintf('preference%s%s', $user->id, $name);
Cache::forget($fullName); Cache::forget($fullName);
$pref = Preference::where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data']); $pref = Preference::where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data']);

View File

@@ -14,11 +14,15 @@ declare(strict_types = 1);
namespace FireflyIII\Support\Search; namespace FireflyIII\Support\Search;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\Tag;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use FireflyIII\Models\Transaction;
use FireflyIII\User;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Log;
/** /**
* Class Search * Class Search
@@ -27,20 +31,46 @@ use Illuminate\Support\Collection;
*/ */
class Search implements SearchInterface class Search implements SearchInterface
{ {
/** @var int */
private $limit = 100;
/** @var User */
private $user;
/** /**
* AttachmentRepository constructor.
*
* @param User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* The search will assume that the user does not have so many accounts
* that this search should be paginated.
*
* @param array $words * @param array $words
* *
* @return Collection * @return Collection
*/ */
public function searchAccounts(array $words): Collection public function searchAccounts(array $words): Collection
{ {
return auth()->user()->accounts()->with('accounttype')->where( $accounts = $this->user->accounts()->get();
function (EloquentBuilder $q) use ($words) { /** @var Collection $result */
foreach ($words as $word) { $result = $accounts->filter(
$q->orWhere('name', 'LIKE', '%' . e($word) . '%'); function (Account $account) use ($words) {
if ($this->strpos_arr(strtolower($account->name), $words)) {
return $account;
} }
return false;
} }
)->get(); );
$result = $result->slice(0, $this->limit);
return $result;
} }
/** /**
@@ -51,46 +81,46 @@ class Search implements SearchInterface
public function searchBudgets(array $words): Collection public function searchBudgets(array $words): Collection
{ {
/** @var Collection $set */ /** @var Collection $set */
$set = auth()->user()->budgets()->get(); $set = auth()->user()->budgets()->get();
$newSet = $set->filter( /** @var Collection $result */
function (Budget $b) use ($words) { $result = $set->filter(
$found = 0; function (Budget $budget) use ($words) {
foreach ($words as $word) { if ($this->strpos_arr(strtolower($budget->name), $words)) {
if (!(strpos(strtolower($b->name), strtolower($word)) === false)) { return $budget;
$found++;
}
} }
return $found > 0; return false;
} }
); );
return $newSet; $result = $result->slice(0, $this->limit);
return $result;
} }
/** /**
* Search assumes the user does not have that many categories. So no paginated search.
*
* @param array $words * @param array $words
* *
* @return Collection * @return Collection
*/ */
public function searchCategories(array $words): Collection public function searchCategories(array $words): Collection
{ {
/** @var Collection $set */ $categories = $this->user->categories()->get();
$set = auth()->user()->categories()->get(); /** @var Collection $result */
$newSet = $set->filter( $result = $categories->filter(
function (Category $c) use ($words) { function (Category $category) use ($words) {
$found = 0; if ($this->strpos_arr(strtolower($category->name), $words)) {
foreach ($words as $word) { return $category;
if (!(strpos(strtolower($c->name), strtolower($word)) === false)) {
$found++;
}
} }
return $found > 0; return false;
} }
); );
$result = $result->slice(0, $this->limit);
return $newSet; return $result;
} }
/** /**
@@ -101,7 +131,21 @@ class Search implements SearchInterface
*/ */
public function searchTags(array $words): Collection public function searchTags(array $words): Collection
{ {
return new Collection; $tags = $this->user->tags()->get();
/** @var Collection $result */
$result = $tags->filter(
function (Tag $tag) use ($words) {
if ($this->strpos_arr(strtolower($tag->tag), $words)) {
return $tag;
}
return false;
}
);
$result = $result->slice(0, $this->limit);
return $result;
} }
/** /**
@@ -111,40 +155,86 @@ class Search implements SearchInterface
*/ */
public function searchTransactions(array $words): Collection public function searchTransactions(array $words): Collection
{ {
// decrypted transaction journals: $pageSize = 100;
$decrypted = auth()->user()->transactionJournals()->expanded()->where('transaction_journals.encrypted', 0)->where( $processed = 0;
function (EloquentBuilder $q) use ($words) { $page = 1;
foreach ($words as $word) { $result = new Collection();
$q->orWhere('transaction_journals.description', 'LIKE', '%' . e($word) . '%'); do {
} $collector = new JournalCollector($this->user);
} $collector->setAllAssetAccounts()->setLimit($pageSize)->setPage($page);
)->get(TransactionJournal::queryFields()); $set = $collector->getPaginatedJournals();
Log::debug(sprintf('Found %d journals to check. ', $set->count()));
// encrypted // Filter transactions that match the given triggers.
$all = auth()->user()->transactionJournals()->expanded()->where('transaction_journals.encrypted', 1)->get(TransactionJournal::queryFields()); $filtered = $set->filter(
$set = $all->filter( function (Transaction $transaction) use ($words) {
function (TransactionJournal $journal) use ($words) { // check descr of journal:
foreach ($words as $word) { if ($this->strpos_arr(strtolower(strval($transaction->description)), $words)) {
$haystack = strtolower($journal->description); return $transaction;
$word = strtolower($word);
if (!(strpos($haystack, $word) === false)) {
return $journal;
} }
// check descr of transaction
if ($this->strpos_arr(strtolower(strval($transaction->transaction_description)), $words)) {
return $transaction;
}
// return false:
return false;
} }
);
return null; Log::debug(sprintf('Found %d journals that match.', $filtered->count()));
// merge:
/** @var Collection $result */
$result = $result->merge($filtered);
Log::debug(sprintf('Total count is now %d', $result->count()));
// Update counters
$page++;
$processed += count($set);
Log::debug(sprintf('Page is now %d, processed is %d', $page, $processed));
// Check for conditions to finish the loop
$reachedEndOfList = $set->count() < 1;
$foundEnough = $result->count() >= $this->limit;
Log::debug(sprintf('reachedEndOfList: %s', var_export($reachedEndOfList, true)));
Log::debug(sprintf('foundEnough: %s', var_export($foundEnough, true)));
} while (!$reachedEndOfList && !$foundEnough);
$result = $result->slice(0, $this->limit);
return $result;
}
/**
* @param int $limit
*/
public function setLimit(int $limit)
{
$this->limit = $limit;
}
/**
* @param string $haystack
* @param array $needle
*
* @return bool
*/
private function strpos_arr(string $haystack, array $needle)
{
if (strlen($haystack) === 0) {
return false;
}
foreach ($needle as $what) {
if (($pos = strpos($haystack, $what)) !== false) {
return true;
} }
); }
$filtered = $set->merge($decrypted);
$filtered = $filtered->sortBy(
function (TransactionJournal $journal) {
return intval($journal->date->format('U'));
}
);
$filtered = $filtered->reverse(); return false;
return $filtered;
} }
} }

View File

@@ -146,7 +146,7 @@ class Journal extends Twig_Extension
$array[] = '<span class="text-success">(cash)</span>'; $array[] = '<span class="text-success">(cash)</span>';
continue; continue;
} }
$array[] = '<a title="' . e($entry->name) . '" href="' . route('accounts.show', $entry->id) . '">' . e($entry->name) . '</a>'; $array[] = sprintf('<a title="%1$s" href="%2$s">%1$s</a>', e($entry->name), route('accounts.show', $entry->id));
} }
$array = array_unique($array); $array = array_unique($array);
$result = join(', ', $array); $result = join(', ', $array);
@@ -221,7 +221,7 @@ class Journal extends Twig_Extension
$array[] = '<span class="text-success">(cash)</span>'; $array[] = '<span class="text-success">(cash)</span>';
continue; continue;
} }
$array[] = '<a title="' . e($entry->name) . '" href="' . route('accounts.show', $entry->id) . '">' . e($entry->name) . '</a>'; $array[] = sprintf('<a title="%1$s" href="%2$s">%1$s</a>', e($entry->name), route('accounts.show', $entry->id));
} }
$array = array_unique($array); $array = array_unique($array);
$result = join(', ', $array); $result = join(', ', $array);
@@ -253,12 +253,12 @@ class Journal extends Twig_Extension
$budgets = []; $budgets = [];
// get all budgets: // get all budgets:
foreach ($journal->budgets as $budget) { foreach ($journal->budgets as $budget) {
$budgets[] = '<a href="' . route('budgets.show', [$budget->id]) . '" title="' . e($budget->name) . '">' . e($budget->name) . '</a>'; $budgets[] = sprintf('<a title="%1$s" href="%2$s">%1$s</a>', e($budget->name), route('accounts.show', $budget->id));
} }
// and more! // and more!
foreach ($journal->transactions as $transaction) { foreach ($journal->transactions as $transaction) {
foreach ($transaction->budgets as $budget) { foreach ($transaction->budgets as $budget) {
$budgets[] = '<a href="' . route('budgets.show', [$budget->id]) . '" title="' . e($budget->name) . '">' . e($budget->name) . '</a>'; $budgets[] = sprintf('<a title="%1$s" href="%2$s">%1$s</a>', e($budget->name), route('accounts.show', $budget->id));
} }
} }
$string = join(', ', array_unique($budgets)); $string = join(', ', array_unique($budgets));
@@ -288,7 +288,7 @@ class Journal extends Twig_Extension
$categories = []; $categories = [];
// get all categories for the journal itself (easy): // get all categories for the journal itself (easy):
foreach ($journal->categories as $category) { foreach ($journal->categories as $category) {
$categories[] = '<a href="' . route('categories.show', [$category->id]) . '" title="' . e($category->name) . '">' . e($category->name) . '</a>'; $categories[] = sprintf('<a title="%1$s" href="%2$s">%1$s</a>', e($category->name), route('accounts.show', $category->id));
} }
if (count($categories) === 0) { if (count($categories) === 0) {
$set = Category::distinct()->leftJoin('category_transaction', 'categories.id', '=', 'category_transaction.category_id') $set = Category::distinct()->leftJoin('category_transaction', 'categories.id', '=', 'category_transaction.category_id')
@@ -299,8 +299,7 @@ class Journal extends Twig_Extension
->get(['categories.*']); ->get(['categories.*']);
/** @var Category $category */ /** @var Category $category */
foreach ($set as $category) { foreach ($set as $category) {
$categories[] = '<a href="' . route('categories.show', [$category->id]) . '" title="' . e($category->name) . '">' . e($category->name) $categories[] = sprintf('<a title="%1$s" href="%2$s">%1$s</a>', e($category->name), route('accounts.show', $category->id));
. '</a>';
} }
} }
@@ -324,16 +323,16 @@ class Journal extends Twig_Extension
switch (true) { switch (true) {
case $journal->isWithdrawal(): case $journal->isWithdrawal():
$txt = '<i class="fa fa-long-arrow-left fa-fw" title="' . trans('firefly.withdrawal') . '"></i>'; $txt = sprintf('<i class="fa fa-long-arrow-left fa-fw" title="%s"></i>', trans('firefly.withdrawal'));
break; break;
case $journal->isDeposit(): case $journal->isDeposit():
$txt = '<i class="fa fa-long-arrow-right fa-fw" title="' . trans('firefly.deposit') . '"></i>'; $txt = sprintf('<i class="fa fa-long-arrow-right fa-fw" title="%s"></i>', trans('firefly.deposit'));
break; break;
case $journal->isTransfer(): case $journal->isTransfer():
$txt = '<i class="fa fa-fw fa-exchange" title="' . trans('firefly.transfer') . '"></i>'; $txt = sprintf('<i class="fa fa-fw fa-exchange" title="%s"></i>', trans('firefly.transfer'));
break; break;
case $journal->isOpeningBalance(): case $journal->isOpeningBalance():
$txt = '<i class="fa-fw fa fa-ban" title="' . trans('firefly.openingBalance') . '"></i>'; $txt = sprintf('<i class="fa-fw fa fa-ban" title="%s"></i>', trans('firefly.openingBalance'));
break; break;
default: default:
$txt = ''; $txt = '';

View File

@@ -125,7 +125,7 @@ class Transaction extends Twig_Extension
&& bccomp($amount, bcmul($transactionAmount, '-1')) !== 0 && bccomp($amount, bcmul($transactionAmount, '-1')) !== 0
) { ) {
// not equal? // not equal?
return ' (' . Amount::formatWithCode($code, $amount, true) . ')'; return sprintf(' (%s)', Amount::formatWithCode($code, $amount, true));
} }
return ''; return '';
@@ -144,7 +144,7 @@ class Transaction extends Twig_Extension
'splitJournalIndicator', function (int $journalId) { 'splitJournalIndicator', function (int $journalId) {
$count = TransactionModel::where('transaction_journal_id', $journalId)->whereNull('deleted_at')->count(); $count = TransactionModel::where('transaction_journal_id', $journalId)->whereNull('deleted_at')->count();
if ($count > 2) { if ($count > 2) {
return '<i class="fa fa-fw fa-share-alt-square" aria-hidden="true"></i>'; return '<i class="fa fa-fw fa-share-alt" aria-hidden="true"></i>';
} }
return ''; return '';
@@ -210,7 +210,7 @@ class Transaction extends Twig_Extension
return '<span class="text-success">(cash)</span>'; return '<span class="text-success">(cash)</span>';
} }
return '<a title="' . e($name) . '" href="' . route('accounts.show', [$id]) . '">' . e($name) . '</a>'; return sprintf('<a title="%1$s" href="%2$s">%1$s</a>', e($name), route('accounts.show', [$id]));
}, ['is_safe' => ['html']] }, ['is_safe' => ['html']]
); );
@@ -276,7 +276,7 @@ class Transaction extends Twig_Extension
return '<span class="text-success">(cash)</span>'; return '<span class="text-success">(cash)</span>';
} }
return '<a title="' . e($name) . '" href="' . route('accounts.show', [$id]) . '">' . e($name) . '</a>'; return sprintf('<a title="%1$s" href="%2$s">%1$s</a>', e($name), route('accounts.show', [$id]));
}, ['is_safe' => ['html']] }, ['is_safe' => ['html']]
); );
@@ -294,16 +294,16 @@ class Transaction extends Twig_Extension
switch ($transaction->transaction_type_type) { switch ($transaction->transaction_type_type) {
case TransactionType::WITHDRAWAL: case TransactionType::WITHDRAWAL:
$txt = '<i class="fa fa-long-arrow-left fa-fw" title="' . trans('firefly.withdrawal') . '"></i>'; $txt = sprintf('<i class="fa fa-long-arrow-left fa-fw" title="%s"></i>', trans('firefly.withdrawal'));
break; break;
case TransactionType::DEPOSIT: case TransactionType::DEPOSIT:
$txt = '<i class="fa fa-long-arrow-right fa-fw" title="' . trans('firefly.deposit') . '"></i>'; $txt = sprintf('<i class="fa fa-long-arrow-right fa-fw" title="%s"></i>', trans('firefly.deposit'));
break; break;
case TransactionType::TRANSFER: case TransactionType::TRANSFER:
$txt = '<i class="fa fa-fw fa-exchange" title="' . trans('firefly.transfer') . '"></i>'; $txt = sprintf('<i class="fa fa-fw fa-exchange" title="%s"></i>', trans('firefly.transfer'));
break; break;
case TransactionType::OPENING_BALANCE: case TransactionType::OPENING_BALANCE:
$txt = '<i class="fa-fw fa fa-ban" title="' . trans('firefly.openingBalance') . '"></i>'; $txt = sprintf('<i class="fa-fw fa fa-ban" title="%s"></i>', trans('firefly.openingBalance'));
break; break;
default: default:
$txt = ''; $txt = '';

View File

@@ -35,7 +35,7 @@ class Translation extends Twig_Extension
$filters[] = new Twig_SimpleFilter( $filters[] = new Twig_SimpleFilter(
'_', function ($name) { '_', function ($name) {
return trans('firefly.' . $name); return strval(trans(sprintf('firefly.%s', $name)));
}, ['is_safe' => ['html']] }, ['is_safe' => ['html']]
); );

View File

@@ -71,6 +71,7 @@
], ],
"post-install-cmd": [ "post-install-cmd": [
"Illuminate\\Foundation\\ComposerScripts::postInstall", "Illuminate\\Foundation\\ComposerScripts::postInstall",
"php artisan firefly:github-move",
"php artisan optimize" "php artisan optimize"
], ],
"post-update-cmd": [ "post-update-cmd": [
@@ -78,6 +79,7 @@
"php artisan firefly:upgrade-instructions", "php artisan firefly:upgrade-instructions",
"php artisan firefly:upgrade-database", "php artisan firefly:upgrade-database",
"php artisan firefly:verify", "php artisan firefly:verify",
"php artisan firefly:github-move",
"php artisan optimize" "php artisan optimize"
] ]
}, },

2
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "cc3d23620e727ee1f4741b2e83f8685f", "hash": "12c9e9450c824d192b8c049989188b8e",
"content-hash": "473d3c681e5c41989e9dced651a939df", "content-hash": "473d3c681e5c41989e9dced651a939df",
"packages": [ "packages": [
{ {

View File

@@ -208,6 +208,7 @@ return [
FireflyIII\Providers\PiggyBankServiceProvider::class, FireflyIII\Providers\PiggyBankServiceProvider::class,
FireflyIII\Providers\RuleServiceProvider::class, FireflyIII\Providers\RuleServiceProvider::class,
FireflyIII\Providers\RuleGroupServiceProvider::class, FireflyIII\Providers\RuleGroupServiceProvider::class,
FireflyIII\Providers\SearchServiceProvider::class,
FireflyIII\Providers\TagServiceProvider::class, FireflyIII\Providers\TagServiceProvider::class,

View File

@@ -22,7 +22,7 @@ return [
'single_user_mode' => true, 'single_user_mode' => true,
], ],
'chart' => 'chartjs', 'chart' => 'chartjs',
'version' => '4.1.5', 'version' => '4.1.6',
'csv_import_enabled' => true, 'csv_import_enabled' => true,
'maxUploadSize' => 5242880, 'maxUploadSize' => 5242880,
'allowedMimes' => ['image/png', 'image/jpeg', 'application/pdf'], 'allowedMimes' => ['image/png', 'image/jpeg', 'application/pdf'],

View File

@@ -1,4 +1,4 @@
/* globals startDate, showOnlyTop, showFullList, endDate, reportType, accountIds, inOutReportUrl, accountReportUrl */ /* globals startDate, showOnlyTop, showFullList, endDate, reportType, expenseReportUri, accountIds, incExpReportUri,accountReportUri, incomeReportUri */
/* /*
* all.js * all.js
* Copyright (C) 2016 thegrumpydictator@gmail.com * Copyright (C) 2016 thegrumpydictator@gmail.com
@@ -11,25 +11,20 @@ $(function () {
"use strict"; "use strict";
// load the account report, which this report shows: // load the account report, which this report shows:
loadAccountReport(); loadAjaxPartial('accountReport', accountReportUri);
// load income / expense / difference: // load income and expense reports:
loadInOutReport(); loadAjaxPartial('incomeReport', incomeReportUri);
loadAjaxPartial('expenseReport', expenseReportUri);
// trigger info click loadAjaxPartial('incomeVsExpenseReport', incExpReportUri);
triggerInfoClick();
// trigger list length things:
listLengthInitial();
}); });
function triggerInfoClick() { function triggerInfoClick() {
"use strict"; "use strict";
// find the little info buttons and respond to them. // find the little info buttons and respond to them.
$('.firefly-info-button').unbind('clicl').click(clickInfoButton); $('.firefly-info-button').unbind('click').click(clickInfoButton);
} }
function listLengthInitial() { function listLengthInitial() {
@@ -58,44 +53,6 @@ function triggerList(e) {
return false; return false;
} }
function loadInOutReport() {
"use strict";
console.log('Going to grab ' + inOutReportUrl);
$.get(inOutReportUrl).done(placeInOutReport).fail(failInOutReport);
}
function placeInOutReport(data) {
"use strict";
$('#incomeReport').removeClass('loading').html(data.income);
$('#expenseReport').removeClass('loading').html(data.expenses);
$('#incomeVsExpenseReport').removeClass('loading').html(data.incomes_expenses);
listLengthInitial();
triggerInfoClick();
}
function failInOutReport() {
"use strict";
console.log('Fail in/out report data!');
$('#incomeReport').removeClass('loading').addClass('general-chart-error');
$('#expenseReport').removeClass('loading').addClass('general-chart-error');
$('#incomeVsExpenseReport').removeClass('loading').addClass('general-chart-error');
}
function loadAccountReport() {
"use strict";
$.get(accountReportUrl).done(placeAccountReport).fail(failAccountReport);
}
function placeAccountReport(data) {
"use strict";
$('#accountReport').removeClass('loading').html(data);
}
function failAccountReport(data) {
"use strict";
$('#accountReport').removeClass('loading').addClass('general-chart-error');
}
function clickInfoButton(e) { function clickInfoButton(e) {
"use strict"; "use strict";
// find all data tags, regardless of what they are: // find all data tags, regardless of what they are:
@@ -125,7 +82,111 @@ function respondInfoButton(data) {
"use strict"; "use strict";
// remove wait cursor // remove wait cursor
$('body').removeClass('waiting'); $('body').removeClass('waiting');
$('#defaultModal').empty().html(data.html); $('#defaultModal').empty().html(data.html).modal('show');
$('#defaultModal').modal('show');
}
function loadAjaxPartial(holder, uri) {
"use strict";
console.log('Going to grab URI ' + uri);
$.get(uri).done(function (data) {
displayAjaxPartial(data, holder);
}).fail(function () {
failAjaxPartial(uri, holder);
});
}
function displayAjaxPartial(data, holder) {
"use strict";
console.log('Display stuff in ' + holder);
var obj = $('#' + holder);
obj.removeClass('loading').html(data);
// call some often needed recalculations and what-not:
// find a sortable table and make it sortable:
if (typeof $.bootstrapSortable === "function") {
$.bootstrapSortable(true);
}
// find the info click things and respond to them:
triggerInfoClick();
// trigger list thing
listLengthInitial();
// budget thing
$('.budget-chart-activate').unbind('click').on('click', clickBudgetChart);
}
function failAjaxPartial(uri, holder) {
"use strict";
console.log('Failed to load' + uri);
$('#' + holder).removeClass('loading').addClass('general-chart-error');
}
function clickBudgetChart(e) {
"use strict";
var link = $(e.target);
var budgetId = link.data('budget');
var URL = 'chart/budget/period/' + budgetId + '/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds;
var container = 'budget_chart';
// if chart drawn is false, draw the first one, then
// set to true
if (chartDrawn == false) {
// do new chart:
$.getJSON(URL).done(function (data) {
console.log('Will draw new columnChart(' + URL + ')');
var ctx = document.getElementById(container).getContext("2d");
var newData = {};
newData.datasets = [];
for (var i = 0; i < data.count; i++) {
newData.labels = data.labels;
var dataset = data.datasets[i];
dataset.backgroundColor = fillColors[i];
newData.datasets.push(dataset);
}
// completely new chart.
budgetChart = new Chart(ctx, {
type: 'bar',
data: data,
options: defaultColumnOptions
});
}).fail(function () {
$('#' + container).addClass('general-chart-error');
});
console.log('URL for column chart : ' + URL);
chartDrawn = true;
} else {
console.log('Will now handle remove data and add new!');
$.getJSON(URL).done(function (data) {
console.log('Will draw updated columnChart(' + URL + ')');
var newData = {};
newData.datasets = [];
for (var i = 0; i < data.count; i++) {
newData.labels = data.labels;
var dataset = data.datasets[i];
dataset.backgroundColor = fillColors[i];
newData.datasets.push(dataset);
}
// update the chart
console.log('Now update chart thing.');
budgetChart.data.datasets = newData.datasets;
budgetChart.update();
}).fail(function () {
$('#' + container).addClass('general-chart-error');
});
}
return false;
} }

View File

@@ -1,74 +1,15 @@
/* globals google, budgetReportUrl, startDate ,reportURL, endDate , reportType ,accountIds, lineChart, categoryReportUrl, balanceReportUrl */ /* globals google, categoryReportUri, budgetReportUri, balanceReportUri */
$(function () { $(function () {
"use strict"; "use strict";
drawChart(); drawChart();
loadCategoryReport(); loadAjaxPartial('categoryReport', categoryReportUri);
loadBalanceReport(); loadAjaxPartial('budgetReport', budgetReportUri);
loadBudgetReport(); loadAjaxPartial('balanceReport',balanceReportUri);
}); });
function loadCategoryReport() {
"use strict";
console.log('Going to grab ' + categoryReportUrl);
$.get(categoryReportUrl).done(placeCategoryReport).fail(failCategoryReport);
}
function loadBudgetReport() {
"use strict";
console.log('Going to grab ' + budgetReportUrl);
$.get(budgetReportUrl).done(placeBudgetReport).fail(failBudgetReport);
}
function loadBalanceReport() {
"use strict";
console.log('Going to grab ' + categoryReportUrl);
$.get(balanceReportUrl).done(placeBalanceReport).fail(failBalanceReport);
}
function placeBudgetReport(data) {
"use strict";
$('#budgetReport').removeClass('loading').html(data);
listLengthInitial();
triggerInfoClick();
}
function placeBalanceReport(data) {
"use strict";
$('#balanceReport').removeClass('loading').html(data);
listLengthInitial();
triggerInfoClick();
}
function placeCategoryReport(data) {
"use strict";
$('#categoryReport').removeClass('loading').html(data);
listLengthInitial();
triggerInfoClick();
}
function failBudgetReport() {
"use strict";
console.log('Fail budget report data!');
$('#budgetReport').removeClass('loading').addClass('general-chart-error');
}
function failBalanceReport() {
"use strict";
console.log('Fail balance report data!');
$('#balanceReport').removeClass('loading').addClass('general-chart-error');
}
function failCategoryReport() {
"use strict";
console.log('Fail category report data!');
$('#categoryReport').removeClass('loading').addClass('general-chart-error');
}
function drawChart() { function drawChart() {
"use strict"; "use strict";

View File

@@ -1,13 +1,13 @@
/* globals google, startDate ,reportURL, endDate , reportType ,accountIds , picker:true, minDate, year, month, columnChart, lineChart, stackedColumnChart */ /* globals budgetMultiUri, accountIds */
$(function () { $(function () {
"use strict"; "use strict";
drawChart(); drawChart();
loadAjaxPartial('budgetMultiYear', budgetMultiUri);
}); });
function drawChart() { function drawChart() {
"use strict"; "use strict";

View File

@@ -1,4 +1,4 @@
/* globals google, accountIds, budgetYearOverviewUrl */ /* globals google, accountIds, budgetYearOverviewUri */
var chartDrawn; var chartDrawn;
var budgetChart; var budgetChart;
@@ -7,30 +7,9 @@ $(function () {
chartDrawn = false; chartDrawn = false;
drawChart(); drawChart();
// loadAjaxPartial('budgetOverview',budgetYearOverviewUri);
loadBudgetOverview();
}); });
function loadBudgetOverview() {
"use strict";
console.log('Going to grab ' + budgetYearOverviewUrl);
$.get(budgetYearOverviewUrl).done(placeBudgetOverview).fail(failBudgetOverview);
}
function placeBudgetOverview(data) {
"use strict";
$('#budgetOverview').removeClass('loading').html(data);
$('.budget-chart-activate').on('click', clickBudgetChart);
}
function failBudgetOverview() {
"use strict";
console.log('Fail budget overview data!');
$('#budgetOverview').removeClass('loading').addClass('general-chart-error');
}
function drawChart() { function drawChart() {
"use strict"; "use strict";
@@ -40,68 +19,3 @@ function drawChart() {
} }
function clickBudgetChart(e) {
"use strict";
var link = $(e.target);
var budgetId = link.data('budget');
var URL = 'chart/budget/period/' + budgetId + '/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds;
var container = 'budget_chart';
// if chart drawn is false, draw the first one, then
// set to true
if (chartDrawn == false) {
// do new chart:
$.getJSON(URL).done(function (data) {
console.log('Will draw new columnChart(' + URL + ')');
var ctx = document.getElementById(container).getContext("2d");
var newData = {};
newData.datasets = [];
for (var i = 0; i < data.count; i++) {
newData.labels = data.labels;
var dataset = data.datasets[i];
dataset.backgroundColor = fillColors[i];
newData.datasets.push(dataset);
}
// completely new chart.
budgetChart = new Chart(ctx, {
type: 'bar',
data: data,
options: defaultColumnOptions
});
}).fail(function () {
$('#' + container).addClass('general-chart-error');
});
console.log('URL for column chart : ' + URL);
chartDrawn = true;
} else {
console.log('Will now handle remove data and add new!');
$.getJSON(URL).done(function (data) {
console.log('Will draw updated columnChart(' + URL + ')');
var newData = {};
newData.datasets = [];
for (var i = 0; i < data.count; i++) {
newData.labels = data.labels;
var dataset = data.datasets[i];
dataset.backgroundColor = fillColors[i];
newData.datasets.push(dataset);
}
// update the chart
console.log('Now update chart thing.');
budgetChart.data.datasets = newData.datasets;
budgetChart.update();
}).fail(function () {
$('#' + container).addClass('general-chart-error');
});
}
return false;
}

View File

@@ -15,7 +15,7 @@ return [
'import_configure_title' => 'Konfigurieren Sie Ihren Import', 'import_configure_title' => 'Konfigurieren Sie Ihren Import',
'import_configure_intro' => 'Es gibt einige Optionen für Ihren CSV-Import. Bitte geben Sie an, ob Ihre CSV-Datei Überschriften in der ersten Spalte enthält und was das Datumsformat in Ihrem Datumsfeld ist. Dieses kann einige Experimente erfordern. Das Trennzeichen ist in der Regel ein ",", könnte aber auch ein "." sein. Bitte überprüfen Sie dieses sorgfältig.', 'import_configure_intro' => 'Es gibt einige Optionen für Ihren CSV-Import. Bitte geben Sie an, ob Ihre CSV-Datei Überschriften in der ersten Spalte enthält und was das Datumsformat in Ihrem Datumsfeld ist. Dieses kann einige Experimente erfordern. Das Trennzeichen ist in der Regel ein ",", könnte aber auch ein "." sein. Bitte überprüfen Sie dieses sorgfältig.',
'import_configure_form' => 'Formular', 'import_configure_form' => 'Basic CSV import options',
'header_help' => 'Hier auswählen, wenn die ersten Zeilen der CSV-Datei die Spaltenüberschriften sind', 'header_help' => 'Hier auswählen, wenn die ersten Zeilen der CSV-Datei die Spaltenüberschriften sind',
'date_help' => 'Datumsformat in ihrer CSV-Datei. Geben Sie das Format so an, wie es <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">diese Seite</a> zeigt. Die Standardeinstellung ergibt Daten die so aussehen: :dateExample.', 'date_help' => 'Datumsformat in ihrer CSV-Datei. Geben Sie das Format so an, wie es <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">diese Seite</a> zeigt. Die Standardeinstellung ergibt Daten die so aussehen: :dateExample.',
'delimiter_help' => 'Wählen Sie das Trennzeichen, welches in ihrer Datei genutzt wird. Wenn Sie nicht sicher sind ist Komma die sicherste Option.', 'delimiter_help' => 'Wählen Sie das Trennzeichen, welches in ihrer Datei genutzt wird. Wenn Sie nicht sicher sind ist Komma die sicherste Option.',
@@ -24,7 +24,6 @@ return [
// roles // roles
'column_roles_title' => 'Define column roles', 'column_roles_title' => 'Define column roles',
'column_roles_text' => '<p>Firefly III cannot guess what data each column contains. You must tell Firefly which kinds of data to expect. The example data can guide you into picking the correct type from the dropdown. If a column cannot be matched to a useful data type, please let me know <a href="https://github.com/JC5/firefly-iii/issues/new">by creating an issue</a>.</p><p>Some values in your CSV file, such as account names or categories, may already exist in your Firefly III database. If you select "map these values" Firefly will not attempt to search for matching values itself but allow you to match the CSV values against the values in your database. This allows you to fine-tune the import.</p>',
'column_roles_table' => 'Tabelle', 'column_roles_table' => 'Tabelle',
'column_name' => 'Name der Spalte', 'column_name' => 'Name der Spalte',
'column_example' => 'Column example data', 'column_example' => 'Column example data',

View File

@@ -67,11 +67,25 @@ return [
'warning_much_data' => ':days Tage an Daten können eine Weile dauern zu laden.', 'warning_much_data' => ':days Tage an Daten können eine Weile dauern zu laden.',
'registered' => 'Sie haben sich erfolgreich registriert!', 'registered' => 'Sie haben sich erfolgreich registriert!',
'search' => 'Suche', 'search' => 'Suche',
'search_found_accounts' => 'Found :count account(s) for your query.',
'search_found_categories' => 'Found :count category(ies) for your query.',
'search_found_budgets' => 'Found :count budget(s) for your query.',
'search_found_tags' => 'Found :count tag(s) for your query.',
'search_found_transactions' => 'Found :count transaction(s) for your query.',
'results_limited' => 'The results are limited to :count entries.',
'tagbalancingAct' => 'Balancing act',
'tagadvancePayment' => 'Advance payment',
'tagnothing' => '',
'Default asset account' => 'Default asset account',
'no_budget_pointer' => 'Sie scheinen keine Budgets festgelegt zu haben. Sie sollten welche auf der <a href="/budgets">Budget</a>-Seite erstellen. Budgets können Ihnen helfen ihre Ausgaben zu verfolgen.', 'no_budget_pointer' => 'Sie scheinen keine Budgets festgelegt zu haben. Sie sollten welche auf der <a href="/budgets">Budget</a>-Seite erstellen. Budgets können Ihnen helfen ihre Ausgaben zu verfolgen.',
'Savings account' => 'Savings account',
'Credit card' => 'Credit card',
'source_accounts' => 'Herkunftskonto', 'source_accounts' => 'Herkunftskonto',
'destination_accounts' => 'Zielkonto', 'destination_accounts' => 'Zielkonto',
'user_id_is' => 'Your user id is <strong>:user</strong>', 'user_id_is' => 'Your user id is <strong>:user</strong>',
'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.', 'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.',
'need_more_help' => 'If you need more help using Firefly III, please <a href="https://github.com/JC5/firefly-iii/issues">open a ticker on Github</a>.',
'nothing_to_display' => 'There are no transactions to show you',
// repeat frequencies: // repeat frequencies:
'repeat_freq_yearly' => 'yearly', 'repeat_freq_yearly' => 'yearly',
@@ -842,14 +856,9 @@ return [
'import_complete_text' => 'Der Import ist bereit zu starten. Alle Einstellungen wurden von Ihnen erledigt. Bitte laden Sie die Konfigurationsdatei herunter. Diese wird Ihnen beim Import helfen, sollte dieser nicht wie gewünscht verlaufen. Um den Import tatsächlich zu starten führen Sie den folgenden Befehl in der Konsole aus oder nutzen Sie den Web-basierten Import. Abhängig von ihrer Konfiguration wird Ihnen der Konsolenimport mehr Rückmeldungen geben.', 'import_complete_text' => 'Der Import ist bereit zu starten. Alle Einstellungen wurden von Ihnen erledigt. Bitte laden Sie die Konfigurationsdatei herunter. Diese wird Ihnen beim Import helfen, sollte dieser nicht wie gewünscht verlaufen. Um den Import tatsächlich zu starten führen Sie den folgenden Befehl in der Konsole aus oder nutzen Sie den Web-basierten Import. Abhängig von ihrer Konfiguration wird Ihnen der Konsolenimport mehr Rückmeldungen geben.',
'import_download_config' => 'Download configuration', 'import_download_config' => 'Download configuration',
'import_start_import' => 'Start import', 'import_start_import' => 'Start import',
'import_intro_beta' => 'Die Importfunktion von Firefly III ist im Beta-Stadium. Viele unterschiedliche Nutzer von Firefly III haben viele verschiedene Datei getestet. Auch wenn die einzelnen Komponenten des Imports funktionieren (wirklich), können Fehler auftreten. Wenn ihre Datei nicht in Firefly importiert werden kann lesen Sie bitte <a href="https://github.com/JC5/firefly-iii/wiki/Submit-issues-with-sensitive-data-in-them">diese Wiki-Seite</a>, damit ich den aufgetretenen Fehler beheben kann.',
'import_data' => 'Daten importieren', 'import_data' => 'Daten importieren',
'import_data_full' => 'Importieren Sie Daten in Firefly III', 'import_data_full' => 'Importieren Sie Daten in Firefly III',
'import' => 'Import', 'import' => 'Import',
'import_intro_what_it_does' => 'Diese Seite erlaubt Ihnen das Importieren von Daten in Firefly III. Exportieren Sie dazu Daten von ihrer Bank oder anderen Finanzverwaltungen. Laden Sie die Dateien anschließend hier hoch. Firefly III wird die Daten daraufhin konvertieren. Sie müssen dafür einige Informationen angeben. Bitte wählen Sie nun eine Datei aus folgen Sie den Anweisungen.',
'import_intro_import_conf_title' => 'Importkonfiguration',
'import_intro_beta_warning' => 'Achtung',
'import_intro_import_conf_text' => 'Wie Sie auf den nächsten Seite feststellen werden, hat die Importfunktion viele Einstellungen. Diese Einstellungen sind vor allem von ihrer Bank (oder Finanzverwaltungssoftware), von der ihre Daten stammen, abhängig. Es ist sehr wahrscheinlich, dass bereits eine andere Person solch eine Datei importiert hat und die jeweile <em>Konfigurationsdatei</em> bereitstellt. Bitte schauen Sie daher in der <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">Übersicht der Import-Einstellungen</a></strong> nach, ob bereits eine Konfiguratiosdatei für ihre Bank vorhanden ist. Wenn eine Datei existiert sollten Sie diese herunterladen und hier hochladen. Es wird Ihnen eine Menge Zeit sparen!',
'import_file_help' => 'Select your file', 'import_file_help' => 'Select your file',
'import_status_settings_complete' => 'The import is ready to start.', 'import_status_settings_complete' => 'The import is ready to start.',
'import_status_import_complete' => 'The import has completed.', 'import_status_import_complete' => 'The import has completed.',
@@ -865,11 +874,9 @@ return [
'import_double' => 'Row #:row: This row has been imported before, and is stored in <a href=":link">:description</a>.', 'import_double' => 'Row #:row: This row has been imported before, and is stored in <a href=":link">:description</a>.',
'import_finished_all' => 'The import has finished. Please check out the results below.', 'import_finished_all' => 'The import has finished. Please check out the results below.',
'import_with_key' => 'Import with key \':key\'', 'import_with_key' => 'Import with key \':key\'',
'import_share_configuration' => 'Bitte denken Sie darüber nach ihre Konfiguration herunterzuladen und in der <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">Übersicht der Import-Einstellungen</a></strong> zu teilen. Dieses erlaubt es anderen Nutzern von Firefly III ihre Daten unkomplizierter zu importieren.',
'import_share_configuration' => 'Bitte denken Sie darüber nach ihre Konfiguration herunterzuladen und in der <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">Übersicht der Import-Einstellungen</a></strong> zu teilen. Dieses erlaubt es anderen Nutzern von Firefly III ihre Daten unkomplizierter zu importieren.', 'import_finished_report' => 'The import has finished. Please note any errors in the block above this line. All transactions imported during this particular session have been tagged, and you can check them out below. ',
'import_finished_link' => 'The transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.',
'import_finished_report' => 'The import has finished. Please note any errors in the block above this line. All transactions imported during this particular session have been tagged, and you can check them out below. ', 'need_at_least_one_account' => 'You need at least one asset account to be able to create piggy banks',
'import_finished_link' => 'The transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.', 'see_help_top_right' => 'For more information, please check out the help pages using the icon in the top right corner of the page.',
]; ];

View File

@@ -15,7 +15,7 @@ return [
'import_configure_title' => 'Configure your import', 'import_configure_title' => 'Configure your import',
'import_configure_intro' => 'There are some options for your CSV import. Please indicate if your CSV file contains headers on the first column, and what the date format of your date-fields is. That might require some experimentation. The field delimiter is usually a ",", but could also be a ";". Check this carefully.', 'import_configure_intro' => 'There are some options for your CSV import. Please indicate if your CSV file contains headers on the first column, and what the date format of your date-fields is. That might require some experimentation. The field delimiter is usually a ",", but could also be a ";". Check this carefully.',
'import_configure_form' => 'Form', 'import_configure_form' => 'Basic CSV import options',
'header_help' => 'Check this if the first row of your CSV file are the column titles', 'header_help' => 'Check this if the first row of your CSV file are the column titles',
'date_help' => 'Date time format in your CSV. Follow the format like <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">this page</a> indicates. The default value will parse dates that look like this: :dateExample.', 'date_help' => 'Date time format in your CSV. Follow the format like <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">this page</a> indicates. The default value will parse dates that look like this: :dateExample.',
'delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.', 'delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
@@ -24,7 +24,6 @@ return [
// roles // roles
'column_roles_title' => 'Define column roles', 'column_roles_title' => 'Define column roles',
'column_roles_text' => '<p>Firefly III cannot guess what data each column contains. You must tell Firefly which kinds of data to expect. The example data can guide you into picking the correct type from the dropdown. If a column cannot be matched to a useful data type, please let me know <a href="https://github.com/JC5/firefly-iii/issues/new">by creating an issue</a>.</p><p>Some values in your CSV file, such as account names or categories, may already exist in your Firefly III database. If you select "map these values" Firefly will not attempt to search for matching values itself but allow you to match the CSV values against the values in your database. This allows you to fine-tune the import.</p>',
'column_roles_table' => 'Table', 'column_roles_table' => 'Table',
'column_name' => 'Name of column', 'column_name' => 'Name of column',
'column_example' => 'Column example data', 'column_example' => 'Column example data',

View File

@@ -67,11 +67,25 @@ return [
'warning_much_data' => ':days days of data may take a while to load.', 'warning_much_data' => ':days days of data may take a while to load.',
'registered' => 'You have registered successfully!', 'registered' => 'You have registered successfully!',
'search' => 'Search', 'search' => 'Search',
'search_found_accounts' => 'Found :count account(s) for your query.',
'search_found_categories' => 'Found :count category(ies) for your query.',
'search_found_budgets' => 'Found :count budget(s) for your query.',
'search_found_tags' => 'Found :count tag(s) for your query.',
'search_found_transactions' => 'Found :count transaction(s) for your query.',
'results_limited' => 'The results are limited to :count entries.',
'tagbalancingAct' => 'Balancing act',
'tagadvancePayment' => 'Advance payment',
'tagnothing' => '',
'Default asset account' => 'Default asset account',
'no_budget_pointer' => 'You seem to have no budgets yet. You should create some on the <a href="/budgets">budgets</a>-page. Budgets can help you keep track of expenses.', 'no_budget_pointer' => 'You seem to have no budgets yet. You should create some on the <a href="/budgets">budgets</a>-page. Budgets can help you keep track of expenses.',
'Savings account' => 'Savings account',
'Credit card' => 'Credit card',
'source_accounts' => 'Source account(s)', 'source_accounts' => 'Source account(s)',
'destination_accounts' => 'Destination account(s)', 'destination_accounts' => 'Destination account(s)',
'user_id_is' => 'Your user id is <strong>:user</strong>', 'user_id_is' => 'Your user id is <strong>:user</strong>',
'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.', 'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.',
'need_more_help' => 'If you need more help using Firefly III, please <a href="https://github.com/JC5/firefly-iii/issues">open a ticker on Github</a>.',
'nothing_to_display' => 'There are no transactions to show you',
// repeat frequencies: // repeat frequencies:
'repeat_freq_yearly' => 'yearly', 'repeat_freq_yearly' => 'yearly',
@@ -842,14 +856,9 @@ return [
'import_complete_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.', 'import_complete_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.',
'import_download_config' => 'Download configuration', 'import_download_config' => 'Download configuration',
'import_start_import' => 'Start import', 'import_start_import' => 'Start import',
'import_intro_beta' => 'The import function of Firefly III is in beta. Many users of Firefly III have tried many different files. Although each individual compontent of this import routine works (really), the combination might break. If your file cannot be imported by Firefly, please read <a href="https://github.com/JC5/firefly-iii/wiki/Submit-issues-with-sensitive-data-in-them">this wiki page</a> so I can fix the problem you have run into.',
'import_data' => 'Import data', 'import_data' => 'Import data',
'import_data_full' => 'Import data into Firefly III', 'import_data_full' => 'Import data into Firefly III',
'import' => 'Import', 'import' => 'Import',
'import_intro_what_it_does' => 'This page allows you to import data into Firefly III. To do so, export data from your bank, or from another financial management system. Upload that file here. Firefly III will convert the data. You need to give it some directions. Please select a file and follow the instructions.',
'import_intro_import_conf_title' => 'Import "configuration"',
'import_intro_beta_warning' => 'Warning',
'import_intro_import_conf_text' => 'As you will discover over the next few pages, this import routine has a lot of settings. These settings are mainly dependent on the bank (or financial management software) your file comes from. There is a good chance somebody else already imported such a file and has shared their <em>configuration file</em>. Please visit the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong> to see if there already is a configuration available for your bank or system. If there is, you should download this configuration file and upload it here as well. It will save you a lot of time!',
'import_file_help' => 'Select your file', 'import_file_help' => 'Select your file',
'import_status_settings_complete' => 'The import is ready to start.', 'import_status_settings_complete' => 'The import is ready to start.',
'import_status_import_complete' => 'The import has completed.', 'import_status_import_complete' => 'The import has completed.',
@@ -865,11 +874,9 @@ return [
'import_double' => 'Row #:row: This row has been imported before, and is stored in <a href=":link">:description</a>.', 'import_double' => 'Row #:row: This row has been imported before, and is stored in <a href=":link">:description</a>.',
'import_finished_all' => 'The import has finished. Please check out the results below.', 'import_finished_all' => 'The import has finished. Please check out the results below.',
'import_with_key' => 'Import with key \':key\'', 'import_with_key' => 'Import with key \':key\'',
'import_share_configuration' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.',
'import_share_configuration' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.', 'import_finished_report' => 'The import has finished. Please note any errors in the block above this line. All transactions imported during this particular session have been tagged, and you can check them out below. ',
'import_finished_link' => 'The transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.',
'import_finished_report' => 'The import has finished. Please note any errors in the block above this line. All transactions imported during this particular session have been tagged, and you can check them out below. ', 'need_at_least_one_account' => 'You need at least one asset account to be able to create piggy banks',
'import_finished_link' => 'The transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.', 'see_help_top_right' => 'For more information, please check out the help pages using the icon in the top right corner of the page.',
]; ];

View File

@@ -15,7 +15,7 @@ return [
'import_configure_title' => 'Configurer l\'import', 'import_configure_title' => 'Configurer l\'import',
'import_configure_intro' => 'Il y a des options pour l\'import CSV. Veuillez indiquer si votre fichier CSV contient les en-têtes dans la première colonne, et quel est le format de la date de votre champs date. Cela peut nécessiter quelques essais. Le délimiteur de champ est généralement un «, », mais pourrait également être un « ; ». Cochez cette case avec soin.', 'import_configure_intro' => 'Il y a des options pour l\'import CSV. Veuillez indiquer si votre fichier CSV contient les en-têtes dans la première colonne, et quel est le format de la date de votre champs date. Cela peut nécessiter quelques essais. Le délimiteur de champ est généralement un «, », mais pourrait également être un « ; ». Cochez cette case avec soin.',
'import_configure_form' => 'Formulaire', 'import_configure_form' => 'Basic CSV import options',
'header_help' => 'Cochez cette case si la première ligne de votre fichier CSV contient les entêtes des colonnes', 'header_help' => 'Cochez cette case si la première ligne de votre fichier CSV contient les entêtes des colonnes',
'date_help' => 'Le format de la date et de lheure dans votre fichier CSV. Utiliser les formats comme indiqué sur <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters"> cette page</a>. La valeur par défaut va extraire les dates qui ressemblent à ceci: :dateExample.', 'date_help' => 'Le format de la date et de lheure dans votre fichier CSV. Utiliser les formats comme indiqué sur <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters"> cette page</a>. La valeur par défaut va extraire les dates qui ressemblent à ceci: :dateExample.',
'delimiter_help' => 'Choisissez le délimiteur de champ qui est utilisé dans votre fichier dentrée. Si vous nêtes pas certain, la virgule est loption la plus sûre.', 'delimiter_help' => 'Choisissez le délimiteur de champ qui est utilisé dans votre fichier dentrée. Si vous nêtes pas certain, la virgule est loption la plus sûre.',
@@ -24,7 +24,6 @@ return [
// roles // roles
'column_roles_title' => 'Définir le rôle des colonnes', 'column_roles_title' => 'Définir le rôle des colonnes',
'column_roles_text' => '<p>Firefly III cannot guess what data each column contains. You must tell Firefly which kinds of data to expect. The example data can guide you into picking the correct type from the dropdown. If a column cannot be matched to a useful data type, please let me know <a href="https://github.com/JC5/firefly-iii/issues/new">by creating an issue</a>.</p><p>Some values in your CSV file, such as account names or categories, may already exist in your Firefly III database. If you select "map these values" Firefly will not attempt to search for matching values itself but allow you to match the CSV values against the values in your database. This allows you to fine-tune the import.</p>',
'column_roles_table' => 'Tableau', 'column_roles_table' => 'Tableau',
'column_name' => 'Nom de colonne', 'column_name' => 'Nom de colonne',
'column_example' => 'Exemple', 'column_example' => 'Exemple',

View File

@@ -67,11 +67,25 @@ return [
'warning_much_data' => ':days de données peuvent prendre un certain temps à charger.', 'warning_much_data' => ':days de données peuvent prendre un certain temps à charger.',
'registered' => 'Vous avez été enregistré avec succès !', 'registered' => 'Vous avez été enregistré avec succès !',
'search' => 'Rechercher', 'search' => 'Rechercher',
'search_found_accounts' => 'Found :count account(s) for your query.',
'search_found_categories' => 'Found :count category(ies) for your query.',
'search_found_budgets' => 'Found :count budget(s) for your query.',
'search_found_tags' => 'Found :count tag(s) for your query.',
'search_found_transactions' => 'Found :count transaction(s) for your query.',
'results_limited' => 'The results are limited to :count entries.',
'tagbalancingAct' => 'Balancing act',
'tagadvancePayment' => 'Advance payment',
'tagnothing' => '',
'Default asset account' => 'Default asset account',
'no_budget_pointer' => 'Vous semblez navoir encore aucun budget. Vous devez en créer sur la page des <a href="/budgets"> budgets</a>. Les budgets peuvent vous aider à garder une trace des dépenses.', 'no_budget_pointer' => 'Vous semblez navoir encore aucun budget. Vous devez en créer sur la page des <a href="/budgets"> budgets</a>. Les budgets peuvent vous aider à garder une trace des dépenses.',
'Savings account' => 'Savings account',
'Credit card' => 'Credit card',
'source_accounts' => 'Compte(s) source', 'source_accounts' => 'Compte(s) source',
'destination_accounts' => 'Compte(s) de destination', 'destination_accounts' => 'Compte(s) de destination',
'user_id_is' => 'Your user id is <strong>:user</strong>', 'user_id_is' => 'Your user id is <strong>:user</strong>',
'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.', 'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.',
'need_more_help' => 'If you need more help using Firefly III, please <a href="https://github.com/JC5/firefly-iii/issues">open a ticker on Github</a>.',
'nothing_to_display' => 'There are no transactions to show you',
// repeat frequencies: // repeat frequencies:
'repeat_freq_yearly' => 'yearly', 'repeat_freq_yearly' => 'yearly',
@@ -842,14 +856,9 @@ return [
'import_complete_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.', 'import_complete_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.',
'import_download_config' => 'Download configuration', 'import_download_config' => 'Download configuration',
'import_start_import' => 'Start import', 'import_start_import' => 'Start import',
'import_intro_beta' => 'The import function of Firefly III is in beta. Many users of Firefly III have tried many different files. Although each individual compontent of this import routine works (really), the combination might break. If your file cannot be imported by Firefly, please read <a href="https://github.com/JC5/firefly-iii/wiki/Submit-issues-with-sensitive-data-in-them">this wiki page</a> so I can fix the problem you have run into.',
'import_data' => 'Import data', 'import_data' => 'Import data',
'import_data_full' => 'Import data into Firefly III', 'import_data_full' => 'Import data into Firefly III',
'import' => 'Import', 'import' => 'Import',
'import_intro_what_it_does' => 'This page allows you to import data into Firefly III. To do so, export data from your bank, or from another financial management system. Upload that file here. Firefly III will convert the data. You need to give it some directions. Please select a file and follow the instructions.',
'import_intro_import_conf_title' => 'Import "configuration"',
'import_intro_beta_warning' => 'Warning',
'import_intro_import_conf_text' => 'As you will discover over the next few pages, this import routine has a lot of settings. These settings are mainly dependent on the bank (or financial management software) your file comes from. There is a good chance somebody else already imported such a file and has shared their <em>configuration file</em>. Please visit the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong> to see if there already is a configuration available for your bank or system. If there is, you should download this configuration file and upload it here as well. It will save you a lot of time!',
'import_file_help' => 'Select your file', 'import_file_help' => 'Select your file',
'import_status_settings_complete' => 'The import is ready to start.', 'import_status_settings_complete' => 'The import is ready to start.',
'import_status_import_complete' => 'The import has completed.', 'import_status_import_complete' => 'The import has completed.',
@@ -865,11 +874,9 @@ return [
'import_double' => 'Row #:row: This row has been imported before, and is stored in <a href=":link">:description</a>.', 'import_double' => 'Row #:row: This row has been imported before, and is stored in <a href=":link">:description</a>.',
'import_finished_all' => 'The import has finished. Please check out the results below.', 'import_finished_all' => 'The import has finished. Please check out the results below.',
'import_with_key' => 'Import with key \':key\'', 'import_with_key' => 'Import with key \':key\'',
'import_share_configuration' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.',
'import_share_configuration' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.', 'import_finished_report' => 'The import has finished. Please note any errors in the block above this line. All transactions imported during this particular session have been tagged, and you can check them out below. ',
'import_finished_link' => 'The transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.',
'import_finished_report' => 'The import has finished. Please note any errors in the block above this line. All transactions imported during this particular session have been tagged, and you can check them out below. ', 'need_at_least_one_account' => 'You need at least one asset account to be able to create piggy banks',
'import_finished_link' => 'The transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.', 'see_help_top_right' => 'For more information, please check out the help pages using the icon in the top right corner of the page.',
]; ];

View File

@@ -15,7 +15,7 @@ return [
'import_configure_title' => 'Configure your import', 'import_configure_title' => 'Configure your import',
'import_configure_intro' => 'There are some options for your CSV import. Please indicate if your CSV file contains headers on the first column, and what the date format of your date-fields is. That might require some experimentation. The field delimiter is usually a ",", but could also be a ";". Check this carefully.', 'import_configure_intro' => 'There are some options for your CSV import. Please indicate if your CSV file contains headers on the first column, and what the date format of your date-fields is. That might require some experimentation. The field delimiter is usually a ",", but could also be a ";". Check this carefully.',
'import_configure_form' => 'Form', 'import_configure_form' => 'Basic CSV import options',
'header_help' => 'Check this if the first row of your CSV file are the column titles', 'header_help' => 'Check this if the first row of your CSV file are the column titles',
'date_help' => 'Date time format in your CSV. Follow the format like <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">this page</a> indicates. The default value will parse dates that look like this: :dateExample.', 'date_help' => 'Date time format in your CSV. Follow the format like <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">this page</a> indicates. The default value will parse dates that look like this: :dateExample.',
'delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.', 'delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
@@ -24,7 +24,6 @@ return [
// roles // roles
'column_roles_title' => 'Define column roles', 'column_roles_title' => 'Define column roles',
'column_roles_text' => '<p>Firefly III cannot guess what data each column contains. You must tell Firefly which kinds of data to expect. The example data can guide you into picking the correct type from the dropdown. If a column cannot be matched to a useful data type, please let me know <a href="https://github.com/JC5/firefly-iii/issues/new">by creating an issue</a>.</p><p>Some values in your CSV file, such as account names or categories, may already exist in your Firefly III database. If you select "map these values" Firefly will not attempt to search for matching values itself but allow you to match the CSV values against the values in your database. This allows you to fine-tune the import.</p>',
'column_roles_table' => 'Table', 'column_roles_table' => 'Table',
'column_name' => 'Name of column', 'column_name' => 'Name of column',
'column_example' => 'Column example data', 'column_example' => 'Column example data',

View File

@@ -67,11 +67,25 @@ return [
'warning_much_data' => ':days days of data may take a while to load.', 'warning_much_data' => ':days days of data may take a while to load.',
'registered' => 'You have registered successfully!', 'registered' => 'You have registered successfully!',
'search' => 'Search', 'search' => 'Search',
'search_found_accounts' => 'Found :count account(s) for your query.',
'search_found_categories' => 'Found :count category(ies) for your query.',
'search_found_budgets' => 'Found :count budget(s) for your query.',
'search_found_tags' => 'Found :count tag(s) for your query.',
'search_found_transactions' => 'Found :count transaction(s) for your query.',
'results_limited' => 'The results are limited to :count entries.',
'tagbalancingAct' => 'Balancing act',
'tagadvancePayment' => 'Advance payment',
'tagnothing' => '',
'Default asset account' => 'Default asset account',
'no_budget_pointer' => 'You seem to have no budgets yet. You should create some on the <a href="/budgets">budgets</a>-page. Budgets can help you keep track of expenses.', 'no_budget_pointer' => 'You seem to have no budgets yet. You should create some on the <a href="/budgets">budgets</a>-page. Budgets can help you keep track of expenses.',
'Savings account' => 'Savings account',
'Credit card' => 'Credit card',
'source_accounts' => 'Source account(s)', 'source_accounts' => 'Source account(s)',
'destination_accounts' => 'Destination account(s)', 'destination_accounts' => 'Destination account(s)',
'user_id_is' => 'Your user id is <strong>:user</strong>', 'user_id_is' => 'Your user id is <strong>:user</strong>',
'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.', 'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.',
'need_more_help' => 'If you need more help using Firefly III, please <a href="https://github.com/JC5/firefly-iii/issues">open a ticker on Github</a>.',
'nothing_to_display' => 'There are no transactions to show you',
// repeat frequencies: // repeat frequencies:
'repeat_freq_yearly' => 'yearly', 'repeat_freq_yearly' => 'yearly',
@@ -842,14 +856,9 @@ return [
'import_complete_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.', 'import_complete_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.',
'import_download_config' => 'Download configuration', 'import_download_config' => 'Download configuration',
'import_start_import' => 'Start import', 'import_start_import' => 'Start import',
'import_intro_beta' => 'The import function of Firefly III is in beta. Many users of Firefly III have tried many different files. Although each individual compontent of this import routine works (really), the combination might break. If your file cannot be imported by Firefly, please read <a href="https://github.com/JC5/firefly-iii/wiki/Submit-issues-with-sensitive-data-in-them">this wiki page</a> so I can fix the problem you have run into.',
'import_data' => 'Import data', 'import_data' => 'Import data',
'import_data_full' => 'Import data into Firefly III', 'import_data_full' => 'Import data into Firefly III',
'import' => 'Import', 'import' => 'Import',
'import_intro_what_it_does' => 'This page allows you to import data into Firefly III. To do so, export data from your bank, or from another financial management system. Upload that file here. Firefly III will convert the data. You need to give it some directions. Please select a file and follow the instructions.',
'import_intro_import_conf_title' => 'Import "configuration"',
'import_intro_beta_warning' => 'Warning',
'import_intro_import_conf_text' => 'As you will discover over the next few pages, this import routine has a lot of settings. These settings are mainly dependent on the bank (or financial management software) your file comes from. There is a good chance somebody else already imported such a file and has shared their <em>configuration file</em>. Please visit the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong> to see if there already is a configuration available for your bank or system. If there is, you should download this configuration file and upload it here as well. It will save you a lot of time!',
'import_file_help' => 'Select your file', 'import_file_help' => 'Select your file',
'import_status_settings_complete' => 'The import is ready to start.', 'import_status_settings_complete' => 'The import is ready to start.',
'import_status_import_complete' => 'The import has completed.', 'import_status_import_complete' => 'The import has completed.',
@@ -865,11 +874,9 @@ return [
'import_double' => 'Row #:row: This row has been imported before, and is stored in <a href=":link">:description</a>.', 'import_double' => 'Row #:row: This row has been imported before, and is stored in <a href=":link">:description</a>.',
'import_finished_all' => 'The import has finished. Please check out the results below.', 'import_finished_all' => 'The import has finished. Please check out the results below.',
'import_with_key' => 'Import with key \':key\'', 'import_with_key' => 'Import with key \':key\'',
'import_share_configuration' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.',
'import_share_configuration' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.', 'import_finished_report' => 'The import has finished. Please note any errors in the block above this line. All transactions imported during this particular session have been tagged, and you can check them out below. ',
'import_finished_link' => 'The transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.',
'import_finished_report' => 'The import has finished. Please note any errors in the block above this line. All transactions imported during this particular session have been tagged, and you can check them out below. ', 'need_at_least_one_account' => 'You need at least one asset account to be able to create piggy banks',
'import_finished_link' => 'The transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.', 'see_help_top_right' => 'For more information, please check out the help pages using the icon in the top right corner of the page.',
]; ];

View File

@@ -15,7 +15,7 @@ return [
'import_configure_title' => 'Import configureren', 'import_configure_title' => 'Import configureren',
'import_configure_intro' => 'Hier zie je enkele opties voor jouw CSV bestand. Geef aan of je CSV bestand kolomtitels bevat, en hoe het datumveld is opgebouwd. Hier moet je wellicht wat experimenteren. Het scheidingsteken is meestal een ",", maar dat kan ook een ";" zijn. Controleer dit zorgvuldig.', 'import_configure_intro' => 'Hier zie je enkele opties voor jouw CSV bestand. Geef aan of je CSV bestand kolomtitels bevat, en hoe het datumveld is opgebouwd. Hier moet je wellicht wat experimenteren. Het scheidingsteken is meestal een ",", maar dat kan ook een ";" zijn. Controleer dit zorgvuldig.',
'import_configure_form' => 'Formulier', 'import_configure_form' => 'Standaard CSV import opties',
'header_help' => 'Vink hier als de eerste rij kolomtitels bevat', 'header_help' => 'Vink hier als de eerste rij kolomtitels bevat',
'date_help' => 'Datum/tijd formaat in jouw CSV bestand. Volg het formaat zoals ze het <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">op deze pagina</a> uitleggen. Het standaardformaat ziet er zo uit: :dateExample.', 'date_help' => 'Datum/tijd formaat in jouw CSV bestand. Volg het formaat zoals ze het <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">op deze pagina</a> uitleggen. Het standaardformaat ziet er zo uit: :dateExample.',
'delimiter_help' => 'Kies het veldscheidingsteken dat in jouw bestand wordt gebruikt. Als je het niet zeker weet, is de komma de beste optie.', 'delimiter_help' => 'Kies het veldscheidingsteken dat in jouw bestand wordt gebruikt. Als je het niet zeker weet, is de komma de beste optie.',
@@ -24,7 +24,6 @@ return [
// roles // roles
'column_roles_title' => 'Bepaal de inhoud van elke kolom', 'column_roles_title' => 'Bepaal de inhoud van elke kolom',
'column_roles_text' => '<p>Firefly III kan niet raden welke soort gegevens er in elke kolom staan. Dat moet je er bij vertellen. Gebruik de voorbeeldgegevens en kies het juiste type uit de dropdown. Staat jouw type er niet bij? <a href="https://github.com/JC5/firefly-iii/issues/new">Open dan een ticket</a>.</p><p>Sommige waarden, zoals rekeningnummers en namen staan wellicht al in jouw Firefly III database. Als je dan het vinkje vinkt, kan je zelf de link leggen tussen wat er in het CSV bestand staat en wat er in de database staat. Hiermee kan je de import sturen.</p>',
'column_roles_table' => 'Tabel', 'column_roles_table' => 'Tabel',
'column_name' => 'Kolomnaam', 'column_name' => 'Kolomnaam',
'column_example' => 'Voorbeeldgegevens', 'column_example' => 'Voorbeeldgegevens',

View File

@@ -67,11 +67,25 @@ return [
'warning_much_data' => 'Het kan even duren voor :days dagen aan gegevens geladen zijn.', 'warning_much_data' => 'Het kan even duren voor :days dagen aan gegevens geladen zijn.',
'registered' => 'Je bent geregistreerd!', 'registered' => 'Je bent geregistreerd!',
'search' => 'Zoeken', 'search' => 'Zoeken',
'search_found_accounts' => ':count rekening(en) gevonden bij je zoekopdracht.',
'search_found_categories' => ':count categorie(en) gevonden bij je zoekopdracht.',
'search_found_budgets' => ':count budget(ten) gevonden bij je zoekopdracht.',
'search_found_tags' => ':count tag(s) gevonden bij je zoekopdracht.',
'search_found_transactions' => ':count transactie(s) gevonden bij je zoekopdracht.',
'results_limited' => 'Er worden maximaal :count resultaten getoond.',
'tagbalancingAct' => 'Balancerende tag',
'tagadvancePayment' => 'Vooruitbetaalde tag',
'tagnothing' => '',
'Default asset account' => 'Standaard betaalrekening',
'no_budget_pointer' => 'Je hebt nog geen budgetten. Maak er een aantal op de <a href="/budgets">budgetten</a>-pagina. Met budgetten kan je je uitgaven beter bijhouden.', 'no_budget_pointer' => 'Je hebt nog geen budgetten. Maak er een aantal op de <a href="/budgets">budgetten</a>-pagina. Met budgetten kan je je uitgaven beter bijhouden.',
'Savings account' => 'Spaarrekening',
'Credit card' => 'Credit card',
'source_accounts' => 'Bronrekening(en)', 'source_accounts' => 'Bronrekening(en)',
'destination_accounts' => 'Doelrekening(en)', 'destination_accounts' => 'Doelrekening(en)',
'user_id_is' => 'Je gebruikersnummer is <strong>:user</strong>', 'user_id_is' => 'Je gebruikersnummer is <strong>:user</strong>',
'field_supports_markdown' => 'Dit veld ondersteunt <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.', 'field_supports_markdown' => 'Dit veld ondersteunt <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.',
'need_more_help' => 'Als je meer hulp nodig hebt met Firefly III, <a href="https://github.com/JC5/firefly-iii/issues">open dan een ticket op Github</a>.',
'nothing_to_display' => 'Er zijn hier geen transacties te zien',
// repeat frequencies: // repeat frequencies:
'repeat_freq_yearly' => 'jaarlijks', 'repeat_freq_yearly' => 'jaarlijks',
@@ -842,14 +856,9 @@ return [
'import_complete_text' => 'De import kan beginnen. Alle configuratie is opgeslagen. Download dit bestand. Het kan schelen als je de import opnieuw moet doen. Om daadwerkelijk te beginnen, gebruik je of het commando in je console, of de website. Afhankelijk van hoe je Firefly III hebt ingesteld, geeft de console-methode meer feedback.', 'import_complete_text' => 'De import kan beginnen. Alle configuratie is opgeslagen. Download dit bestand. Het kan schelen als je de import opnieuw moet doen. Om daadwerkelijk te beginnen, gebruik je of het commando in je console, of de website. Afhankelijk van hoe je Firefly III hebt ingesteld, geeft de console-methode meer feedback.',
'import_download_config' => 'Download importconfiguratie', 'import_download_config' => 'Download importconfiguratie',
'import_start_import' => 'Import starten', 'import_start_import' => 'Import starten',
'import_intro_beta' => 'De importfunctie van Firefly III is in bèta. Er zijn al veel bestanden geprobeerd, en elk individueel component zou moeten werken. Gecombineerd echter, kan er wat stuk gaan. Als jouw bestand problemen geeft, lees dan <a href="https://github.com/JC5/firefly-iii/wiki/Submit-issues-with-sensitive-data-in-them">deze wikipagina</a> zodat ik eventuele bugs kan fixen.',
'import_data' => 'Importeer data', 'import_data' => 'Importeer data',
'import_data_full' => 'Gegevens importeren in Firefly III', 'import_data_full' => 'Gegevens importeren in Firefly III',
'import' => 'Import', 'import' => 'Import',
'import_intro_what_it_does' => 'Vanaf deze pagina kan je gegevens importeren in Firefly III. Exporteer ze eerst vanuit je internetbankieren of financiële software. Upload dat bestandje hier. Firefly III zal de transacties omzetten. Je zult wel wat hints moeten geven. Selecteer alsjeblieft een bestand en volg de instructies.',
'import_intro_import_conf_title' => 'Importconfiguratie',
'import_intro_beta_warning' => 'Waarschuwing',
'import_intro_import_conf_text' => 'Zoals je wel zult ontdekken heeft de import-routine veel opties. Deze opties verschillen voornamelijk per bank (of softwarepakket). Grote kans dat iemand anders je al voor was en zijn of haar <em>configuratiebestand</em> heeft gedeeld. Kijk vlug op de <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">configuratiebestand-wiki</a></strong> of er al een bestand is voor jouw bank (of softwarepakket). Als die er is, download dit bestand dan en selecteer deze. Het kan veel tijd schelen!',
'import_file_help' => 'Selecteer je bestand', 'import_file_help' => 'Selecteer je bestand',
'import_status_settings_complete' => 'De import is klaar om te beginnen.', 'import_status_settings_complete' => 'De import is klaar om te beginnen.',
'import_status_import_complete' => 'Het importeren is voltooid.', 'import_status_import_complete' => 'Het importeren is voltooid.',
@@ -865,11 +874,9 @@ return [
'import_double' => 'Rij: #:row: Deze rij is al geimporteerd en is opgeslagen als <a href=":link">:description</a>.', 'import_double' => 'Rij: #:row: Deze rij is al geimporteerd en is opgeslagen als <a href=":link">:description</a>.',
'import_finished_all' => 'Het importeren is voltooid. Hieronder zie je de resultaten.', 'import_finished_all' => 'Het importeren is voltooid. Hieronder zie je de resultaten.',
'import_with_key' => 'Import met code \':key\'', 'import_with_key' => 'Import met code \':key\'',
'import_share_configuration' => 'Overweeg om je configuratiebestand te downloaden en te delen op de <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">configuratiebestand-wiki</a></strong>. Hiermee kan je het andere Firefly III gebruikers weer makkelijker maken.',
'import_share_configuration' => 'Overweeg om je configuratiebestand te downloaden en te delen op de <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">configuratiebestand-wiki</a></strong>. Hiermee kan je het andere Firefly III gebruikers weer makkelijker maken.', 'import_finished_report' => 'Het importeren is voltooid. Kijk naar eventuele fouten in het blok hierboven. Alle geimporteerde transacties hebben een tag, en die kan je hieronder bekijken. ',
'import_finished_link' => 'De geimporteerde transacties kan je vinden onder tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.',
'import_finished_report' => 'Het importeren is voltooid. Kijk naar eventuele fouten in het blok hierboven. Alle geimporteerde transacties hebben een tag, en die kan je hieronder bekijken. ', 'need_at_least_one_account' => 'Je moet minstens één betaalrekening hebben voor je spaarpotjes kan maken',
'import_finished_link' => 'De geimporteerde transacties kan je vinden onder tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.', 'see_help_top_right' => 'Meer informatie vind je in de help pagina\'s. Gebruik daarvoor het icoontje rechtsboven in de hoek.',
]; ];

View File

@@ -15,7 +15,7 @@ return [
'import_configure_title' => 'Configure sua importação', 'import_configure_title' => 'Configure sua importação',
'import_configure_intro' => 'There are some options for your CSV import. Please indicate if your CSV file contains headers on the first column, and what the date format of your date-fields is. That might require some experimentation. The field delimiter is usually a ",", but could also be a ";". Check this carefully.', 'import_configure_intro' => 'There are some options for your CSV import. Please indicate if your CSV file contains headers on the first column, and what the date format of your date-fields is. That might require some experimentation. The field delimiter is usually a ",", but could also be a ";". Check this carefully.',
'import_configure_form' => 'Formulário', 'import_configure_form' => 'Basic CSV import options',
'header_help' => 'Verifique se a primeira linha do seu arquivo CSV está com os títulos de coluna', 'header_help' => 'Verifique se a primeira linha do seu arquivo CSV está com os títulos de coluna',
'date_help' => 'Date time format in your CSV. Follow the format like <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">this page</a> indicates. The default value will parse dates that look like this: :dateExample.', 'date_help' => 'Date time format in your CSV. Follow the format like <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">this page</a> indicates. The default value will parse dates that look like this: :dateExample.',
'delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.', 'delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
@@ -24,7 +24,6 @@ return [
// roles // roles
'column_roles_title' => 'Definir papeis da coluna', 'column_roles_title' => 'Definir papeis da coluna',
'column_roles_text' => '<p>Firefly III cannot guess what data each column contains. You must tell Firefly which kinds of data to expect. The example data can guide you into picking the correct type from the dropdown. If a column cannot be matched to a useful data type, please let me know <a href="https://github.com/JC5/firefly-iii/issues/new">by creating an issue</a>.</p><p>Some values in your CSV file, such as account names or categories, may already exist in your Firefly III database. If you select "map these values" Firefly will not attempt to search for matching values itself but allow you to match the CSV values against the values in your database. This allows you to fine-tune the import.</p>',
'column_roles_table' => 'Tabela', 'column_roles_table' => 'Tabela',
'column_name' => 'Nome da coluna', 'column_name' => 'Nome da coluna',
'column_example' => 'Dados de exemplo da coluna', 'column_example' => 'Dados de exemplo da coluna',

View File

@@ -67,11 +67,25 @@ return [
'warning_much_data' => ':days dias de dados podem demorar um pouco para carregar.', 'warning_much_data' => ':days dias de dados podem demorar um pouco para carregar.',
'registered' => 'Você se registrou com sucesso!', 'registered' => 'Você se registrou com sucesso!',
'search' => 'Pesquisa', 'search' => 'Pesquisa',
'search_found_accounts' => 'Found :count account(s) for your query.',
'search_found_categories' => 'Found :count category(ies) for your query.',
'search_found_budgets' => 'Found :count budget(s) for your query.',
'search_found_tags' => 'Found :count tag(s) for your query.',
'search_found_transactions' => 'Found :count transaction(s) for your query.',
'results_limited' => 'The results are limited to :count entries.',
'tagbalancingAct' => 'Balancing act',
'tagadvancePayment' => 'Advance payment',
'tagnothing' => '',
'Default asset account' => 'Default asset account',
'no_budget_pointer' => 'Parece que não há orçamentos ainda. Você deve criar alguns na página <a href="/budgets">orçamentos</a>. Orçamentos podem ajudá-lo a manter o controle de despesas.', 'no_budget_pointer' => 'Parece que não há orçamentos ainda. Você deve criar alguns na página <a href="/budgets">orçamentos</a>. Orçamentos podem ajudá-lo a manter o controle de despesas.',
'Savings account' => 'Savings account',
'Credit card' => 'Credit card',
'source_accounts' => 'Conta(s) de origem', 'source_accounts' => 'Conta(s) de origem',
'destination_accounts' => 'Conta(s) de destino', 'destination_accounts' => 'Conta(s) de destino',
'user_id_is' => 'Your user id is <strong>:user</strong>', 'user_id_is' => 'Your user id is <strong>:user</strong>',
'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.', 'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.',
'need_more_help' => 'If you need more help using Firefly III, please <a href="https://github.com/JC5/firefly-iii/issues">open a ticker on Github</a>.',
'nothing_to_display' => 'There are no transactions to show you',
// repeat frequencies: // repeat frequencies:
'repeat_freq_yearly' => 'yearly', 'repeat_freq_yearly' => 'yearly',
@@ -842,14 +856,9 @@ return [
'import_complete_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.', 'import_complete_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.',
'import_download_config' => 'Download da configuração', 'import_download_config' => 'Download da configuração',
'import_start_import' => 'Iniciar importação', 'import_start_import' => 'Iniciar importação',
'import_intro_beta' => 'A função de importação do Firefly III está em beta. Muitos usuários do Firefly III têm tentado diferentes arquivos. Embora cada componente individual desta rotina de importação funcione (realmente), a combinação pode quebrar. Se seu arquivo não puder ser importado pelo Firefly, por favor leia <a href="https://github.com/JC5/firefly-iii/wiki/Submit-issues-with-sensitive-data-in-them">esta página da wiki</a> para resolver o problema que temos para executar.',
'import_data' => 'Importar dados', 'import_data' => 'Importar dados',
'import_data_full' => 'Importar dados para o Firefly III', 'import_data_full' => 'Importar dados para o Firefly III',
'import' => 'Importar', 'import' => 'Importar',
'import_intro_what_it_does' => 'This page allows you to import data into Firefly III. To do so, export data from your bank, or from another financial management system. Upload that file here. Firefly III will convert the data. You need to give it some directions. Please select a file and follow the instructions.',
'import_intro_import_conf_title' => 'Import "configuration"',
'import_intro_beta_warning' => 'Warning',
'import_intro_import_conf_text' => 'As you will discover over the next few pages, this import routine has a lot of settings. These settings are mainly dependent on the bank (or financial management software) your file comes from. There is a good chance somebody else already imported such a file and has shared their <em>configuration file</em>. Please visit the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong> to see if there already is a configuration available for your bank or system. If there is, you should download this configuration file and upload it here as well. It will save you a lot of time!',
'import_file_help' => 'Selecione seu arquivo', 'import_file_help' => 'Selecione seu arquivo',
'import_status_settings_complete' => 'The import is ready to start.', 'import_status_settings_complete' => 'The import is ready to start.',
'import_status_import_complete' => 'The import has completed.', 'import_status_import_complete' => 'The import has completed.',
@@ -865,11 +874,9 @@ return [
'import_double' => 'Row #:row: This row has been imported before, and is stored in <a href=":link">:description</a>.', 'import_double' => 'Row #:row: This row has been imported before, and is stored in <a href=":link">:description</a>.',
'import_finished_all' => 'The import has finished. Please check out the results below.', 'import_finished_all' => 'The import has finished. Please check out the results below.',
'import_with_key' => 'Import with key \':key\'', 'import_with_key' => 'Import with key \':key\'',
'import_share_configuration' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.',
'import_share_configuration' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.', 'import_finished_report' => 'The import has finished. Please note any errors in the block above this line. All transactions imported during this particular session have been tagged, and you can check them out below. ',
'import_finished_link' => 'The transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.',
'import_finished_report' => 'The import has finished. Please note any errors in the block above this line. All transactions imported during this particular session have been tagged, and you can check them out below. ', 'need_at_least_one_account' => 'You need at least one asset account to be able to create piggy banks',
'import_finished_link' => 'The transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.', 'see_help_top_right' => 'For more information, please check out the help pages using the icon in the top right corner of the page.',
]; ];

View File

@@ -15,7 +15,7 @@ return [
'import_configure_title' => 'Configure your import', 'import_configure_title' => 'Configure your import',
'import_configure_intro' => 'There are some options for your CSV import. Please indicate if your CSV file contains headers on the first column, and what the date format of your date-fields is. That might require some experimentation. The field delimiter is usually a ",", but could also be a ";". Check this carefully.', 'import_configure_intro' => 'There are some options for your CSV import. Please indicate if your CSV file contains headers on the first column, and what the date format of your date-fields is. That might require some experimentation. The field delimiter is usually a ",", but could also be a ";". Check this carefully.',
'import_configure_form' => 'Form', 'import_configure_form' => 'Basic CSV import options',
'header_help' => 'Check this if the first row of your CSV file are the column titles', 'header_help' => 'Check this if the first row of your CSV file are the column titles',
'date_help' => 'Date time format in your CSV. Follow the format like <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">this page</a> indicates. The default value will parse dates that look like this: :dateExample.', 'date_help' => 'Date time format in your CSV. Follow the format like <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">this page</a> indicates. The default value will parse dates that look like this: :dateExample.',
'delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.', 'delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
@@ -24,7 +24,6 @@ return [
// roles // roles
'column_roles_title' => 'Define column roles', 'column_roles_title' => 'Define column roles',
'column_roles_text' => '<p>Firefly III cannot guess what data each column contains. You must tell Firefly which kinds of data to expect. The example data can guide you into picking the correct type from the dropdown. If a column cannot be matched to a useful data type, please let me know <a href="https://github.com/JC5/firefly-iii/issues/new">by creating an issue</a>.</p><p>Some values in your CSV file, such as account names or categories, may already exist in your Firefly III database. If you select "map these values" Firefly will not attempt to search for matching values itself but allow you to match the CSV values against the values in your database. This allows you to fine-tune the import.</p>',
'column_roles_table' => 'Table', 'column_roles_table' => 'Table',
'column_name' => 'Name of column', 'column_name' => 'Name of column',
'column_example' => 'Column example data', 'column_example' => 'Column example data',

View File

@@ -67,11 +67,25 @@ return [
'warning_much_data' => ':days days of data may take a while to load.', 'warning_much_data' => ':days days of data may take a while to load.',
'registered' => 'You have registered successfully!', 'registered' => 'You have registered successfully!',
'search' => 'Search', 'search' => 'Search',
'search_found_accounts' => 'Found :count account(s) for your query.',
'search_found_categories' => 'Found :count category(ies) for your query.',
'search_found_budgets' => 'Found :count budget(s) for your query.',
'search_found_tags' => 'Found :count tag(s) for your query.',
'search_found_transactions' => 'Found :count transaction(s) for your query.',
'results_limited' => 'The results are limited to :count entries.',
'tagbalancingAct' => 'Balancing act',
'tagadvancePayment' => 'Advance payment',
'tagnothing' => '',
'Default asset account' => 'Default asset account',
'no_budget_pointer' => 'You seem to have no budgets yet. You should create some on the <a href="/budgets">budgets</a>-page. Budgets can help you keep track of expenses.', 'no_budget_pointer' => 'You seem to have no budgets yet. You should create some on the <a href="/budgets">budgets</a>-page. Budgets can help you keep track of expenses.',
'Savings account' => 'Savings account',
'Credit card' => 'Credit card',
'source_accounts' => 'Source account(s)', 'source_accounts' => 'Source account(s)',
'destination_accounts' => 'Destination account(s)', 'destination_accounts' => 'Destination account(s)',
'user_id_is' => 'Your user id is <strong>:user</strong>', 'user_id_is' => 'Your user id is <strong>:user</strong>',
'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.', 'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.',
'need_more_help' => 'If you need more help using Firefly III, please <a href="https://github.com/JC5/firefly-iii/issues">open a ticker on Github</a>.',
'nothing_to_display' => 'There are no transactions to show you',
// repeat frequencies: // repeat frequencies:
'repeat_freq_yearly' => 'yearly', 'repeat_freq_yearly' => 'yearly',
@@ -842,14 +856,9 @@ return [
'import_complete_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.', 'import_complete_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.',
'import_download_config' => 'Download configuration', 'import_download_config' => 'Download configuration',
'import_start_import' => 'Start import', 'import_start_import' => 'Start import',
'import_intro_beta' => 'The import function of Firefly III is in beta. Many users of Firefly III have tried many different files. Although each individual compontent of this import routine works (really), the combination might break. If your file cannot be imported by Firefly, please read <a href="https://github.com/JC5/firefly-iii/wiki/Submit-issues-with-sensitive-data-in-them">this wiki page</a> so I can fix the problem you have run into.',
'import_data' => 'Import data', 'import_data' => 'Import data',
'import_data_full' => 'Import data into Firefly III', 'import_data_full' => 'Import data into Firefly III',
'import' => 'Import', 'import' => 'Import',
'import_intro_what_it_does' => 'This page allows you to import data into Firefly III. To do so, export data from your bank, or from another financial management system. Upload that file here. Firefly III will convert the data. You need to give it some directions. Please select a file and follow the instructions.',
'import_intro_import_conf_title' => 'Import "configuration"',
'import_intro_beta_warning' => 'Warning',
'import_intro_import_conf_text' => 'As you will discover over the next few pages, this import routine has a lot of settings. These settings are mainly dependent on the bank (or financial management software) your file comes from. There is a good chance somebody else already imported such a file and has shared their <em>configuration file</em>. Please visit the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong> to see if there already is a configuration available for your bank or system. If there is, you should download this configuration file and upload it here as well. It will save you a lot of time!',
'import_file_help' => 'Select your file', 'import_file_help' => 'Select your file',
'import_status_settings_complete' => 'The import is ready to start.', 'import_status_settings_complete' => 'The import is ready to start.',
'import_status_import_complete' => 'The import has completed.', 'import_status_import_complete' => 'The import has completed.',
@@ -865,11 +874,9 @@ return [
'import_double' => 'Row #:row: This row has been imported before, and is stored in <a href=":link">:description</a>.', 'import_double' => 'Row #:row: This row has been imported before, and is stored in <a href=":link">:description</a>.',
'import_finished_all' => 'The import has finished. Please check out the results below.', 'import_finished_all' => 'The import has finished. Please check out the results below.',
'import_with_key' => 'Import with key \':key\'', 'import_with_key' => 'Import with key \':key\'',
'import_share_configuration' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.',
'import_share_configuration' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.', 'import_finished_report' => 'The import has finished. Please note any errors in the block above this line. All transactions imported during this particular session have been tagged, and you can check them out below. ',
'import_finished_link' => 'The transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.',
'import_finished_report' => 'The import has finished. Please note any errors in the block above this line. All transactions imported during this particular session have been tagged, and you can check them out below. ', 'need_at_least_one_account' => 'You need at least one asset account to be able to create piggy banks',
'import_finished_link' => 'The transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.', 'see_help_top_right' => 'For more information, please check out the help pages using the icon in the top right corner of the page.',
]; ];

View File

@@ -22,7 +22,7 @@ return [
| |
*/ */
'failed' => 'These credentials do not match our records.', 'failed' => '帳號或密碼錯誤。',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 'throttle' => '登入失敗次數過多,請等待 :seconds 秒後再試。',
]; ];

View File

@@ -15,7 +15,7 @@ return [
'import_configure_title' => '匯入設定', 'import_configure_title' => '匯入設定',
'import_configure_intro' => '這裡有一些 CSV 匯入選項。請檢查你的 CSV 檔的第一列是否包含欄位名稱,和你的日期格式是什麼。你可能需要嘗試幾次來調整正確。欄位分隔符號是通常 ",",但也可能是";";仔細檢查這一點。', 'import_configure_intro' => '這裡有一些 CSV 匯入選項。請檢查你的 CSV 檔的第一列是否包含欄位名稱,和你的日期格式是什麼。你可能需要嘗試幾次來調整正確。欄位分隔符號是通常 ",",但也可能是";";仔細檢查這一點。',
'import_configure_form' => '表單', 'import_configure_form' => 'Basic CSV import options',
'header_help' => 'CSV 檔的第一行是標題', 'header_help' => 'CSV 檔的第一行是標題',
'date_help' => 'CSV 內的日期格式。請跟從<a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">這頁</a>內的格式來填寫。 系統預設能夠解析像這樣的日期: :dateExample 。', 'date_help' => 'CSV 內的日期格式。請跟從<a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">這頁</a>內的格式來填寫。 系統預設能夠解析像這樣的日期: :dateExample 。',
'delimiter_help' => '請選擇你的檔案中所使用的欄位分隔符號。如果不肯定的話,逗號是最安全的選項。', 'delimiter_help' => '請選擇你的檔案中所使用的欄位分隔符號。如果不肯定的話,逗號是最安全的選項。',
@@ -24,7 +24,6 @@ return [
// roles // roles
'column_roles_title' => '定義欄的內容', 'column_roles_title' => '定義欄的內容',
'column_roles_text' => '<p>Firefly III 猜不出每一欄中儲存了什麼資料。你必須告訴 Firefly 每一欄中有什麼資料。 下列的示範資料可以幫助你從列表中選擇正確類型。如果有欄位不能配對到有用的類型,請<a href="https://github.com/JC5/firefly-iii/issues/new">告訴我 (只有英語版本)</a>。</p><p>你的 CSV 檔中某些欄位可能已經存在於 Firefly III 的資料庫內,例如帳號名稱,或類別。如果你選擇「配對這些資料」, Firefly 會請你手動配對 CSV 檔和資料庫內的資料。這容許你微調你的匯入設定。</p>',
'column_roles_table' => '表格', 'column_roles_table' => '表格',
'column_name' => '欄位名稱', 'column_name' => '欄位名稱',
'column_example' => '欄的示例資料', 'column_example' => '欄的示例資料',

View File

@@ -51,8 +51,8 @@ return [
'flash_info_multiple' => '有一個訊息|有 :count 個訊息', 'flash_info_multiple' => '有一個訊息|有 :count 個訊息',
'flash_error_multiple' => '出現了一個錯誤|出現了 :count 個錯誤', 'flash_error_multiple' => '出現了一個錯誤|出現了 :count 個錯誤',
'net_worth' => '淨值', 'net_worth' => '淨值',
'route_has_no_help' => 'There is no help for this route.', 'route_has_no_help' => '目前還沒有說明。',
'help_may_not_be_your_language' => 'This help text is in English. It is not yet available in your language', 'help_may_not_be_your_language' => '這個說明還沒有中文版本,將會顯示英文版本。',
'two_factor_welcome' => '哈囉, :user ', 'two_factor_welcome' => '哈囉, :user ',
'two_factor_enter_code' => '若要繼續,請輸入你的雙重身份驗證 2FA 應用程序內顯示的驗證代碼。', 'two_factor_enter_code' => '若要繼續,請輸入你的雙重身份驗證 2FA 應用程序內顯示的驗證代碼。',
'two_factor_code_here' => '在此輸入代碼', 'two_factor_code_here' => '在此輸入代碼',
@@ -67,11 +67,25 @@ return [
'warning_much_data' => ':days 天的資料需要一點時間載入。', 'warning_much_data' => ':days 天的資料需要一點時間載入。',
'registered' => '您已成功註冊 ', 'registered' => '您已成功註冊 ',
'search' => '搜尋', 'search' => '搜尋',
'search_found_accounts' => 'Found :count account(s) for your query.',
'search_found_categories' => 'Found :count category(ies) for your query.',
'search_found_budgets' => 'Found :count budget(s) for your query.',
'search_found_tags' => 'Found :count tag(s) for your query.',
'search_found_transactions' => 'Found :count transaction(s) for your query.',
'results_limited' => 'The results are limited to :count entries.',
'tagbalancingAct' => 'Balancing act',
'tagadvancePayment' => 'Advance payment',
'tagnothing' => '',
'Default asset account' => 'Default asset account',
'no_budget_pointer' => '你還沒有預算。你可以在<a href="/budgets">預算</a>頁來建立預算。預算可以幫助你跟蹤支出情況。', 'no_budget_pointer' => '你還沒有預算。你可以在<a href="/budgets">預算</a>頁來建立預算。預算可以幫助你跟蹤支出情況。',
'Savings account' => 'Savings account',
'Credit card' => 'Credit card',
'source_accounts' => '來源帳戶', 'source_accounts' => '來源帳戶',
'destination_accounts' => '目標帳戶', 'destination_accounts' => '目標帳戶',
'user_id_is' => 'Your user id is <strong>:user</strong>', 'user_id_is' => 'Your user id is <strong>:user</strong>',
'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.', 'field_supports_markdown' => 'This field supports <a href="https://en.support.wordpress.com/markdown-quick-reference/">Markdown</a>.',
'need_more_help' => 'If you need more help using Firefly III, please <a href="https://github.com/JC5/firefly-iii/issues">open a ticker on Github</a>.',
'nothing_to_display' => 'There are no transactions to show you',
// repeat frequencies: // repeat frequencies:
'repeat_freq_yearly' => 'yearly', 'repeat_freq_yearly' => 'yearly',
@@ -239,8 +253,8 @@ return [
'rule_action_set_description_choice' => '把描述設置為…', 'rule_action_set_description_choice' => '把描述設置為…',
'rule_action_append_description_choice' => '描述後加上…', 'rule_action_append_description_choice' => '描述後加上…',
'rule_action_prepend_description_choice' => '描述前加上…', 'rule_action_prepend_description_choice' => '描述前加上…',
'rule_action_set_source_account_choice' => 'Set source account to...', 'rule_action_set_source_account_choice' => '把來源帳戶設置為...',
'rule_action_set_source_account' => 'Set source account to :action_value', 'rule_action_set_source_account' => '將來源帳戶設置為 :action_value',
'rule_action_set_destination_account_choice' => 'Set destination account to...', 'rule_action_set_destination_account_choice' => 'Set destination account to...',
'rule_action_set_destination_account' => 'Set destination account to :action_value', 'rule_action_set_destination_account' => 'Set destination account to :action_value',
@@ -379,7 +393,7 @@ return [
'convert_please_set_expense_destination' => 'Please pick the expense account where the money will go to.', 'convert_please_set_expense_destination' => 'Please pick the expense account where the money will go to.',
'convert_please_set_asset_source' => 'Please pick the asset account where the money will come from.', 'convert_please_set_asset_source' => 'Please pick the asset account where the money will come from.',
'convert_explanation_withdrawal_deposit' => 'If you convert this withdrawal into a deposit, :amount will be deposited into <a href=":sourceRoute">:sourceName</a> instead of taken from it.', 'convert_explanation_withdrawal_deposit' => 'If you convert this withdrawal into a deposit, :amount will be deposited into <a href=":sourceRoute">:sourceName</a> instead of taken from it.',
'convert_explanation_withdrawal_transfer' => 'If you convert this withdrawal into a transfer, :amount will be transferred from <a href=":sourceRoute">:sourceName</a> to a new asset account, instead of being paid to <a href=":destinationRoute">:destinationName</a>.', 'convert_explanation_withdrawal_transfer' => '如果你把這個提款(支出)轉換為轉帳, :amount 會從 <a href=":sourceRoute">:sourceName</a> 轉帳到新的資產帳戶,而不會付款到 <a href=":destinationRoute">:destinationName</a>',
'convert_explanation_deposit_withdrawal' => 'If you convert this deposit into a withdrawal, :amount will be removed from <a href=":destinationRoute">:destinationName</a> instead of added to it.', 'convert_explanation_deposit_withdrawal' => 'If you convert this deposit into a withdrawal, :amount will be removed from <a href=":destinationRoute">:destinationName</a> instead of added to it.',
'convert_explanation_deposit_transfer' => 'If you convert this deposit into a transfer, :amount will be transferred from an asset account of your choice into <a href=":destinationRoute">:destinationName</a>.', 'convert_explanation_deposit_transfer' => 'If you convert this deposit into a transfer, :amount will be transferred from an asset account of your choice into <a href=":destinationRoute">:destinationName</a>.',
'convert_explanation_transfer_withdrawal' => 'If you convert this transfer into a withdrawal, :amount will go from <a href=":sourceRoute">:sourceName</a> to a new destination as an expense, instead of to <a href=":destinationRoute">:destinationName</a> as a transfer.', 'convert_explanation_transfer_withdrawal' => 'If you convert this transfer into a withdrawal, :amount will go from <a href=":sourceRoute">:sourceName</a> to a new destination as an expense, instead of to <a href=":destinationRoute">:destinationName</a> as a transfer.',
@@ -842,14 +856,9 @@ return [
'import_complete_text' => '匯入程序已準備妥當。你已完成所有設定。請下載設定檔,當你的匯入出現問題時它將幫上忙。若要執行匯入程序,你可以在您的伺服器上執行以下命令,或運行網頁導入程序。根據您的配置,在伺服器上執行命令或會給你更多的資訊。', 'import_complete_text' => '匯入程序已準備妥當。你已完成所有設定。請下載設定檔,當你的匯入出現問題時它將幫上忙。若要執行匯入程序,你可以在您的伺服器上執行以下命令,或運行網頁導入程序。根據您的配置,在伺服器上執行命令或會給你更多的資訊。',
'import_download_config' => 'Download configuration', 'import_download_config' => 'Download configuration',
'import_start_import' => '開始匯入', 'import_start_import' => '開始匯入',
'import_intro_beta' => 'Firefly III 的匯入功能依然在測試階段。很多 Firefly III 的用戶已經成功使用這個功能匯入不同的檔案。儘管這個匯入功能的每個部分都能夠正常運作(我說真的),但是整個功能或者會有點問題。如果你的檔案不能匯入到 Firefly 內,請閱讀<a href="https://github.com/JC5/firefly-iii/wiki/Submit-issues-with-sensitive-data-in-them">這個維基頁面</a>,以方便我修復你所遇到的問題。',
'import_data' => '匯入資料', 'import_data' => '匯入資料',
'import_data_full' => '匯入資料到 Firefly III', 'import_data_full' => '匯入資料到 Firefly III',
'import' => '匯入', 'import' => '匯入',
'import_intro_what_it_does' => 'This page allows you to import data into Firefly III. To do so, export data from your bank, or from another financial management system. Upload that file here. Firefly III will convert the data. You need to give it some directions. Please select a file and follow the instructions.',
'import_intro_import_conf_title' => 'Import "configuration"',
'import_intro_beta_warning' => 'Warning',
'import_intro_import_conf_text' => 'As you will discover over the next few pages, this import routine has a lot of settings. These settings are mainly dependent on the bank (or financial management software) your file comes from. There is a good chance somebody else already imported such a file and has shared their <em>configuration file</em>. Please visit the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong> to see if there already is a configuration available for your bank or system. If there is, you should download this configuration file and upload it here as well. It will save you a lot of time!',
'import_file_help' => 'Select your file', 'import_file_help' => 'Select your file',
'import_status_settings_complete' => '匯入已準備妥當,可以開始。', 'import_status_settings_complete' => '匯入已準備妥當,可以開始。',
'import_status_import_complete' => '匯入已完成。', 'import_status_import_complete' => '匯入已完成。',
@@ -865,11 +874,9 @@ return [
'import_double' => '行 #:row 這行曾被匯入過,並已儲存在<a href=":link">:description</a>。', 'import_double' => '行 #:row 這行曾被匯入過,並已儲存在<a href=":link">:description</a>。',
'import_finished_all' => '匯入已完成。請檢查下列的結果。', 'import_finished_all' => '匯入已完成。請檢查下列的結果。',
'import_with_key' => '以鍵 \':key\' 作匯入', 'import_with_key' => '以鍵 \':key\' 作匯入',
'import_share_configuration' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.',
'import_share_configuration' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.', 'import_finished_report' => '匯入已完成。請留意在這行上面的錯誤記錄。這次所匯入的所有交易都已經進行標記,你可以在下面查看。 ',
'import_finished_link' => '匯入成功的所有交易都可以在標籤 <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a> 內找到。',
'import_finished_report' => '匯入已完成。請留意在這行上面的錯誤記錄。這次所匯入的所有交易都已經進行標記,你可以在下面查看。 ', 'need_at_least_one_account' => 'You need at least one asset account to be able to create piggy banks',
'import_finished_link' => '匯入成功的所有交易都可以在標籤 <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a> 內找到。', 'see_help_top_right' => 'For more information, please check out the help pages using the icon in the top right corner of the page.',
]; ];

View File

@@ -31,13 +31,13 @@ return [
'journal_source_account_id' => '資產帳戶 (源頭)', 'journal_source_account_id' => '資產帳戶 (源頭)',
'account_from_id' => '從帳戶', 'account_from_id' => '從帳戶',
'account_to_id' => '到帳戶', 'account_to_id' => '到帳戶',
'source_account' => 'Source account', 'source_account' => '來源帳戶',
'destination_account' => 'Destination account', 'destination_account' => '目標帳戶',
'journal_destination_account_id' => '資產帳戶 (目標)', 'journal_destination_account_id' => '資產帳戶 (目標)',
'asset_destination_account' => '資產帳戶 (目標)', 'asset_destination_account' => '資產帳戶 (目標)',
'asset_source_account' => '資產帳戶 (來源)', 'asset_source_account' => '資產帳戶 (來源)',
'journal_description' => '描述', 'journal_description' => '描述',
'note' => 'Notes', 'note' => '備註',
'split_journal' => '分割此交易', 'split_journal' => '分割此交易',
'split_journal_explanation' => '分割這個交易為幾個部分', 'split_journal_explanation' => '分割這個交易為幾個部分',
'currency' => '貨幣', 'currency' => '貨幣',
@@ -61,11 +61,11 @@ return [
'expense_account' => '支出帳戶', 'expense_account' => '支出帳戶',
'revenue_account' => '收入帳戶', 'revenue_account' => '收入帳戶',
'revenue_account_source' => 'Revenue account (source)', 'revenue_account_source' => '收入帳戶 (源頭)',
'source_account_asset' => 'Source account (asset account)', 'source_account_asset' => '來源帳戶 (資產帳戶)',
'destination_account_expense' => 'Destination account (expense account)', 'destination_account_expense' => 'Destination account (expense account)',
'destination_account_asset' => 'Destination account (asset account)', 'destination_account_asset' => 'Destination account (asset account)',
'source_account_revenue' => 'Source account (revenue account)', 'source_account_revenue' => '來源帳戶 (收入帳戶)',
'type' => 'Type', 'type' => 'Type',
'convert_Withdrawal' => 'Convert withdrawal', 'convert_Withdrawal' => 'Convert withdrawal',
'convert_Deposit' => 'Convert deposit', 'convert_Deposit' => 'Convert deposit',

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