mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-10 23:45:48 -06:00
First attempt at optimised query for multi-year budget chart.
This commit is contained in:
parent
83de3482ce
commit
6ab6dd6ac3
@ -37,6 +37,8 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* TODO expand with no budget chart.
|
||||||
|
*
|
||||||
* @param BudgetRepositoryInterface $repository
|
* @param BudgetRepositoryInterface $repository
|
||||||
* @param $report_type
|
* @param $report_type
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
@ -61,41 +63,43 @@ class BudgetController extends Controller
|
|||||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* budget
|
* Get the budgeted amounts for each budgets in each year.
|
||||||
* year:
|
|
||||||
* spent: x
|
|
||||||
* budgeted: x
|
|
||||||
* year
|
|
||||||
* spent: x
|
|
||||||
* budgeted: x
|
|
||||||
*/
|
*/
|
||||||
|
$budgetedSet = $repository->getBudgetedPerYear($budgets, $start, $end);
|
||||||
|
$budgetedArray = [];
|
||||||
|
/** @var Budget $entry */
|
||||||
|
foreach ($budgetedSet as $entry) {
|
||||||
|
$budgetedArray[$entry->id][$entry->dateFormatted] = $entry->budgeted;
|
||||||
|
}
|
||||||
|
|
||||||
|
$set = $repository->getBudgetsAndExpensesPerYear($budgets, $accounts, $start, $end);
|
||||||
$entries = new Collection;
|
$entries = new Collection;
|
||||||
// go by budget, not by year.
|
// go by budget, not by year.
|
||||||
|
/** @var Budget $budget */
|
||||||
foreach ($budgets as $budget) {
|
foreach ($budgets as $budget) {
|
||||||
$entry = ['name' => '', 'spent' => [], 'budgeted' => []];
|
$entry = ['name' => '', 'spent' => [], 'budgeted' => []];
|
||||||
|
$id = $budget->id;
|
||||||
$currentStart = clone $start;
|
$currentStart = clone $start;
|
||||||
while ($currentStart < $end) {
|
while ($currentStart < $end) {
|
||||||
// fix the date:
|
// fix the date:
|
||||||
$currentEnd = clone $currentStart;
|
$currentEnd = clone $currentStart;
|
||||||
$currentEnd->endOfYear();
|
$currentEnd->endOfYear();
|
||||||
|
|
||||||
// get data:
|
// save to array:
|
||||||
if (is_null($budget->id)) {
|
$year = $currentStart->year;
|
||||||
$name = trans('firefly.noBudget');
|
$entry['name'] = $budget->name;
|
||||||
$sum = $repository->getWithoutBudgetSum($currentStart, $currentEnd);
|
$spent = 0;
|
||||||
$budgeted = 0;
|
$budgeted = 0;
|
||||||
} else {
|
if (isset($set[$id]['entries'][$year])) {
|
||||||
$name = $budget->name;
|
$spent = $set[$id]['entries'][$year] * -1;
|
||||||
$sum = $repository->balanceInPeriod($budget, $currentStart, $currentEnd, $accounts);
|
|
||||||
$budgeted = $repository->getBudgetLimitRepetitions($budget, $currentStart, $currentEnd)->sum('amount');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// save to array:
|
if (isset($budgetedArray[$id][$year])) {
|
||||||
$year = $currentStart->year;
|
$budgeted = round($budgetedArray[$id][$year], 2);
|
||||||
$entry['name'] = $name;
|
}
|
||||||
$entry['spent'][$year] = ($sum * -1);
|
|
||||||
|
$entry['spent'][$year] = $spent;
|
||||||
$entry['budgeted'][$year] = $budgeted;
|
$entry['budgeted'][$year] = $budgeted;
|
||||||
|
|
||||||
// jump to next year.
|
// jump to next year.
|
||||||
@ -106,6 +110,7 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
// generate chart with data:
|
// generate chart with data:
|
||||||
$data = $this->generator->multiYear($entries);
|
$data = $this->generator->multiYear($entries);
|
||||||
|
$cache->store($data);
|
||||||
|
|
||||||
return Response::json($data);
|
return Response::json($data);
|
||||||
|
|
||||||
@ -273,6 +278,8 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* TODO expand with no budget chart.
|
||||||
|
*
|
||||||
* @param BudgetRepositoryInterface $repository
|
* @param BudgetRepositoryInterface $repository
|
||||||
* @param $report_type
|
* @param $report_type
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
@ -295,7 +302,7 @@ class BudgetController extends Controller
|
|||||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
|
|
||||||
$budgetInformation = $repository->getBudgetsAndExpenses($start, $end);
|
$budgetInformation = $repository->getBudgetsAndExpensesPerMonth($accounts, $start, $end);
|
||||||
$budgets = new Collection;
|
$budgets = new Collection;
|
||||||
$entries = new Collection;
|
$entries = new Collection;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ namespace FireflyIII\Repositories\Budget;
|
|||||||
use Auth;
|
use Auth;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use DB;
|
use DB;
|
||||||
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Models\BudgetLimit;
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Models\LimitRepetition;
|
use FireflyIII\Models\LimitRepetition;
|
||||||
@ -214,33 +215,41 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
|||||||
* Returns an array with every budget in it and the expenses for each budget
|
* Returns an array with every budget in it and the expenses for each budget
|
||||||
* per month.
|
* per month.
|
||||||
*
|
*
|
||||||
* @param Carbon $start
|
* @param Collection $accounts
|
||||||
* @param Carbon $end
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getBudgetsAndExpenses(Carbon $start, Carbon $end)
|
public function getBudgetsAndExpensesPerMonth(Collection $accounts, Carbon $start, Carbon $end)
|
||||||
{
|
{
|
||||||
|
$ids = [];
|
||||||
|
/** @var Account $account */
|
||||||
|
foreach ($accounts as $account) {
|
||||||
|
$ids[] = $account->id;
|
||||||
|
}
|
||||||
|
|
||||||
/** @var Collection $set */
|
/** @var Collection $set */
|
||||||
$set = Auth::user()->budgets()
|
$set = Auth::user()->budgets()
|
||||||
->leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
|
->leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
|
||||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
|
||||||
->leftJoin(
|
->leftJoin(
|
||||||
'transactions', function (JoinClause $join) {
|
'transactions', function (JoinClause $join) {
|
||||||
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0);
|
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
->groupBy('budgets.id')
|
->groupBy('budgets.id')
|
||||||
->groupBy('dateFormatted')
|
->groupBy('dateFormatted')
|
||||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
->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'))
|
||||||
->get(
|
->whereIn('transactions.account_id', $ids)
|
||||||
[
|
->get(
|
||||||
'budgets.*',
|
[
|
||||||
DB::Raw('DATE_FORMAT(`transaction_journals`.`date`, "%Y-%m") AS `dateFormatted`'),
|
'budgets.*',
|
||||||
DB::Raw('SUM(`transactions`.`amount`) AS `sumAmount`')
|
DB::Raw('DATE_FORMAT(`transaction_journals`.`date`, "%Y-%m") AS `dateFormatted`'),
|
||||||
]
|
DB::Raw('SUM(`transactions`.`amount`) AS `sumAmount`')
|
||||||
);
|
]
|
||||||
|
);
|
||||||
|
|
||||||
$set = $set->sortBy(
|
$set = $set->sortBy(
|
||||||
function (Budget $budget) {
|
function (Budget $budget) {
|
||||||
@ -260,6 +269,7 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
|||||||
// store each entry:
|
// store each entry:
|
||||||
$return[$id]['entries'][$budget->dateFormatted] = $budget->sumAmount;
|
$return[$id]['entries'][$budget->dateFormatted] = $budget->sumAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,7 +513,110 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
return $limit;
|
return $limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the budgeted amounts for each budgets in each year.
|
||||||
|
*
|
||||||
|
* @param Collection $budgets
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getBudgetedPerYear(Collection $budgets, Carbon $start, Carbon $end)
|
||||||
|
{
|
||||||
|
$budgetIds = [];
|
||||||
|
|
||||||
|
/** @var Budget $budget */
|
||||||
|
foreach ($budgets as $budget) {
|
||||||
|
$budgetIds[] = $budget->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$set = Auth::user()->budgets()
|
||||||
|
->leftJoin('budget_limits', 'budgets.id', '=', 'budget_limits.budget_id')
|
||||||
|
->leftJoin('limit_repetitions', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
|
||||||
|
->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d'))
|
||||||
|
->where('limit_repetitions.enddate', '<=', $end->format('Y-m-d'))
|
||||||
|
->groupBy('budgets.id')
|
||||||
|
->groupBy('dateFormatted')
|
||||||
|
->whereIn('budgets.id', $budgetIds)
|
||||||
|
->get(
|
||||||
|
[
|
||||||
|
'budgets.*',
|
||||||
|
DB::Raw('DATE_FORMAT(`limit_repetitions`.`startdate`,"%Y") as `dateFormatted`'),
|
||||||
|
DB::Raw('SUM(`limit_repetitions`.`amount`) as `budgeted`')
|
||||||
|
]
|
||||||
|
);
|
||||||
|
return $set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array with every budget in it and the expenses for each budget
|
||||||
|
* per year for.
|
||||||
|
*
|
||||||
|
* @param Collection $budgets
|
||||||
|
* @param Collection $accounts
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getBudgetsAndExpensesPerYear(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end)
|
||||||
|
{
|
||||||
|
$ids = [];
|
||||||
|
/** @var Account $account */
|
||||||
|
foreach ($accounts as $account) {
|
||||||
|
$ids[] = $account->id;
|
||||||
|
}
|
||||||
|
$budgetIds = [];
|
||||||
|
/** @var Budget $budget */
|
||||||
|
foreach ($budgets as $budget) {
|
||||||
|
$budgetIds[] = $budget->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Collection $set */
|
||||||
|
$set = Auth::user()->budgets()
|
||||||
|
->leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
|
||||||
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
|
||||||
|
->leftJoin(
|
||||||
|
'transactions', function (JoinClause $join) {
|
||||||
|
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
->groupBy('budgets.id')
|
||||||
|
->groupBy('dateFormatted')
|
||||||
|
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||||
|
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||||
|
->whereIn('transactions.account_id', $ids)
|
||||||
|
->whereIn('budgets.id', $budgetIds)
|
||||||
|
->get(
|
||||||
|
[
|
||||||
|
'budgets.*',
|
||||||
|
DB::Raw('DATE_FORMAT(`transaction_journals`.`date`, "%Y") AS `dateFormatted`'),
|
||||||
|
DB::Raw('SUM(`transactions`.`amount`) AS `sumAmount`')
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$set = $set->sortBy(
|
||||||
|
function (Budget $budget) {
|
||||||
|
return strtolower($budget->name);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$return = [];
|
||||||
|
foreach ($set as $budget) {
|
||||||
|
$id = $budget->id;
|
||||||
|
if (!isset($return[$id])) {
|
||||||
|
$return[$id] = [
|
||||||
|
'budget' => $budget,
|
||||||
|
'entries' => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
// store each entry:
|
||||||
|
$return[$id]['entries'][$budget->dateFormatted] = $budget->sumAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,26 @@ interface BudgetRepositoryInterface
|
|||||||
* Returns an array with every budget in it and the expenses for each budget
|
* Returns an array with every budget in it and the expenses for each budget
|
||||||
* per month.
|
* per month.
|
||||||
*
|
*
|
||||||
* @param Carbon $start
|
* @param Collection $accounts
|
||||||
* @param Carbon $end
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getBudgetsAndExpenses(Carbon $start, Carbon $end);
|
public function getBudgetsAndExpensesPerMonth(Collection $accounts, Carbon $start, Carbon $end);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array with every budget in it and the expenses for each budget
|
||||||
|
* per year for.
|
||||||
|
*
|
||||||
|
* @param Collection $budgets
|
||||||
|
* @param Collection $accounts
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getBudgetsAndExpensesPerYear(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes tags into account.
|
* Takes tags into account.
|
||||||
@ -53,6 +67,17 @@ interface BudgetRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function getActiveBudgets();
|
public function getActiveBudgets();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the budgeted amounts for each budgets in each year.
|
||||||
|
*
|
||||||
|
* @param Collection $budgets
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getBudgetedPerYear(Collection $budgets, Carbon $start, Carbon $end);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
|
Loading…
Reference in New Issue
Block a user