firefly-iii/app/Helpers/Report/AccountReportHelper.php

133 lines
4.6 KiB
PHP
Raw Normal View History

<?php
2016-02-05 05:08:25 -06:00
declare(strict_types = 1);
/**
* AccountReportHelper.php
2016-04-01 09:44:46 -05:00
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace FireflyIII\Helpers\Report;
2016-01-27 13:48:35 -06:00
use Carbon\Carbon;
use DB;
use FireflyIII\Helpers\Collection\Account as AccountCollection;
use FireflyIII\Models\Account;
use Illuminate\Support\Collection;
/**
* Class AccountReportHelper
*
* @package FireflyIII\Helpers\Report
*/
class AccountReportHelper implements AccountReportHelperInterface
{
2016-01-27 13:48:35 -06:00
/**
* This method generates a full report for the given period on all
* given accounts
*
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts
*
* @return AccountCollection
*/
2016-04-06 09:37:28 -05:00
public function getAccountReport(Carbon $start, Carbon $end, Collection $accounts): AccountCollection
2016-01-27 13:48:35 -06:00
{
$startAmount = '0';
$endAmount = '0';
$diff = '0';
$ids = $accounts->pluck('id')->toArray();
2016-04-27 03:38:51 -05:00
$yesterday = clone $start;
2016-01-27 13:48:35 -06:00
$yesterday->subDay();
// get balances for start.
2016-04-27 03:38:51 -05:00
$startSet = $this->getSet($ids, $yesterday);
2016-01-27 13:48:35 -06:00
2016-02-08 13:59:09 -06:00
// a special consideration for accounts that did exist on this exact day.
// we also grab the balance from today just in case, to see if that changes things.
// it's a fall back for users who (rightly so) start keeping score at the first of
// the month and find the first report lacking / broken.
2016-04-27 03:38:51 -05:00
$backupSet = $this->getSet($ids, $start);
2016-02-08 13:59:09 -06:00
2016-01-27 13:48:35 -06:00
// and end:
2016-04-27 03:38:51 -05:00
$endSet = $this->getSet($ids, $end);
2016-01-27 13:48:35 -06:00
$accounts->each(
2016-02-08 13:59:09 -06:00
function (Account $account) use ($startSet, $endSet, $backupSet) {
2016-01-27 13:48:35 -06:00
/**
* The balance for today always incorporates transactions
* made on today. So to get todays "start" balance, we sub one
* day.
*/
$account->startBalance = '0';
$account->endBalance = '0';
$currentStart = $startSet->filter(
2016-01-27 13:48:35 -06:00
function (Account $entry) use ($account) {
return $account->id == $entry->id;
}
);
2016-02-08 13:59:09 -06:00
// grab entry from current backup as well:
$currentBackup = $backupSet->filter(
function (Account $entry) use ($account) {
return $account->id == $entry->id;
}
);
2016-01-27 13:48:35 -06:00
if ($currentStart->first()) {
$account->startBalance = $currentStart->first()->balance;
2016-02-08 13:59:09 -06:00
} else {
if (is_null($currentStart->first()) && !is_null($currentBackup->first())) {
$account->startBalance = $currentBackup->first()->balance;
}
2016-01-27 13:48:35 -06:00
}
$currentEnd = $endSet->filter(
function (Account $entry) use ($account) {
return $account->id == $entry->id;
}
);
if ($currentEnd->first()) {
$account->endBalance = $currentEnd->first()->balance;
}
}
);
// summarize:
foreach ($accounts as $account) {
$startAmount = bcadd($startAmount, $account->startBalance);
$endAmount = bcadd($endAmount, $account->endBalance);
$diff = bcadd($diff, bcsub($account->endBalance, $account->startBalance));
}
$object = new AccountCollection;
$object->setStart($startAmount);
$object->setEnd($endAmount);
$object->setDifference($diff);
$object->setAccounts($accounts);
2016-01-27 13:48:35 -06:00
return $object;
}
2016-04-27 03:38:51 -05:00
/**
* @param array $ids
* @param Carbon $date
*
* @return Collection
*/
private function getSet(array $ids, Carbon $date): Collection
{
Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->whereIn('accounts.id', $ids)
->whereNull('transaction_journals.deleted_at')
->whereNull('transactions.deleted_at')
->where('transaction_journals.date', '<=', $date->format('Y-m-d'))
->groupBy('accounts.id')
->get(['accounts.id', DB::raw('SUM(`transactions`.`amount`) as `balance`')]);
}
}