diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php index b4fe3cd03d..a3a3d84697 100644 --- a/app/controllers/AccountController.php +++ b/app/controllers/AccountController.php @@ -236,7 +236,7 @@ class AccountController extends BaseController } // go back to update screen. if ($data['post_submit_action'] == 'return_to_edit') { - return Redirect::route('accounts.edit', $account->id); + return Redirect::route('accounts.edit', $account->id)->withInput(['post_submit_action' => 'return_to_edit']); } return Redirect::route('accounts.index', $data['what']); diff --git a/app/controllers/BudgetController.php b/app/controllers/BudgetController.php index 3d2f95d75a..467d0318c1 100644 --- a/app/controllers/BudgetController.php +++ b/app/controllers/BudgetController.php @@ -1,24 +1,31 @@ _repository = $repository; + $this->_repository = $repository; + $this->_preferences = $preferences; View::share('title', 'Budgets'); View::share('mainTitleIcon', 'fa-tasks'); } @@ -31,17 +38,11 @@ class BudgetController extends BaseController */ public function amount(Budget $budget) { - $amount = intval(Input::get('amount')); - $date = Session::get('start'); - $limit = $this->_repository->updateLimitAmount($budget, $date, $amount); + $amount = intval(Input::get('amount')); + $date = Session::get('start'); + $limitRepetition = $this->_repository->updateLimitAmount($budget, $date, $amount); - // try to find the limit repetition for this limit: - $repetition = $limit->limitrepetitions()->first(); - if ($repetition) { - return Response::json(['name' => $budget->name, 'repetition' => $repetition->id]); - } else { - return Response::json(['name' => $budget->name, 'repetition' => null]); - } + return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition->id]); } @@ -72,8 +73,9 @@ class BudgetController extends BaseController */ public function destroy(Budget $budget) { + Session::flash('success', 'Budget "' . e($budget->name) . '" was deleted.'); $this->_repository->destroy($budget); - Session::flash('success', 'The budget was deleted.'); + return Redirect::route('budgets.index'); @@ -86,67 +88,39 @@ class BudgetController extends BaseController */ public function edit(Budget $budget) { - $subTitle = 'Edit budget "' . $budget->name . '"'; + $subTitle = 'Edit budget "' . e($budget->name) . '"'; return View::make('budgets.edit', compact('budget', 'subTitle')); } /** + * The index of the budget controller contains all budgets and the current relevant limit repetition. + * * @return $this */ public function index() { + $budgets = $this->_repository->get(); - /** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */ - $preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface'); - - /** @var \FireflyIII\Database\Budget $repos */ - $repos = App::make('FireflyIII\Database\Budget'); - $budgets = $repos->get(); - - // get the limits for the current month. - $date = \Session::get('start'); - $spent = 0; - /** @var \Budget $budget */ - foreach ($budgets as $budget) { - - $budget->spent = $repos->spentInMonth($budget, $date); - $spent += $budget->spent; - $budget->pct = 0; - $budget->limit = 0; - - /** @var \Limit $limit */ - foreach ($budget->limits as $limit) { - /** @var \LimitRepetition $repetition */ - foreach ($limit->limitrepetitions as $repetition) { - if ($repetition->startdate == $date) { - $budget->currentRep = $repetition; - $budget->limit = floatval($repetition->amount); - if ($budget->limit > $budget->spent) { - // not overspent: - $budget->pct = 30; - } else { - $budget->pct = 50; - } - - } - } + // loop the budgets: + $budgets->each( + function (Budget $budget) { + /** @noinspection PhpUndefinedFieldInspection */ + $budget->spent = $this->_repository->spentInMonth($budget, \Session::get('start')); + /** @noinspection PhpUndefinedFieldInspection */ + $budget->currentRep = $budget->limitrepetitions()->where('limit_repetitions.startdate', \Session::get('start')->format('Y-m-d'))->first( + ['limit_repetitions.*'] + ); } - } + ); - $budgetAmount = $preferences->get('budgetIncomeTotal' . $date->format('FY'), 1000); - $amount = floatval($budgetAmount->data); - $overspent = $spent > $amount; - if ($overspent) { - // overspent on total amount - $spentPCT = ceil($amount / $spent * 100); - } else { - // not overspent on total amount. - $spentPCT = ceil($spent / $amount * 100); - } + $spent = $budgets->sum('spent'); + $amount = $this->_preferences->get('budgetIncomeTotal' . \Session::get('start')->format('FY'), 1000)->data; + $overspent = $spent > $amount; + $spentPCT = $overspent ? ceil($amount / $spent * 100) : ceil($spent / $amount * 100); - return View::make('budgets.index', compact('budgets', 'spent', 'spentPCT', 'overspent'))->with('budgetAmount', $budgetAmount); + return View::make('budgets.index', compact('budgets', 'spent', 'spentPCT', 'overspent', 'amount')); } /** @@ -154,12 +128,7 @@ class BudgetController extends BaseController */ public function postUpdateIncome() { - /** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */ - $preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface'); - $date = Session::get('start'); - - $value = intval(Input::get('amount')); - $preferences->set('budgetIncomeTotal' . $date->format('FY'), $value); + $this->_preferences->set('budgetIncomeTotal' . Session::get('start')->format('FY'), intval(Input::get('amount'))); return Redirect::route('budgets.index'); } @@ -175,121 +144,93 @@ class BudgetController extends BaseController if (!is_null($repetition) && $repetition->limit->budget->id != $budget->id) { App::abort(500); } - /** @var \FireflyIII\Database\Budget $repos */ - $repos = App::make('FireflyIII\Database\Budget'); - if (is_null($repetition)) { - // get all other repetitions: - $limits = $budget->limits()->orderBy('startdate', 'DESC')->get(); - // get all transaction journals for this budget. - $journals = $repos->getTransactionJournals($budget, 50); + $journals = $this->_repository->getJournals($budget, $repetition); + $limits = $repetition ? $budget->limits()->orderBy('startdate', 'DESC')->get() : [$repetition->limit]; + $subTitle = $repetition ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name); - $subTitle = $budget->name; - } else { - // get nothing? i dunno - $limits = [$repetition->limit]; - // get all transaction journals for this budget and limit repetition. - $subTitle = $budget->name . ' in ' . $repetition->startdate->format('F Y'); - $journals = $repos->getTransactionJournalsInRepetition($budget, $repetition, 50); - } - $hideBudget = true; - - - return View::make('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget')); + return View::make('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle')); } /** - * @return $this - * @throws FireflyException + * @return $this|\Illuminate\Http\RedirectResponse */ public function store() { - /** @var \FireflyIII\Database\Budget $repos */ - $repos = App::make('FireflyIII\Database\Budget'); - $data = Input::except('_token'); + $data = Input::except('_token'); - switch ($data['post_submit_action']) { - default: - throw new FireflyException('Cannot handle post_submit_action "' . e($data['post_submit_action']) . '"'); - break; - case 'create_another': - case 'store': - $messages = $repos->validate($data); - /** @var MessageBag $messages ['errors'] */ - if ($messages['errors']->count() > 0) { - Session::flash('warnings', $messages['warnings']); - Session::flash('successes', $messages['successes']); - Session::flash('error', 'Could not save budget: ' . $messages['errors']->first()); + // always validate: + $messages = $this->_repository->validate($data); - return Redirect::route('budgets.create')->withInput()->withErrors($messages['errors']); - } - // store! - $repos->store($data); - Session::flash('success', 'New budget stored!'); - - if ($data['post_submit_action'] == 'create_another') { - return Redirect::route('budgets.create'); - } else { - return Redirect::route('budgets.index'); - } - break; - case 'validate_only': - $messageBags = $repos->validate($data); - Session::flash('warnings', $messageBags['warnings']); - Session::flash('successes', $messageBags['successes']); - Session::flash('errors', $messageBags['errors']); - - return Redirect::route('budgets.create')->withInput(); - break; + // flash messages: + Session::flash('warnings', $messages['warnings']); + Session::flash('successes', $messages['successes']); + Session::flash('errors', $messages['errors']); + if ($messages['errors']->count() > 0) { + Session::flash('error', 'Could not store budget: ' . $messages['errors']->first()); } + + // return to create screen: + if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { + return Redirect::route('budgets.create')->withInput(); + } + + // store: + $this->_repository->store($data); + Session::flash('success', 'Budget "' . e($data['name']) . '" stored.'); + if ($data['post_submit_action'] == 'store') { + return Redirect::route('budgets.index'); + } + + // create another. + if ($data['post_submit_action'] == 'create_another') { + return Redirect::route('budgets.create')->withInput(); + } + + return Redirect::route('budgets.index'); } + /** * @param Budget $budget * - * @return $this - * @throws FireflyException + * @return $this|\Illuminate\Http\RedirectResponse */ public function update(Budget $budget) { - /** @var \FireflyIII\Database\Budget $repos */ - $repos = App::make('FireflyIII\Database\Budget'); - $data = Input::except('_token'); + $data = Input::except('_token'); - switch (Input::get('post_submit_action')) { - default: - throw new FireflyException('Cannot handle post_submit_action "' . e(Input::get('post_submit_action')) . '"'); - break; - case 'return_to_edit': - case 'update': - $messages = $repos->validate($data); - /** @var MessageBag $messages ['errors'] */ - if ($messages['errors']->count() > 0) { - Session::flash('warnings', $messages['warnings']); - Session::flash('successes', $messages['successes']); - Session::flash('error', 'Could not save budget: ' . $messages['errors']->first()); + // always validate: + $messages = $this->_repository->validate($data); - return Redirect::route('budgets.edit', $budget->id)->withInput()->withErrors($messages['errors']); - } - // store! - $repos->update($budget, $data); - Session::flash('success', 'Budget updated!'); - - if ($data['post_submit_action'] == 'return_to_edit') { - return Redirect::route('budgets.edit', $budget->id); - } else { - return Redirect::route('budgets.index'); - } - case 'validate_only': - $messageBags = $repos->validate($data); - Session::flash('warnings', $messageBags['warnings']); - Session::flash('successes', $messageBags['successes']); - Session::flash('errors', $messageBags['errors']); - - return Redirect::route('budgets.edit', $budget->id)->withInput(); - break; + // flash messages: + Session::flash('warnings', $messages['warnings']); + Session::flash('successes', $messages['successes']); + Session::flash('errors', $messages['errors']); + if ($messages['errors']->count() > 0) { + Session::flash('error', 'Could not update budget: ' . $messages['errors']->first()); } + + // return to update screen: + if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { + return Redirect::route('budgets.edit', $budget->id)->withInput(); + } + + // update + $this->_repository->update($budget, $data); + Session::flash('success', 'Budget "' . e($data['name']) . '" updated.'); + + // go back to list + if ($data['post_submit_action'] == 'update') { + return Redirect::route('budgets.index'); + } + // go back to update screen. + if ($data['post_submit_action'] == 'return_to_edit') { + return Redirect::route('budgets.edit', $budget->id)->withInput(['post_submit_action' => 'return_to_edit']); + } + + return Redirect::route('budgets.index'); } /** @@ -297,11 +238,7 @@ class BudgetController extends BaseController */ public function updateIncome() { - $date = Session::get('start'); - /** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */ - $preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface'); - $budgetAmount = $preferences->get('budgetIncomeTotal' . $date->format('FY'), 1000); - - return View::make('budgets.income')->with('amount', $budgetAmount)->with('date', $date); + $budgetAmount = $this->_preferences->get('budgetIncomeTotal' . Session::get('start')->format('FY'), 1000); + return View::make('budgets.income')->with('amount', $budgetAmount); } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/Budget.php b/app/lib/FireflyIII/Database/Budget.php index 369dd15512..9f14598cbf 100644 --- a/app/lib/FireflyIII/Database/Budget.php +++ b/app/lib/FireflyIII/Database/Budget.php @@ -166,6 +166,40 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface throw new NotImplementedException; } + /** + * Returns all the transaction journals for a limit, possibly limited by a limit repetition. + * + * @param \Budget $budget + * @param \LimitRepetition $repetition + * @param int $take + * + * @return \Illuminate\Pagination\Paginator + */ + public function getJournals(\Budget $budget, \LimitRepetition $repetition = null, $take = 50) + { + $offset = intval(\Input::get('page')) > 0 ? intval(\Input::get('page')) * $take : 0; + + + $setQuery = $budget->transactionJournals()->withRelevantData()->take($take)->offset($offset)->orderBy('date', 'DESC'); + $countQuery = $budget->transactionJournals(); + + + if (!is_null($repetition)) { + $setQuery->before($repetition->startdate)->after($repetition->enddate); + $countQuery->before($repetition->startdate)->after($repetition->enddate); + } + + + $set = $setQuery->get(['transaction_journals.*']); + $count = $countQuery->count(); + $items = []; + foreach ($set as $entry) { + $items[] = $entry; + } + + return \Paginator::make($items, $count, $take); + } + public function getTransactionJournals(\Budget $budget, $limit = 50) { $offset = intval(\Input::get('page')) > 0 ? intval(\Input::get('page')) * $limit : 0; @@ -265,11 +299,14 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface } /** + * This method updates the amount (envelope) for the given date and budget. This results in a (new) limit (aka an envelope) + * for that budget. Returned to the user is the new limit repetition. + * * @param \Budget $budget * @param Carbon $date * @param $amount * - * @return \Limit + * @return \LimitRepetition * @throws \Exception */ public function updateLimitAmount(\Budget $budget, Carbon $date, $amount) @@ -280,10 +317,10 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface // create one! $limit = new \Limit; $limit->budget()->associate($budget); - $limit->startdate = $date; - $limit->amount = $amount; + $limit->startdate = $date; + $limit->amount = $amount; $limit->repeat_freq = 'monthly'; - $limit->repeats = 0; + $limit->repeats = 0; $limit->save(); /* * A newly stored limit also created a limit repetition. @@ -302,7 +339,7 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface } } - return $limit; + return $limit->limitrepetitions()->first(); } diff --git a/app/views/budgets/income.blade.php b/app/views/budgets/income.blade.php index 4c6e3761df..d5b70c4f93 100644 --- a/app/views/budgets/income.blade.php +++ b/app/views/budgets/income.blade.php @@ -4,7 +4,7 @@