From 658265c93845e786a0329a2d9bc8d70a82f543b4 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 29 Dec 2015 08:45:43 +0100 Subject: [PATCH] Optimised whole budget chart to use less queries. --- .../Controllers/Chart/BudgetController.php | 28 ++++++----- app/Repositories/Budget/BudgetRepository.php | 48 +++++++++++++------ .../Budget/BudgetRepositoryInterface.php | 12 +++++ 3 files changed, 62 insertions(+), 26 deletions(-) diff --git a/app/Http/Controllers/Chart/BudgetController.php b/app/Http/Controllers/Chart/BudgetController.php index 1f3d2f5723..8f197a6a88 100644 --- a/app/Http/Controllers/Chart/BudgetController.php +++ b/app/Http/Controllers/Chart/BudgetController.php @@ -130,11 +130,6 @@ class BudgetController extends Controller $first = $repository->getFirstBudgetLimitDate($budget); $range = Preferences::get('viewRange', '1M')->data; $last = Session::get('end', new Carbon); - $final = clone $last; - $final->addYears(2); - $last = Navigation::endOfX($last, $range, $final); - $accounts = $accountRepository->getAccounts(['Default account', 'Asset account', 'Cash account']); - // chart properties for cache: $cache = new CacheProperties(); @@ -142,18 +137,29 @@ class BudgetController extends Controller $cache->addProperty($last); $cache->addProperty('budget'); if ($cache->has()) { + return Response::json($cache->get()); // @codeCoverageIgnore } + $final = clone $last; + $final->addYears(2); + $last = Navigation::endOfX($last, $range, $final); $entries = new Collection; + // get all expenses: + $set = $repository->getExpensesPerMonth($budget, $first, $last); while ($first < $last) { - $end = Navigation::addPeriod($first, $range, 0); - $end->subDay(); - $chartDate = clone $end; - $chartDate->startOfMonth(); - $spent = $repository->balanceInPeriod($budget, $first, $end, $accounts) * -1; - $entries->push([$chartDate, $spent]); + $monthFormatted = $first->format('Y-m'); + + $filtered = $set->filter( + function (Budget $obj) use ($monthFormatted) { + return $obj->dateFormatted == $monthFormatted; + } + ); + $spent = is_null($filtered->first()) ? '0' : $filtered->first()->monthlyAmount; + + $entries->push([$first, round(($spent * -1), 2)]); + $first = Navigation::addPeriod($first, $range, 0); } diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index 6a06fd533b..a828ede212 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -49,26 +49,12 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn */ public function getExpensesPerDay(Budget $budget, Carbon $start, Carbon $end) { - /* - * select transaction_journals.date, SUM(transactions.amount) as dailyAmount from budgets -left join budget_transaction_journal ON budget_transaction_journal.budget_id = budgets.id -left join transaction_journals ON budget_transaction_journal.transaction_journal_id = transaction_journals.id -left join transactions ON transaction_journals.id = transactions.transaction_journal_id -where - -transaction_journals.date >= "2015-12-01" -and transaction_journals.date <= "2015-12-31" -and budgets.id = 1 -and transactions.amount < 0 -group by transaction_journals.date -order by transaction_journals.date - */ - $set = Auth::user()->budgets() ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.budget_id', '=', 'budgets.id') ->leftJoin('transaction_journals', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') ->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) + ->whereNull('transaction_journals.deleted_at') ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) ->where('budgets.id', $budget->id) ->where('transactions.amount', '<', 0) @@ -77,7 +63,39 @@ order by transaction_journals.date ->get(['transaction_journals.date', DB::Raw('SUM(`transactions`.`amount`) as `dailyAmount`')]); return $set; + } + /** + * Returns the expenses for this budget grouped per month, with the date + * in "dateFormatted" (a string, not a Carbon) and the amount in "dailyAmount". + * + * @param Budget $budget + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getExpensesPerMonth(Budget $budget, Carbon $start, Carbon $end) + { + $set = Auth::user()->budgets() + ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.budget_id', '=', 'budgets.id') + ->leftJoin('transaction_journals', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) + ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) + ->whereNull('transaction_journals.deleted_at') + ->where('budgets.id', $budget->id) + ->where('transactions.amount', '<', 0) + ->groupBy('dateFormatted') + ->orderBy('transaction_journals.date') + ->get( + [ + DB::Raw('DATE_FORMAT(`transaction_journals`.`date`, "%Y-%m") AS `dateFormatted`'), + DB::Raw('SUM(`transactions`.`amount`) as `monthlyAmount`') + ] + ); + + return $set; } /** diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php index 11dbcae4c1..c1109188f7 100644 --- a/app/Repositories/Budget/BudgetRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -32,6 +32,18 @@ interface BudgetRepositoryInterface */ public function getExpensesPerDay(Budget $budget, Carbon $start, Carbon $end); + /** + * Returns the expenses for this budget grouped per month, with the date + * in "date" (a string, not a Carbon) and the amount in "dailyAmount". + * + * @param Budget $budget + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getExpensesPerMonth(Budget $budget, Carbon $start, Carbon $end); + /** * @param Budget $budget *