mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Expanded reports.
This commit is contained in:
parent
84a24f0333
commit
9f23462c42
@ -71,6 +71,7 @@ class ReportController extends BaseController
|
||||
$budgets = $this->_repository->getBudgetsForMonth($date);
|
||||
$categories = $this->_repository->getCategoriesForMonth($date, 10);
|
||||
$accounts = $this->_repository->getAccountsForMonth($date);
|
||||
$piggyBanks = $this->_repository->getPiggyBanksForMonth($date);
|
||||
|
||||
return View::make(
|
||||
'reports.month',
|
||||
|
@ -389,7 +389,12 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData
|
||||
if ($category) {
|
||||
$journal->categories()->sync([$category->id]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
$journal->categories()->sync([]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,6 +96,8 @@ class FF3ServiceProvider extends ServiceProvider
|
||||
|
||||
// reports
|
||||
$this->app->bind('FireflyIII\Report\ReportInterface', 'FireflyIII\Report\Report');
|
||||
$this->app->bind('FireflyIII\Report\ReportQueryInterface', 'FireflyIII\Report\ReportQuery');
|
||||
$this->app->bind('FireflyIII\Report\ReportHelperInterface', 'FireflyIII\Report\ReportHelper');
|
||||
|
||||
// chart
|
||||
$this->app->bind('FireflyIII\Chart\ChartInterface', 'FireflyIII\Chart\Chart');
|
||||
|
@ -6,11 +6,12 @@ use Carbon\Carbon;
|
||||
use FireflyIII\Database\Account\Account as AccountRepository;
|
||||
use FireflyIII\Database\SwitchUser;
|
||||
use FireflyIII\Database\TransactionJournal\TransactionJournal as JournalRepository;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
use stdClass;
|
||||
|
||||
// todo add methods to itnerface
|
||||
// todo add methods to interface
|
||||
|
||||
/**
|
||||
* Class Report
|
||||
@ -25,9 +26,12 @@ class Report implements ReportInterface
|
||||
|
||||
/** @var AccountRepository */
|
||||
protected $_accounts;
|
||||
|
||||
/** @var \FireflyIII\Report\ReportHelperInterface */
|
||||
protected $_helper;
|
||||
/** @var JournalRepository */
|
||||
protected $_journals;
|
||||
/** @var \FireflyIII\Report\ReportQueryInterface */
|
||||
protected $_queries;
|
||||
|
||||
/**
|
||||
* @param AccountRepository $accounts
|
||||
@ -36,10 +40,15 @@ class Report implements ReportInterface
|
||||
{
|
||||
$this->_accounts = $accounts;
|
||||
$this->_journals = $journals;
|
||||
$this->_queries = \App::make('FireflyIII\Report\ReportQueryInterface');
|
||||
$this->_helper = \App::make('FireflyIII\Report\ReportHelperInterface');
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO Used in yearly report, so not ready for cleanup.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param int $limit
|
||||
@ -76,7 +85,7 @@ class Report implements ReportInterface
|
||||
->where('acm_from.data', '!=', '"sharedExpense"')
|
||||
->before($end)->after($start)
|
||||
->where('transaction_journals.user_id', \Auth::user()->id)
|
||||
->groupBy('account_id')->orderBy('sum', 'DESC')->limit(15)
|
||||
->groupBy('account_id')->orderBy('sum', 'DESC')->limit($limit)
|
||||
->get(['t_to.account_id as account_id', 'ac_to.name as name', \DB::Raw('SUM(t_to.amount) as `sum`')]);
|
||||
|
||||
|
||||
@ -85,7 +94,7 @@ class Report implements ReportInterface
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return Collection
|
||||
* @return array
|
||||
*/
|
||||
public function getAccountsForMonth(Carbon $date)
|
||||
{
|
||||
@ -93,31 +102,21 @@ class Report implements ReportInterface
|
||||
$start->startOfMonth();
|
||||
$end = clone $date;
|
||||
$end->endOfMonth();
|
||||
$list = \Auth::user()->accounts()
|
||||
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', "accountRole");
|
||||
}
|
||||
)
|
||||
->whereIn('account_types.type', ['Default account', 'Cash account', 'Asset account'])
|
||||
->where('active', 1)
|
||||
->where(
|
||||
function ($query) {
|
||||
$query->where('account_meta.data', '!=', '"sharedExpense"');
|
||||
$query->orWhereNull('account_meta.data');
|
||||
}
|
||||
)
|
||||
->get(['accounts.*']);
|
||||
$list->each(
|
||||
function (\Account $account) use ($start, $end) {
|
||||
$account->startBalance = \Steam::balance($account, $start);
|
||||
$account->endBalance = \Steam::balance($account, $end);
|
||||
$account->difference = $account->endBalance - $account->startBalance;
|
||||
}
|
||||
);
|
||||
$list = $this->_queries->accountList();
|
||||
$accounts = [];
|
||||
/** @var \Account $account */
|
||||
foreach ($list as $account) {
|
||||
$id = intval($account->id);
|
||||
$accounts[$id] = [
|
||||
'name' => $account->name,
|
||||
'startBalance' => \Steam::balance($account, $start),
|
||||
'endBalance' => \Steam::balance($account, $end)
|
||||
];
|
||||
|
||||
return $list;
|
||||
$accounts[$id]['difference'] = $accounts[$id]['endBalance'] - $accounts[$id]['startBalance'];
|
||||
}
|
||||
|
||||
return $accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,74 +131,29 @@ class Report implements ReportInterface
|
||||
$end = clone $date;
|
||||
$end->endOfMonth();
|
||||
// all budgets
|
||||
/** @var Collection $budgets */
|
||||
$budgets = \Auth::user()->budgets()
|
||||
->leftJoin(
|
||||
'budget_limits', function (JoinClause $join) use ($date) {
|
||||
$join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d'));
|
||||
}
|
||||
)
|
||||
->get(['budgets.*', 'budget_limits.amount as budget_amount']);
|
||||
$amounts = \Auth::user()->transactionjournals()
|
||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('account_meta.data', '!=', '"sharedExpense"')
|
||||
->where('transaction_types.type', 'Withdrawal')
|
||||
->groupBy('budgets.id')
|
||||
->orderBy('name','ASC')
|
||||
->get(['budgets.id', 'budgets.name', \DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]);
|
||||
$set = $this->_queries->getAllBudgets($date);
|
||||
$budgets = $this->_helper->makeArray($set);
|
||||
$amountSet = $this->_queries->journalsByBudget($start, $end);
|
||||
$amounts = $this->_helper->makeArray($amountSet);
|
||||
$combined = $this->_helper->mergeArrays($budgets, $amounts);
|
||||
$combined[0]['spent'] = isset($combined[0]['spent']) ? $combined[0]['spent'] : 0.0;
|
||||
$combined[0]['amount'] = isset($combined[0]['amount']) ? $combined[0]['amount'] : 0.0;
|
||||
$combined[0]['name'] = 'No budget';
|
||||
|
||||
|
||||
$spentNoBudget = 0;
|
||||
foreach ($budgets as $budget) {
|
||||
$budget->spent = 0;
|
||||
foreach ($amounts as $amount) {
|
||||
if (intval($budget->id) == intval($amount->id)) {
|
||||
$budget->spent = floatval($amount->sum) * -1;
|
||||
}
|
||||
if (is_null($amount->id)) {
|
||||
$spentNoBudget = floatval($amount->sum) * -1;
|
||||
}
|
||||
}
|
||||
// find transactions to shared expense accounts, which are without a budget by default:
|
||||
$transfers = $this->_queries->sharedExpenses($start, $end);
|
||||
foreach ($transfers as $transfer) {
|
||||
$combined[0]['spent'] += floatval($transfer->amount) * -1;
|
||||
}
|
||||
|
||||
$noBudget = new stdClass;
|
||||
$noBudget->id = 0;
|
||||
$noBudget->name = '(no budget)';
|
||||
$noBudget->budget_amount = 0;
|
||||
$noBudget->spent = $spentNoBudget;
|
||||
|
||||
// also get transfers to expense accounts (which are without a budget, and grouped).
|
||||
$transfers = $this->getTransfersToSharedAccounts($date);
|
||||
foreach($transfers as $transfer) {
|
||||
$noBudget->spent += floatval($transfer->sum) * -1;
|
||||
}
|
||||
|
||||
|
||||
$budgets->push($noBudget);
|
||||
|
||||
return $budgets;
|
||||
return $combined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
* @param int $limit
|
||||
*
|
||||
* @return Collection
|
||||
* @return array
|
||||
*/
|
||||
public function getCategoriesForMonth(Carbon $date, $limit = 15)
|
||||
{
|
||||
@ -208,58 +162,21 @@ class Report implements ReportInterface
|
||||
$end = clone $date;
|
||||
$end->endOfMonth();
|
||||
// all categories.
|
||||
$amounts = \Auth::user()->transactionjournals()
|
||||
->leftJoin(
|
||||
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
|
||||
)
|
||||
->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('account_meta.data', '!=', '"sharedExpense"')
|
||||
->where('transaction_types.type', 'Withdrawal')
|
||||
->groupBy('categories.id')
|
||||
->orderBy('sum')
|
||||
->get(['categories.id', 'categories.name', \DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]);
|
||||
$spentNoCategory = 0;
|
||||
foreach ($amounts as $amount) {
|
||||
if (is_null($amount->id)) {
|
||||
$spentNoCategory = floatval($amount->sum) * -1;
|
||||
}
|
||||
}
|
||||
$noCategory = new stdClass;
|
||||
$noCategory->id = 0;
|
||||
$noCategory->name = '(no category)';
|
||||
$noCategory->sum = $spentNoCategory;
|
||||
$amounts->push($noCategory);
|
||||
$result = $this->_queries->journalsByCategory($start, $end);
|
||||
$categories = $this->_helper->makeArray($result);
|
||||
|
||||
$return = new Collection;
|
||||
$bottom = new stdClass();
|
||||
$bottom->name = 'Others';
|
||||
$bottom->id = 0;
|
||||
$bottom->sum = 0;
|
||||
// all transfers
|
||||
$result = $this->_queries->sharedExpensesByCategory($start, $end);
|
||||
$transfers = $this->_helper->makeArray($result);
|
||||
$merged = $this->_helper->mergeArrays($categories, $transfers);
|
||||
|
||||
foreach ($amounts as $index => $entry) {
|
||||
if ($index < $limit) {
|
||||
$return->push($entry);
|
||||
} else {
|
||||
$bottom->sum += floatval($entry->sum);
|
||||
}
|
||||
}
|
||||
$return->push($bottom);
|
||||
// sort.
|
||||
$sorted = $this->_helper->sortNegativeArray($merged);
|
||||
|
||||
return $return;
|
||||
// limit to $limit:
|
||||
$cut = $this->_helper->limitArray($sorted, $limit);
|
||||
|
||||
return $cut;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -314,7 +231,7 @@ class Report implements ReportInterface
|
||||
\DB::Raw('SUM(`transactions`.`amount`) * -1 AS `sum`')
|
||||
]
|
||||
);
|
||||
$transfers = $this->getTransfersToSharedAccounts($date);
|
||||
$transfers = $this->getTransfersToSharedGroupedByAccounts($date);
|
||||
// merge $transfers into $set
|
||||
foreach ($transfers as $transfer) {
|
||||
if (!is_null($transfer->account_id)) {
|
||||
@ -409,7 +326,40 @@ class Report implements ReportInterface
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getTransfersToSharedAccounts(Carbon $date)
|
||||
public function getPiggyBanksForMonth(Carbon $date)
|
||||
{
|
||||
$start = clone $date;
|
||||
$start->startOfMonth();
|
||||
$end = clone $date;
|
||||
$end->endOfMonth();
|
||||
|
||||
$set = \PiggyBank::
|
||||
leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
|
||||
->where('accounts.user_id', \Auth::user()->id)
|
||||
->where('repeats', 0)
|
||||
->where(
|
||||
function (Builder $query) use ($start, $end) {
|
||||
$query->whereNull('piggy_banks.deleted_at');
|
||||
$query->orWhere(
|
||||
function (Builder $query) use ($start, $end) {
|
||||
$query->whereNotNull('piggy_banks.deleted_at');
|
||||
$query->where('piggy_banks.deleted_at', '>=', $start->format('Y-m-d 00:00:00'));
|
||||
$query->where('piggy_banks.deleted_at', '<=', $end->format('Y-m-d 00:00:00'));
|
||||
}
|
||||
);
|
||||
}
|
||||
)
|
||||
->get(['piggy_banks.*']);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getTransfersToSharedGroupedByAccounts(Carbon $date)
|
||||
{
|
||||
$start = clone $date;
|
||||
$start->startOfMonth();
|
||||
@ -436,6 +386,7 @@ class Report implements ReportInterface
|
||||
->where('date', '<=', $end->format('Y-m-d'))
|
||||
->where('transaction_types.type', 'Transfer')
|
||||
->where('transaction_journals.user_id', \Auth::user()->id)
|
||||
->groupBy('accounts.name')
|
||||
->get(
|
||||
[
|
||||
'transactions.account_id',
|
||||
@ -445,6 +396,7 @@ class Report implements ReportInterface
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
*
|
||||
|
119
app/lib/FireflyIII/Report/ReportHelper.php
Normal file
119
app/lib/FireflyIII/Report/ReportHelper.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Report;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class ReportHelper
|
||||
*
|
||||
* @package FireflyIII\Report
|
||||
*/
|
||||
class ReportHelper implements ReportHelperInterface
|
||||
{
|
||||
/**
|
||||
* Only return the top X entries, group the rest by amount
|
||||
* and described as 'Others'. id = 0 as well
|
||||
*
|
||||
* @param array $array
|
||||
* @param int $limit
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function limitArray(array $array, $limit = 10)
|
||||
{
|
||||
$others = [
|
||||
'name' => 'Others',
|
||||
'amount' => 0
|
||||
];
|
||||
$return = [];
|
||||
$count = 0;
|
||||
foreach ($array as $id => $entry) {
|
||||
if ($count < ($limit - 1)) {
|
||||
$return[$id] = $entry;
|
||||
} else {
|
||||
$others['amount'] += $entry['amount'];
|
||||
}
|
||||
|
||||
$count++;
|
||||
}
|
||||
$return[0] = $others;
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a collection into an array. Needs the field 'id' for the key,
|
||||
* and saves only 'name' and 'amount' as a subarray.
|
||||
*
|
||||
* @param Collection $collection
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function makeArray(Collection $collection)
|
||||
{
|
||||
$array = [];
|
||||
foreach ($collection as $entry) {
|
||||
$entry->spent = isset($entry->spent) ? floatval($entry->spent) : 0.0;
|
||||
$id = intval($entry->id);
|
||||
if (isset($array[$id])) {
|
||||
$array[$id]['amount'] += floatval($entry->amount);
|
||||
$array[$id]['spent'] += floatval($entry->spent);
|
||||
} else {
|
||||
$array[$id] = [
|
||||
'amount' => floatval($entry->amount),
|
||||
'spent' => floatval($entry->spent),
|
||||
'name' => $entry->name
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges two of the arrays as defined above. Can't handle more (yet)
|
||||
*
|
||||
* @param array $one
|
||||
* @param array $two
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function mergeArrays(array $one, array $two)
|
||||
{
|
||||
foreach ($two as $id => $value) {
|
||||
// $otherId also exists in $one:
|
||||
if (isset($one[$id])) {
|
||||
$one[$id]['amount'] += $value['amount'];
|
||||
$one[$id]['spent'] += $value['spent'];
|
||||
} else {
|
||||
$one[$id] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $one;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort an array where all 'amount' keys are negative floats.
|
||||
*
|
||||
* @param array $array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function sortNegativeArray(array $array)
|
||||
{
|
||||
uasort(
|
||||
$array, function ($left, $right) {
|
||||
if ($left['amount'] == $right['amount']) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ($left['amount'] < $right['amount']) ? -1 : 1;
|
||||
}
|
||||
);
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
55
app/lib/FireflyIII/Report/ReportHelperInterface.php
Normal file
55
app/lib/FireflyIII/Report/ReportHelperInterface.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Report;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface ReportHelperInterface
|
||||
*
|
||||
* @package FireflyIII\Report
|
||||
*/
|
||||
interface ReportHelperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Only return the top X entries, group the rest by amount
|
||||
* and described as 'Others'. id = 0 as well
|
||||
*
|
||||
* @param array $array
|
||||
* @param int $limit
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function limitArray(array $array, $limit = 10);
|
||||
|
||||
/**
|
||||
* Turns a collection into an array. Needs the field 'id' for the key,
|
||||
* and saves 'name', 'amount','spent' (if present) as a subarray.
|
||||
*
|
||||
* @param Collection $collection
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function makeArray(Collection $collection);
|
||||
|
||||
/**
|
||||
* Merges two of the arrays as defined above. Can't handle more (yet)
|
||||
*
|
||||
* @param array $one
|
||||
* @param array $two
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function mergeArrays(array $one, array $two);
|
||||
|
||||
/**
|
||||
* Sort an array where all 'amount' keys are negative floats.
|
||||
*
|
||||
* @param array $array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function sortNegativeArray(array $array);
|
||||
|
||||
}
|
@ -33,20 +33,27 @@ interface ReportInterface
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getTransfersToSharedAccounts(Carbon $date);
|
||||
public function getTransfersToSharedGroupedByAccounts(Carbon $date);
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getPiggyBanksForMonth(Carbon $date);
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
* @param int $limit
|
||||
*
|
||||
* @return Collection
|
||||
* @return array
|
||||
*/
|
||||
public function getCategoriesForMonth(Carbon $date, $limit = 15);
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return Collection
|
||||
* @return array
|
||||
*/
|
||||
public function getAccountsForMonth(Carbon $date);
|
||||
|
||||
@ -58,6 +65,7 @@ interface ReportInterface
|
||||
*/
|
||||
public function getExpenseGroupedForMonth(Carbon $date, $limit = 15);
|
||||
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
* @param bool $shared
|
||||
|
227
app/lib/FireflyIII/Report/ReportQuery.php
Normal file
227
app/lib/FireflyIII/Report/ReportQuery.php
Normal file
@ -0,0 +1,227 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Report;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class ReportQuery
|
||||
*
|
||||
* @package FireflyIII\Report
|
||||
*/
|
||||
class ReportQuery implements ReportQueryInterface
|
||||
{
|
||||
/**
|
||||
* This query retrieves a list of accounts that are active and not shared.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function accountList()
|
||||
{
|
||||
return \Auth::user()->accounts()
|
||||
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', "accountRole");
|
||||
}
|
||||
)
|
||||
->whereIn('account_types.type', ['Default account', 'Cash account', 'Asset account'])
|
||||
->where('active', 1)
|
||||
->where(
|
||||
function ($query) {
|
||||
$query->where('account_meta.data', '!=', '"sharedExpense"');
|
||||
$query->orWhereNull('account_meta.data');
|
||||
}
|
||||
)
|
||||
->get(['accounts.*']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all budgets and if present, the amount of the current BudgetLimit
|
||||
* as well
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAllBudgets(Carbon $date)
|
||||
{
|
||||
return \Auth::user()->budgets()
|
||||
->leftJoin(
|
||||
'budget_limits', function (JoinClause $join) use ($date) {
|
||||
$join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d'));
|
||||
}
|
||||
)
|
||||
->get(['budgets.*', 'budget_limits.amount as amount']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of expenses grouped by the budget they were filed under.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByBudget(Carbon $start, Carbon $end)
|
||||
{
|
||||
return \Auth::user()->transactionjournals()
|
||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('account_meta.data', '!=', '"sharedExpense"')
|
||||
->where('transaction_types.type', 'Withdrawal')
|
||||
->groupBy('budgets.id')
|
||||
->orderBy('name', 'ASC')
|
||||
->get(['budgets.id', 'budgets.name', \DB::Raw('SUM(`transactions`.`amount`) AS `spent`')]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of categories and the expenses therein, grouped by the relevant category.
|
||||
* This result excludes transfers to shared accounts which are expenses, technically.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByCategory(Carbon $start, Carbon $end)
|
||||
{
|
||||
return \Auth::user()->transactionjournals()
|
||||
->leftJoin(
|
||||
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
|
||||
)
|
||||
->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('account_meta.data', '!=', '"sharedExpense"')
|
||||
->where('transaction_types.type', 'Withdrawal')
|
||||
->groupBy('categories.id')
|
||||
->orderBy('amount')
|
||||
->get(['categories.id', 'categories.name', \DB::Raw('SUM(`transactions`.`amount`) AS `amount`')]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of expense accounts and the expenses therein, grouped by that expense account.
|
||||
* This result excludes transfers to shared accounts which are expenses, technically.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByExpenseAccount(Carbon $start, Carbon $end)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* With an equally misleading name, this query returns are transfers to shared accounts. These are considered
|
||||
* expenses.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function sharedExpenses(Carbon $start, Carbon $end)
|
||||
{
|
||||
return \TransactionJournal::
|
||||
leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where(
|
||||
'transactions.amount', '>', 0
|
||||
);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->where('account_meta.data', '"sharedExpense"')
|
||||
->after($start)
|
||||
->before($end)
|
||||
->where('transaction_types.type', 'Transfer')
|
||||
->where('transaction_journals.user_id', \Auth::user()->id)
|
||||
->get(
|
||||
['transaction_journals.id', 'transaction_journals.description', 'transactions.account_id', 'accounts.name',
|
||||
'transactions.amount']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* With a slightly misleading name, this query returns all transfers to shared accounts
|
||||
* which are technically expenses, since it won't be just your money that gets spend.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function sharedExpensesByCategory(Carbon $start, Carbon $end)
|
||||
{
|
||||
return \TransactionJournal::
|
||||
leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where(
|
||||
'transactions.amount', '>', 0
|
||||
);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
|
||||
)
|
||||
->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id')
|
||||
->where('account_meta.data', '"sharedExpense"')
|
||||
->after($start)
|
||||
->before($end)
|
||||
->where('transaction_types.type', 'Transfer')
|
||||
->where('transaction_journals.user_id', \Auth::user()->id)
|
||||
->groupBy('categories.name')
|
||||
->get(
|
||||
[
|
||||
'categories.id',
|
||||
'categories.name as name',
|
||||
\DB::Raw('SUM(`transactions`.`amount`) * -1 AS `amount`')
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
89
app/lib/FireflyIII/Report/ReportQueryInterface.php
Normal file
89
app/lib/FireflyIII/Report/ReportQueryInterface.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Report;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
|
||||
/**
|
||||
* Interface ReportQueryInterface
|
||||
*
|
||||
* @package FireflyIII\Report
|
||||
*/
|
||||
interface ReportQueryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* This query retrieves a list of accounts that are active and not shared.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function accountList();
|
||||
|
||||
/**
|
||||
* Gets a list of expenses grouped by the budget they were filed under.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByBudget(Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* Gets a list of all budgets and if present, the amount of the current BudgetLimit
|
||||
* as well
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAllBudgets(Carbon $date);
|
||||
|
||||
/**
|
||||
* Gets a list of categories and the expenses therein, grouped by the relevant category.
|
||||
* This result excludes transfers to shared accounts which are expenses, technically.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByCategory(Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* Gets a list of expense accounts and the expenses therein, grouped by that expense account.
|
||||
* This result excludes transfers to shared accounts which are expenses, technically.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByExpenseAccount(Carbon $start, Carbon $end);
|
||||
|
||||
|
||||
/**
|
||||
* With a slightly misleading name, this query returns all transfers to shared accounts
|
||||
* grouped by category (which are technically expenses, since it won't be just your money that gets spend).
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function sharedExpensesByCategory(Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* With an equally misleading name, this query returns are transfers to shared accounts. These are considered
|
||||
* expenses.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function sharedExpenses(Carbon $start, Carbon $end);
|
||||
|
||||
}
|
@ -2,13 +2,13 @@
|
||||
@section('content')
|
||||
{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName()) }}
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||
<div class="col-lg-5 col-md-5 col-sm-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Income</div>
|
||||
@include('list.journals-small',['journals' => $income])
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||
<div class="col-lg-4 col-md-4 col-sm-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Expenses (top 10)</div>
|
||||
<table class="table table-bordered">
|
||||
@ -31,6 +31,31 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-4 col-sm-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Sums</div>
|
||||
<?php
|
||||
$in = 0;
|
||||
foreach($income as $entry) {
|
||||
$in += floatval($entry->transactions[1]->amount);
|
||||
}
|
||||
?>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<td>In</td>
|
||||
<td>{{mf($in)}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Out</td>
|
||||
<td>{{mf($sum)}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Difference</td>
|
||||
<td>{{mf($sum + $in)}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||
@ -48,23 +73,23 @@
|
||||
$sumEnvelope = 0;
|
||||
$sumLeft = 0;
|
||||
?>
|
||||
@foreach($budgets as $budget)
|
||||
@foreach($budgets as $id => $budget)
|
||||
<?php
|
||||
$sumSpent += floatval($budget->spent);
|
||||
$sumEnvelope += floatval($budget->budget_amount);
|
||||
$sumLeft += floatval($budget->budget_amount) - floatval($budget->spent);
|
||||
$sumSpent += $budget['spent'];
|
||||
$sumEnvelope += $budget['amount'];
|
||||
$sumLeft += $budget['amount'] + $budget['spent'];
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
@if($budget->id > 0)
|
||||
<a href="{{route('budgets.show',$budget->id)}}">{{{$budget->name}}}</a>
|
||||
@if($id > 0)
|
||||
<a href="{{route('budgets.show',$id)}}">{{{$budget['name']}}}</a>
|
||||
@else
|
||||
<em>{{{$budget->name}}}</em>
|
||||
<em>{{{$budget['name']}}}</em>
|
||||
@endif
|
||||
</td>
|
||||
<td>{{mf($budget->budget_amount)}}</td>
|
||||
<td>{{mf($budget->spent,false)}}</td>
|
||||
<td>{{mf(floatval($budget->budget_amount) - floatval($budget->spent))}}</td>
|
||||
<td>{{mf($budget['amount'])}}</td>
|
||||
<td>{{mf($budget['spent'],false)}}</td>
|
||||
<td>{{mf($budget['amount'] + $budget['spent'])}}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
<tr>
|
||||
@ -74,9 +99,6 @@
|
||||
<td>{{mf($sumLeft)}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="panel-body">
|
||||
<em>This list does not take in account outgoing transfers to shared accounts.</em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||
@ -88,17 +110,17 @@
|
||||
<th>Spent</th>
|
||||
</tr>
|
||||
<?php $sum = 0;?>
|
||||
@foreach($categories as $category)
|
||||
<?php $sum += floatval($category->sum);?>
|
||||
@foreach($categories as $id => $category)
|
||||
<?php $sum += floatval($category['amount']);?>
|
||||
<tr>
|
||||
<td>
|
||||
@if($category->id > 0)
|
||||
<a href="{{route('categories.show',$category->id)}}">{{{$category->name}}}</a>
|
||||
@if($id > 0)
|
||||
<a href="{{route('categories.show',$id)}}">{{{$category['name']}}}</a>
|
||||
@else
|
||||
<em>{{{$category->name}}}</em>
|
||||
<em>{{{$category['name']}}}</em>
|
||||
@endif
|
||||
</td>
|
||||
<td>{{mf($category->sum,false)}}</td>
|
||||
<td>{{mf($category['amount'],false)}}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
<tr>
|
||||
@ -106,9 +128,6 @@
|
||||
<td>{{mf($sum)}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="panel-body">
|
||||
<em>This list does not take in account outgoing transfers to shared accounts.</em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -122,17 +141,17 @@
|
||||
$sumEnd = 0;
|
||||
$sumDiff = 0;
|
||||
?>
|
||||
@foreach($accounts as $account)
|
||||
@foreach($accounts as $id => $account)
|
||||
<?php
|
||||
$sumStart += $account->startBalance;
|
||||
$sumEnd += $account->endBalance;
|
||||
$sumDiff += $account->difference;
|
||||
$sumStart += $account['startBalance'];
|
||||
$sumEnd += $account['endBalance'];
|
||||
$sumDiff += $account['difference'];
|
||||
?>
|
||||
<tr>
|
||||
<td><a href="#">{{{$account->name}}}</a></td>
|
||||
<td>{{mf($account->startBalance)}}</td>
|
||||
<td>{{mf($account->endBalance)}}</td>
|
||||
<td>{{mf($account->difference)}}</td>
|
||||
<td><a href="{{route('accounts.show',$id)}}">{{{$account['name']}}}</a></td>
|
||||
<td>{{mf($account['startBalance'])}}</td>
|
||||
<td>{{mf($account['endBalance'])}}</td>
|
||||
<td>{{mf($account['difference'])}}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
<tr>
|
||||
|
Loading…
Reference in New Issue
Block a user