Some query optimisations for the audit report

This commit is contained in:
James Cole 2016-04-08 15:10:07 +02:00
parent 33bf373151
commit d783d05462
No known key found for this signature in database
GPG Key ID: C16961E655E74B5E
2 changed files with 71 additions and 91 deletions

View File

@ -7,7 +7,7 @@ use FireflyIII\Helpers\Report\BalanceReportHelperInterface;
use FireflyIII\Helpers\Report\BudgetReportHelperInterface;
use FireflyIII\Helpers\Report\ReportHelperInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use Illuminate\Support\Collection;
use Log;
@ -102,22 +102,22 @@ class ReportController extends Controller
$start = session('first');
}
View::share(
'subTitle', trans(
'firefly.report_' . $reportType,
[
'start' => $start->formatLocalized($this->monthFormat),
'end' => $end->formatLocalized($this->monthFormat),
]
)
);
View::share('subTitleIcon', 'fa-calendar');
switch ($reportType) {
default:
throw new FireflyException('Unfortunately, reports of the type "' . e($reportType) . '" are not yet available. ');
case 'default':
View::share(
'subTitle', trans(
'firefly.report_default',
[
'start' => $start->formatLocalized($this->monthFormat),
'end' => $end->formatLocalized($this->monthFormat),
]
)
);
View::share('subTitleIcon', 'fa-calendar');
// more than one year date difference means year report.
if ($start->diffInMonths($end) > 12) {
return $this->defaultMultiYear($reportType, $start, $end, $accounts);
@ -127,9 +127,10 @@ class ReportController extends Controller
return $this->defaultYear($reportType, $start, $end, $accounts);
}
// otherwise default
return $this->defaultMonth($reportType, $start, $end, $accounts);
case 'audit':
// always default
return $this->auditReport($start, $end, $accounts);
}
@ -145,26 +146,14 @@ class ReportController extends Controller
*/
private function auditReport(Carbon $start, Carbon $end, Collection $accounts)
{
bcscale(2);
/** @var ARI $repos */
$repos = app('FireflyIII\Repositories\Account\AccountRepositoryInterface');
View::share(
'subTitle', trans(
'firefly.report_audit',
[
'start' => $start->formatLocalized($this->monthFormat),
'end' => $end->formatLocalized($this->monthFormat),
]
)
);
View::share('subTitleIcon', 'fa-calendar');
$repos = app('FireflyIII\Repositories\Account\AccountRepositoryInterface');
$auditData = [];
$dayBefore = clone $start;
$dayBefore->subDay();
/** @var Account $account */
foreach ($accounts as $account) {
// balance the day before:
$id = $account->id;
$first = $repos->oldestJournalDate($account);
@ -173,34 +162,38 @@ class ReportController extends Controller
$journals = new Collection;
$dayBeforeBalance = Steam::balance($account, $dayBefore);
/*
* Is there even activity on this account between the requested dates?
*/
if ($start->between($first, $last) || $end->between($first, $last)) {
$exists = true;
$journals = $repos->getJournalsInRange($account, $start, $end);
$journals = $journals->reverse();
}
/*
* Reverse set, get balances.
*/
$journals = $journals->reverse();
$startBalance = $dayBeforeBalance;
/** @var TransactionJournal $journal */
foreach ($journals as $journal) {
$journal->before = $startBalance;
$journal->before = $startBalance;
$transactionAmount = $journal->source_amount;
// get currently relevant transaction:
$transaction = $journal->transactions->filter(
function (Transaction $t) use ($account) {
return $t->account_id === $account->id;
}
)->first();
$newBalance = bcadd($startBalance, $transaction->amount);
if (intval($journal->destination_account_id) === $account->id) {
$transactionAmount = $journal->destination_amount;
}
$newBalance = bcadd($startBalance, $transactionAmount);
$journal->after = $newBalance;
$startBalance = $newBalance;
}
$journals = $journals->reverse();
$auditData[$id]['journals'] = $journals;
/*
* Reverse set again.
*/
$auditData[$id]['journals'] = $journals->reverse();
$auditData[$id]['exists'] = $exists;
$auditData[$id]['end'] = $end->formatLocalized(trans('config.month_and_day'));
$auditData[$id]['endBalance'] = Steam::balance($account, $end);

View File

@ -14,6 +14,7 @@ use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
@ -253,6 +254,31 @@ class AccountRepository implements AccountRepositoryInterface
return $set;
}
/**
* Returns a list of transactions TO the given (asset) $account, but none from the
* given list of accounts
*
* @param Account $account
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getIncomeByDestination(Account $account, Collection $accounts, Carbon $start, Carbon $end): Collection
{
$ids = $accounts->pluck('id')->toArray();
$journals = $this->user->transactionjournals()
->expanded()
->before($end)
->where('source_account.id', $account->id)
->whereIn('destination_account.id', $ids)
->after($start)
->get(TransactionJournal::QUERYFIELDS);
return $journals;
}
/**
* @param Account $account
* @param int $page
@ -290,27 +316,16 @@ class AccountRepository implements AccountRepositoryInterface
public function getJournalsInRange(Account $account, Carbon $start, Carbon $end): Collection
{
$query = $this->user
->transactionJournals()
->expanded()
->with(
[
'transactions' => function (HasMany $q) {
$q->orderBy('amount', 'ASC');
},
'transactionType',
'transactionCurrency',
'budgets',
'categories',
'bill',
]
)
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.account_id', $account->id)
->after($start)
->before($end)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC');
->transactionJournals()
->expanded()
->where(
function (Builder $q) use ($account) {
$q->where('destination_account.id', $account->id);
$q->orWhere('source_account.id', $account->id);
}
)
->after($start)
->before($end);
$set = $query->get(TransactionJournal::QUERYFIELDS);
@ -334,7 +349,6 @@ class AccountRepository implements AccountRepositoryInterface
if (count($ids) > 0) {
$accounts = $this->user->accounts()->whereIn('id', $ids)->where('accounts.active', 1)->get();
}
bcscale(2);
$accounts->each(
function (Account $account) use ($start, $end) {
@ -375,8 +389,6 @@ class AccountRepository implements AccountRepositoryInterface
$start = clone Session::get('start', new Carbon);
$end = clone Session::get('end', new Carbon);
bcscale(2);
$accounts->each(
function (Account $account) use ($start, $end) {
$account->startBalance = Steam::balance($account, $start);
@ -761,29 +773,4 @@ class AccountRepository implements AccountRepositoryInterface
}
}
/**
* Returns a list of transactions TO the given (asset) $account, but none from the
* given list of accounts
*
* @param Account $account
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getIncomeByDestination(Account $account, Collection $accounts, Carbon $start, Carbon $end): Collection
{
$ids = $accounts->pluck('id')->toArray();
$journals = $this->user->transactionjournals()
->expanded()
->before($end)
->where('source_account.id', $account->id)
->whereIn('destination_account.id', $ids)
->after($start)
->get(TransactionJournal::QUERYFIELDS);
return $journals;
}
}