firefly-iii/app/Http/Controllers/BudgetController.php

433 lines
16 KiB
PHP
Raw Normal View History

2016-05-20 01:57:45 -05:00
<?php
/**
* BudgetController.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
2016-05-20 01:57:45 -05:00
declare(strict_types = 1);
namespace FireflyIII\Http\Controllers;
2015-02-22 02:46:21 -06:00
2015-05-24 15:54:59 -05:00
use Amount;
2015-02-22 02:46:21 -06:00
use Carbon\Carbon;
2016-02-05 22:01:34 -06:00
use FireflyIII\Exceptions\FireflyException;
2016-12-28 04:34:00 -06:00
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
2015-02-22 08:40:13 -06:00
use FireflyIII\Http\Requests\BudgetFormRequest;
2016-12-22 09:36:56 -06:00
use FireflyIII\Http\Requests\BudgetIncomeRequest;
2016-05-20 04:02:07 -05:00
use FireflyIII\Models\AccountType;
2015-02-22 02:46:21 -06:00
use FireflyIII\Models\Budget;
2016-12-29 13:48:33 -06:00
use FireflyIII\Models\BudgetLimit;
2016-10-10 00:49:39 -05:00
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
2015-02-22 02:46:21 -06:00
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
2016-12-28 06:02:56 -06:00
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
2015-02-22 02:46:21 -06:00
use Preferences;
2015-02-22 08:40:13 -06:00
use Response;
2015-02-22 02:46:21 -06:00
use Session;
2015-04-01 02:40:19 -05:00
use URL;
2015-04-05 03:36:28 -05:00
use View;
2015-02-22 02:46:21 -06:00
/**
* Class BudgetController
*
* @package FireflyIII\Http\Controllers
*/
class BudgetController extends Controller
{
2016-12-22 09:36:56 -06:00
/** @var BudgetRepositoryInterface */
private $repository;
2015-04-03 12:11:55 -05:00
/**
2016-02-04 00:27:03 -06:00
*
2015-04-03 12:11:55 -05:00
*/
2015-02-22 02:46:21 -06:00
public function __construct()
{
2015-04-28 08:26:30 -05:00
parent::__construct();
2016-10-29 00:44:46 -05:00
2015-04-28 08:26:30 -05:00
View::share('hideBudgets', true);
2016-10-29 00:44:46 -05:00
$this->middleware(
function ($request, $next) {
View::share('title', trans('firefly.budgets'));
View::share('mainTitleIcon', 'fa-tasks');
2016-12-22 09:36:56 -06:00
$this->repository = app(BudgetRepositoryInterface::class);
2016-10-29 00:44:46 -05:00
return $next($request);
}
);
2015-02-22 02:46:21 -06:00
}
/**
2016-12-28 06:02:56 -06:00
* @param Request $request
2015-05-03 05:54:39 -05:00
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
2015-02-22 02:46:21 -06:00
*
2016-12-28 06:02:56 -06:00
* @return \Illuminate\Http\JsonResponse
2015-02-22 02:46:21 -06:00
*/
2016-12-28 06:02:56 -06:00
public function amount(Request $request, BudgetRepositoryInterface $repository, Budget $budget)
2015-02-22 02:46:21 -06:00
{
2016-12-28 06:02:56 -06:00
$amount = intval($request->get('amount'));
2016-04-28 03:59:36 -05:00
/** @var Carbon $start */
$start = session('start', Carbon::now()->startOfMonth());
/** @var Carbon $end */
2016-12-30 00:39:42 -06:00
$end = session('end', Carbon::now()->endOfMonth());
2016-12-29 13:52:02 -06:00
$budgetLimit = $repository->updateLimitAmount($budget, $start, $end, $amount);
2015-05-24 15:54:59 -05:00
if ($amount == 0) {
2016-12-29 13:52:02 -06:00
$budgetLimit = null;
2015-05-24 15:54:59 -05:00
}
Preferences::mark();
2015-02-22 02:46:21 -06:00
2016-12-29 13:52:02 -06:00
return Response::json(['name' => $budget->name, 'limit' => $budgetLimit ? $budgetLimit->id : 0, 'amount' => $amount]);
2015-02-22 02:46:21 -06:00
}
2015-02-22 08:40:13 -06:00
/**
* @return View
2015-02-22 08:40:13 -06:00
*/
public function create()
{
2015-04-01 02:40:19 -05:00
// put previous url in session if not redirect from store (not "create another").
2016-02-04 00:27:03 -06:00
if (session('budgets.create.fromStore') !== true) {
2015-04-01 02:40:19 -05:00
Session::put('budgets.create.url', URL::previous());
}
Session::forget('budgets.create.fromStore');
2015-05-25 01:12:31 -05:00
Session::flash('gaEventCategory', 'budgets');
Session::flash('gaEventAction', 'create');
$subTitle = (string)trans('firefly.create_new_budget');
2015-04-01 02:40:19 -05:00
2015-05-05 03:23:01 -05:00
return view('budgets.create', compact('subTitle'));
2015-02-22 08:40:13 -06:00
}
/**
* @param Budget $budget
*
* @return View
2015-02-22 08:40:13 -06:00
*/
public function delete(Budget $budget)
{
2015-05-25 15:16:00 -05:00
$subTitle = trans('firefly.delete_budget', ['name' => $budget->name]);
2015-02-22 08:40:13 -06:00
2015-04-01 02:40:19 -05:00
// put previous url in session
Session::put('budgets.delete.url', URL::previous());
2015-05-25 01:12:31 -05:00
Session::flash('gaEventCategory', 'budgets');
Session::flash('gaEventAction', 'delete');
2015-04-01 02:40:19 -05:00
2015-02-22 09:19:32 -06:00
return view('budgets.delete', compact('budget', 'subTitle'));
2015-02-22 08:40:13 -06:00
}
/**
2015-05-03 05:54:39 -05:00
* @param Budget $budget
* @param BudgetRepositoryInterface $repository
2015-02-22 08:40:13 -06:00
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Budget $budget, BudgetRepositoryInterface $repository)
{
2016-12-19 14:07:22 -06:00
$name = $budget->name;
$budgetId = $budget->id;
2015-02-22 08:40:13 -06:00
$repository->destroy($budget);
2015-04-01 02:40:19 -05:00
2016-03-20 05:38:01 -05:00
Session::flash('success', strval(trans('firefly.deleted_budget', ['name' => e($name)])));
Preferences::mark();
2015-02-22 08:40:13 -06:00
2016-12-19 14:07:22 -06:00
$uri = session('budgets.delete.url');
if (!(strpos($uri, sprintf('budgets/show/%s', $budgetId)) === false)) {
// uri would point back to budget
$uri = route('budgets.index');
}
2015-05-25 01:12:31 -05:00
2016-12-19 14:07:22 -06:00
return redirect($uri);
2015-02-22 08:40:13 -06:00
}
/**
* @param Budget $budget
*
* @return View
2015-02-22 08:40:13 -06:00
*/
public function edit(Budget $budget)
{
2015-06-13 03:02:36 -05:00
$subTitle = trans('firefly.edit_budget', ['name' => $budget->name]);
2015-02-22 08:40:13 -06:00
2015-04-01 02:40:19 -05:00
// put previous url in session if not redirect from store (not "return_to_edit").
2016-02-04 00:27:03 -06:00
if (session('budgets.edit.fromUpdate') !== true) {
2015-04-01 02:40:19 -05:00
Session::put('budgets.edit.url', URL::previous());
}
Session::forget('budgets.edit.fromUpdate');
2015-05-25 01:12:31 -05:00
Session::flash('gaEventCategory', 'budgets');
Session::flash('gaEventAction', 'edit');
2015-04-01 02:40:19 -05:00
2015-02-22 09:19:32 -06:00
return view('budgets.edit', compact('budget', 'subTitle'));
2015-02-22 08:40:13 -06:00
}
2015-02-22 02:46:21 -06:00
/**
2016-05-20 04:02:07 -05:00
* @return View
2015-02-22 02:46:21 -06:00
*/
2016-12-22 09:36:56 -06:00
public function index()
2015-02-22 02:46:21 -06:00
{
2016-12-22 09:36:56 -06:00
$this->repository->cleanupBudgets();
2016-06-07 05:22:46 -05:00
2016-12-22 09:36:56 -06:00
$budgets = $this->repository->getActiveBudgets();
$inactive = $this->repository->getInactiveBudgets();
$start = session('start', new Carbon);
2016-04-25 06:20:42 -05:00
$end = session('end', new Carbon);
$periodStart = $start->formatLocalized($this->monthAndDayFormat);
$periodEnd = $end->formatLocalized($this->monthAndDayFormat);
2016-12-22 09:36:56 -06:00
$budgetInformation = $this->collectBudgetInformation($budgets, $start, $end);
$defaultCurrency = Amount::getDefaultCurrency();
$available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end);
$spent = array_sum(array_column($budgetInformation, 'spent'));
$budgeted = array_sum(array_column($budgetInformation, 'budgeted'));
2015-02-22 02:46:21 -06:00
2015-05-24 15:54:59 -05:00
return view(
2016-12-22 09:36:56 -06:00
'budgets.index',
compact('available', 'periodStart', 'periodEnd', 'budgetInformation', 'inactive', 'budgets', 'spent', 'budgeted')
2015-05-24 15:54:59 -05:00
);
2015-02-22 02:46:21 -06:00
}
2015-02-22 08:40:13 -06:00
/**
2016-12-28 06:02:56 -06:00
* @param Request $request
*
* @return View
2015-02-22 08:40:13 -06:00
*/
2016-12-28 06:02:56 -06:00
public function noBudget(Request $request)
2015-02-22 08:40:13 -06:00
{
/** @var Carbon $start */
$start = session('start', Carbon::now()->startOfMonth());
/** @var Carbon $end */
2016-11-05 12:43:18 -05:00
$end = session('end', Carbon::now()->endOfMonth());
2016-12-28 06:02:56 -06:00
$page = intval($request->get('page')) == 0 ? 1 : intval($request->get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
2016-09-16 05:07:45 -05:00
$subTitle = trans(
'firefly.without_budget_between',
2015-05-25 14:17:36 -05:00
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
2015-02-22 08:40:13 -06:00
// collector
2016-12-28 04:34:00 -06:00
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
$collector->setAllAssetAccounts()->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withoutBudget();
2016-11-05 12:43:18 -05:00
$journals = $collector->getPaginatedJournals();
$journals->setPath('/budgets/list/noBudget');
return view('budgets.no-budget', compact('journals', 'subTitle'));
2015-02-22 08:40:13 -06:00
}
/**
2015-05-03 05:54:39 -05:00
* @return \Illuminate\Http\RedirectResponse
2015-02-22 08:40:13 -06:00
*/
2016-12-22 09:36:56 -06:00
public function postUpdateIncome(BudgetIncomeRequest $request)
2015-02-22 08:40:13 -06:00
{
2016-12-22 09:36:56 -06:00
$start = session('start', new Carbon);
$end = session('end', new Carbon);
$defaultCurrency = Amount::getDefaultCurrency();
$amount = $request->get('amount');
$this->repository->setAvailableBudget($defaultCurrency, $start, $end, $amount);
Preferences::mark();
2015-02-22 08:40:13 -06:00
2015-07-06 09:27:21 -05:00
return redirect(route('budgets.index'));
2015-02-22 08:40:13 -06:00
}
2015-04-05 03:36:28 -05:00
/**
2016-12-28 06:02:56 -06:00
* @param Request $request
2016-10-29 09:11:54 -05:00
* @param BudgetRepositoryInterface $repository
* @param AccountRepositoryInterface $accountRepository
* @param Budget $budget
2015-04-05 03:36:28 -05:00
*
2016-02-05 22:01:34 -06:00
* @return View
2015-04-05 03:36:28 -05:00
*/
2016-12-28 06:02:56 -06:00
public function show(Request $request, BudgetRepositoryInterface $repository, AccountRepositoryInterface $accountRepository, Budget $budget)
2015-04-05 03:36:28 -05:00
{
2016-05-05 23:15:46 -05:00
/** @var Carbon $start */
2016-12-11 07:03:30 -06:00
$start = session('first', Carbon::create()->startOfYear());
$end = new Carbon;
2016-12-28 06:02:56 -06:00
$page = intval($request->get('page')) == 0 ? 1 : intval($request->get('page'));
2016-12-11 07:03:30 -06:00
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
$repetition = null;
// collector:
2016-12-28 04:34:00 -06:00
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
2016-12-27 23:14:58 -06:00
$collector->setAllAssetAccounts()->setRange($start, $end)->setBudget($budget)->setLimit($pageSize)->setPage($page)->withCategoryInformation();
2016-11-05 12:43:18 -05:00
$journals = $collector->getPaginatedJournals();
2016-05-05 23:15:46 -05:00
$journals->setPath('/budgets/show/' . $budget->id);
2016-12-30 07:24:16 -06:00
$set = $repository->getBudgetLimits($budget, $start, $end);
2016-04-29 01:56:56 -05:00
$subTitle = e($budget->name);
2016-05-05 23:15:46 -05:00
$limits = new Collection();
2016-04-29 01:56:56 -05:00
2016-12-30 00:39:42 -06:00
/** @var BudgetLimit $entry */
2016-04-29 01:56:56 -05:00
foreach ($set as $entry) {
2016-12-30 00:39:42 -06:00
$entry->spent = $repository->spentInPeriod(new Collection([$budget]), $accounts, $entry->start_date, $entry->end_date);
2016-04-29 01:56:56 -05:00
$limits->push($entry);
2015-04-05 03:36:28 -05:00
}
2016-04-29 01:56:56 -05:00
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle'));
}
/**
2016-12-30 00:39:42 -06:00
* @param Request $request
* @param Budget $budget
* @param BudgetLimit $budgetLimit
2016-04-29 01:56:56 -05:00
*
* @return View
* @throws FireflyException
*/
2016-12-30 00:39:42 -06:00
public function showByBudgetLimit(Request $request, Budget $budget, BudgetLimit $budgetLimit)
2016-11-26 02:16:06 -06:00
{
2016-12-30 01:41:48 -06:00
if ($budgetLimit->budget->id != $budget->id) {
2016-04-29 01:56:56 -05:00
throw new FireflyException('This budget limit is not part of this budget.');
2015-06-04 10:43:50 -05:00
}
2016-11-26 02:16:06 -06:00
/** @var BudgetRepositoryInterface $repository */
$repository = app(BudgetRepositoryInterface::class);
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
2016-12-28 06:02:56 -06:00
$page = intval($request->get('page')) == 0 ? 1 : intval($request->get('page'));
2016-11-26 02:16:06 -06:00
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$subTitle = trans(
2016-12-30 00:39:42 -06:00
'firefly.budget_in_period', [
'name' => $budget->name,
'start' => $budgetLimit->start_date->formatLocalized($this->monthAndDayFormat),
'end' => $budgetLimit->end_date->formatLocalized($this->monthAndDayFormat),
]
2016-11-26 02:16:06 -06:00
);
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
2016-10-29 09:11:54 -05:00
// collector:
2016-12-28 04:34:00 -06:00
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class, [auth()->user()]);
2016-12-30 00:39:42 -06:00
$collector->setAllAssetAccounts()->setRange($budgetLimit->start_date, $budgetLimit->end_date)
->setBudget($budget)->setLimit($pageSize)->setPage($page)->withCategoryInformation();
2016-11-05 12:43:18 -05:00
$journals = $collector->getPaginatedJournals();
2016-12-30 00:39:42 -06:00
$journals->setPath('/budgets/show/' . $budget->id . '/' . $budgetLimit->id);
2016-12-30 00:39:42 -06:00
$budgetLimit->spent = $repository->spentInPeriod(new Collection([$budget]), $accounts, $budgetLimit->start_date, $budgetLimit->end_date);
$limits = new Collection([$budgetLimit]);
2015-04-05 03:36:28 -05:00
2016-12-30 00:39:42 -06:00
return view('budgets.show', compact('limits', 'budget', 'budgetLimit', 'journals', 'subTitle'));
2016-04-29 01:56:56 -05:00
2015-04-05 03:36:28 -05:00
}
/**
* @param BudgetFormRequest $request
* @param BudgetRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse
*/
2015-02-22 08:40:13 -06:00
public function store(BudgetFormRequest $request, BudgetRepositoryInterface $repository)
{
2016-10-29 00:44:46 -05:00
$data = $request->getBudgetData();
$budget = $repository->store($data);
2015-02-22 08:40:13 -06:00
2016-03-20 05:38:01 -05:00
Session::flash('success', strval(trans('firefly.stored_new_budget', ['name' => e($budget->name)])));
Preferences::mark();
2015-02-22 08:40:13 -06:00
2016-12-28 06:02:56 -06:00
if (intval($request->get('create_another')) === 1) {
2015-04-01 02:40:19 -05:00
// set value so create routine will not overwrite URL:
Session::put('budgets.create.fromStore', true);
2015-04-05 03:36:28 -05:00
2015-07-06 09:27:21 -05:00
return redirect(route('budgets.create'))->withInput();
2015-03-28 12:22:36 -05:00
}
2015-04-01 02:40:19 -05:00
// redirect to previous URL.
2016-02-04 00:27:03 -06:00
return redirect(session('budgets.create.url'));
2015-02-22 08:40:13 -06:00
}
/**
* @param BudgetFormRequest $request
* @param BudgetRepositoryInterface $repository
2015-05-03 05:54:39 -05:00
* @param Budget $budget
2015-02-22 08:40:13 -06:00
*
* @return \Illuminate\Http\RedirectResponse
2015-02-22 08:40:13 -06:00
*/
2015-05-03 05:54:39 -05:00
public function update(BudgetFormRequest $request, BudgetRepositoryInterface $repository, Budget $budget)
2015-02-22 08:40:13 -06:00
{
2016-10-22 15:03:00 -05:00
$data = $request->getBudgetData();
$repository->update($budget, $data);
2015-02-22 08:40:13 -06:00
2016-03-20 05:38:01 -05:00
Session::flash('success', strval(trans('firefly.updated_budget', ['name' => e($budget->name)])));
Preferences::mark();
2015-02-22 08:40:13 -06:00
2016-12-28 06:02:56 -06:00
if (intval($request->get('return_to_edit')) === 1) {
2015-04-01 02:40:19 -05:00
// set value so edit routine will not overwrite URL:
Session::put('budgets.edit.fromUpdate', true);
2015-04-05 03:36:28 -05:00
2015-07-06 09:27:21 -05:00
return redirect(route('budgets.edit', [$budget->id]))->withInput(['return_to_edit' => 1]);
}
2015-04-01 02:43:19 -05:00
// redirect to previous URL.
2016-02-04 00:27:03 -06:00
return redirect(session('budgets.edit.url'));
2015-02-22 08:40:13 -06:00
}
/**
* @return View
2015-02-22 08:40:13 -06:00
*/
public function updateIncome()
{
2016-12-22 09:36:56 -06:00
$start = session('start', new Carbon);
$end = session('end', new Carbon);
$defaultCurrency = Amount::getDefaultCurrency();
$available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end);
return view('budgets.income', compact('available', 'start', 'end'));
}
/**
* @param Collection $budgets
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
private function collectBudgetInformation(Collection $budgets, Carbon $start, Carbon $end): array
{
// get account information
$accountRepository = app(AccountRepositoryInterface::class);
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
$return = [];
/** @var Budget $budget */
foreach ($budgets as $budget) {
$budgetId = $budget->id;
$return[$budgetId] = [
'spent' => $this->repository->spentInPeriod(new Collection([$budget]), $accounts, $start, $end),
'budgeted' => '0',
'currentRep' => false,
];
2016-12-29 13:48:33 -06:00
$budgetLimits = $this->repository->getBudgetLimits($budget, $start, $end);
$otherLimits = new Collection;
// get all the budget limits relevant between start and end and examine them:
/** @var BudgetLimit $limit */
foreach ($budgetLimits as $limit) {
if ($limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end)
) {
$return[$budgetId]['currentLimit'] = $limit;
2016-12-30 00:39:42 -06:00
$return[$budgetId]['budgeted'] = $limit->amount;
2016-12-29 13:48:33 -06:00
continue;
2016-12-22 09:36:56 -06:00
}
2016-12-29 13:48:33 -06:00
// otherwise it's just one of the many relevant repetitions:
$otherLimits->push($limit);
2016-12-22 09:36:56 -06:00
}
2016-12-29 13:48:33 -06:00
$return[$budgetId]['otherLimits'] = $otherLimits;
2016-12-22 09:36:56 -06:00
}
return $return;
2015-02-22 08:40:13 -06:00
}
2015-02-22 02:46:21 -06:00
}