From 36901359d0e711aa4ff6a455b0e9606934389bb9 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 24 Jul 2014 06:47:28 +0200 Subject: [PATCH] More views and options for limits [skip ci] --- app/controllers/HomeController.php | 17 +-- app/controllers/LimitController.php | 45 +++++++ app/lib/Firefly/Helper/Toolkit/Toolkit.php | 1 - .../Budget/EloquentBudgetRepository.php | 22 +++- .../Storage/Limit/EloquentLimitRepository.php | 4 +- .../EloquentTransactionJournalRepository.php | 4 +- .../TransactionJournalRepositoryInterface.php | 2 +- .../Trigger/Limits/EloquentLimitTrigger.php | 14 --- app/routes.php | 6 +- app/views/budgets/index-date.blade.php | 8 +- app/views/index.blade.php | 114 +++++++++++------- app/views/limits/edit.blade.php | 110 +++++++++++++++++ app/views/transactions/journals.blade.php | 15 +-- 13 files changed, 280 insertions(+), 82 deletions(-) create mode 100644 app/views/limits/edit.blade.php diff --git a/app/controllers/HomeController.php b/app/controllers/HomeController.php index 67912e60d6..019a0f3128 100644 --- a/app/controllers/HomeController.php +++ b/app/controllers/HomeController.php @@ -1,9 +1,9 @@ _accounts->count(); + list($start, $end) = $this->_tk->getDateRange(); // get the preference for the home accounts to show: @@ -53,11 +54,11 @@ class HomeController extends BaseController // get the budgets for this period: $dates = $this->_tk->getDateRange(); - $budgets = $this->_budgets->getWithRepetitionsInPeriod($dates[0],\Session::get('range')); + $budgets = $this->_budgets->getWithRepetitionsInPeriod($dates[0], \Session::get('range')); $transactions = []; foreach ($accounts as $account) { - $transactions[] = [$this->_journal->getByAccount($account, 15), $account]; + $transactions[] = [$this->_journal->getByAccountInDateRange($account, 15, $start, $end), $account]; } if (count($transactions) % 2 == 0) { @@ -68,6 +69,8 @@ class HomeController extends BaseController $transactions = array_chunk($transactions, 3); } // build the home screen: - return View::make('index')->with('count', $count)->with('transactions', $transactions)->with('budgets',$budgets); + return View::make('index')->with('count', $count)->with('transactions', $transactions)->with( + 'budgets', $budgets + ); } } \ No newline at end of file diff --git a/app/controllers/LimitController.php b/app/controllers/LimitController.php index c50c1f9bf2..1476c05b81 100644 --- a/app/controllers/LimitController.php +++ b/app/controllers/LimitController.php @@ -35,6 +35,51 @@ class LimitController extends BaseController ); } + public function edit($limitId = null) + { + $limit = $this->_limits->find($limitId); + $budgets = $this->_budgets->getAsSelectList(); + + $periods = [ + 'weekly' => 'A week', + 'monthly' => 'A month', + 'quarterly' => 'A quarter', + 'half-year' => 'Six months', + 'yearly' => 'A year', + ]; + + + if ($limit) { + return View::make('limits.edit')->with('limit', $limit)->with('budgets', $budgets)-> + with('periods',$periods); + } + + } + + public function update($limitId = null) + { + /** @var \Limit $limit */ + $limit = $this->_limits->find($limitId); + if($limit) { + $limit->startdate = new \Carbon\Carbon(Input::get('date')); + $limit->repeat_freq = Input::get('period'); + $limit->repeats = !is_null(Input::get('repeats')) && Input::get('repeats') == '1' ? 1 : 0; + $limit->amount = floatval(Input::get('amount')); + if(!$limit->save()) { + Session::flash('error','Could not save new limit: ' . $limit->errors()->first()); + return Redirect::route('budgets.limits.edit',$limit->id)->withInput(); + } else { + Session::flash('success','Limit saved!'); + foreach($limit->limitrepetitions()->get() as $rep) { + $rep->delete(); + } + return Redirect::route('budgets.index'); + } + } + return View::make('error')->with('message','No limit!'); + + } + public function store() { // find a limit with these properties, as we might already have one: diff --git a/app/lib/Firefly/Helper/Toolkit/Toolkit.php b/app/lib/Firefly/Helper/Toolkit/Toolkit.php index 1fea808409..58d10ceccc 100644 --- a/app/lib/Firefly/Helper/Toolkit/Toolkit.php +++ b/app/lib/Firefly/Helper/Toolkit/Toolkit.php @@ -20,7 +20,6 @@ class Toolkit implements ToolkitInterface */ public function getDateRange() { - \Log::debug('Should be mocked!'); $preferences = \App::make('Firefly\Helper\Preferences\PreferencesHelperInterface'); $viewRange = $preferences->get('viewRange', '1M'); diff --git a/app/lib/Firefly/Storage/Budget/EloquentBudgetRepository.php b/app/lib/Firefly/Storage/Budget/EloquentBudgetRepository.php index aadb3dbc71..f3d157bdfb 100644 --- a/app/lib/Firefly/Storage/Budget/EloquentBudgetRepository.php +++ b/app/lib/Firefly/Storage/Budget/EloquentBudgetRepository.php @@ -34,13 +34,31 @@ class EloquentBudgetRepository implements BudgetRepositoryInterface // $q->where('startdate',$date->format('Y-m-d')); }, 'limits.limitrepetitions' => function ($q) use ($date) { $q->orderBy('limit_repetitions.startdate', 'ASC'); - $q->where('startdate',$date->format('Y-m-d')); + $q->where('startdate', $date->format('Y-m-d')); }] )->orderBy('name', 'ASC')->get(); foreach ($set as $budget) { $budget->count = 0; - foreach($budget->limits as $limit) { + foreach ($budget->limits as $limit) { + /** @var $rep \LimitRepetition */ + foreach ($limit->limitrepetitions as $rep) { + $rep->left = $rep->left(); + // overspent: + if ($rep->left < 0) { + $rep->spent = ($rep->left * -1) + $rep->amount; + $rep->overspent = $rep->left * -1; + $total = $rep->spent + $rep->overspent; + $rep->spent_pct = round(($rep->spent / $total) * 100); + $rep->overspent_pct = 100 - $rep->spent_pct; + } else { + $rep->spent = $rep->amount - $rep->left; + $rep->spent_pct = round(($rep->spent / $rep->amount) * 100); + $rep->left_pct = 100 - $rep->spent_pct; + + + } + } $budget->count += count($limit->limitrepetitions); } } diff --git a/app/lib/Firefly/Storage/Limit/EloquentLimitRepository.php b/app/lib/Firefly/Storage/Limit/EloquentLimitRepository.php index 141d9bc25f..87619a595c 100644 --- a/app/lib/Firefly/Storage/Limit/EloquentLimitRepository.php +++ b/app/lib/Firefly/Storage/Limit/EloquentLimitRepository.php @@ -14,7 +14,9 @@ class EloquentLimitRepository implements LimitRepositoryInterface public function find($limitId) { - return \Limit::with('limitrepetitions')->where('limits.id', $limitId)->leftJoin('components', 'components.id', '=', 'limits.component_id') + return \Limit::with('limitrepetitions')->where('limits.id', $limitId)->leftJoin( + 'components', 'components.id', '=', 'limits.component_id' + ) ->where('components.user_id', \Auth::user()->id)->first(['limits.*']); } diff --git a/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php b/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php index 598ef2489d..88209ad9e1 100644 --- a/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php +++ b/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php @@ -167,7 +167,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito } - public function getByAccount(\Account $account, $count = 25) + public function getByAccountInDateRange(\Account $account, $count = 25,\Carbon\Carbon $start, \Carbon\Carbon $end) { $accountID = $account->id; $query = \Auth::user()->transactionjournals()->with( @@ -180,6 +180,8 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') ->where('accounts.id', $accountID) + ->where('date','>=',$start->format('Y-m-d')) + ->where('date','<=',$end->format('Y-m-d')) ->orderBy('transaction_journals.date', 'DESC') ->orderBy('transaction_journals.id', 'DESC') ->take($count) diff --git a/app/lib/Firefly/Storage/TransactionJournal/TransactionJournalRepositoryInterface.php b/app/lib/Firefly/Storage/TransactionJournal/TransactionJournalRepositoryInterface.php index 9963dae8a4..1a314211b2 100644 --- a/app/lib/Firefly/Storage/TransactionJournal/TransactionJournalRepositoryInterface.php +++ b/app/lib/Firefly/Storage/TransactionJournal/TransactionJournalRepositoryInterface.php @@ -11,7 +11,7 @@ interface TransactionJournalRepositoryInterface public function find($journalId); - public function getByAccount(\Account $account, $count = 25); + public function getByAccountInDateRange(\Account $account, $count = 25,\Carbon\Carbon $start, \Carbon\Carbon $end); public function getByAccountAndDate(\Account $account, \Carbon\Carbon $date); diff --git a/app/lib/Firefly/Trigger/Limits/EloquentLimitTrigger.php b/app/lib/Firefly/Trigger/Limits/EloquentLimitTrigger.php index 05c8166603..5ebc75ca89 100644 --- a/app/lib/Firefly/Trigger/Limits/EloquentLimitTrigger.php +++ b/app/lib/Firefly/Trigger/Limits/EloquentLimitTrigger.php @@ -25,23 +25,11 @@ class EloquentLimitTrigger // get todays date. foreach ($budgets as $budget) { - \Log::debug( - 'Now checking the ' . count($budget->limits) . ' limits in ' . $budget->name . ' (#' . $budget->id - . ').' - ); // loop limits: foreach ($budget->limits as $limit) { - \Log::debug( - 'Now at limit #' . $limit->id . ', which has ' . count($limit->limitrepetitions) . ' reps already' - ); - \Log::debug( - 'More: Amount: ' . $limit->amount . ', repeat: ' . $limit->repeats . ', freq: ' - . $limit->repeat_freq - ); // should have a repetition, at the very least // for the period it starts (startdate and onwards). if (count($limit->limitrepetitions) == 0) { - \Log::debug('No reps, create one.'); // create such a repetition: $repetition = new \LimitRepetition(); $start = clone $limit->startdate; @@ -73,7 +61,6 @@ class EloquentLimitTrigger $repetition->enddate = $end; $repetition->amount = $limit->amount; $repetition->limit()->associate($limit); - \Log::debug('Created single rep for non-repeating limit, from ' . $start . ' until ' . $end); try { $repetition->save(); @@ -163,7 +150,6 @@ class EloquentLimitTrigger } } } - \Log::debug('Done checking the budget!'); } } diff --git a/app/routes.php b/app/routes.php index 2f5103e29b..957c4a2ae0 100644 --- a/app/routes.php +++ b/app/routes.php @@ -34,6 +34,7 @@ Route::group(['before' => 'auth'], function () { // limit controller: Route::get('/budgets/limits/create/{id?}',['uses' => 'LimitController@create','as' => 'budgets.limits.create']); Route::get('/budgets/limits/delete/{id?}',['uses' => 'LimitController@delete','as' => 'budgets.limits.delete']); + Route::get('/budgets/limits/edit/{id?}',['uses' => 'LimitController@edit','as' => 'budgets.limits.edit']); // JSON controller: Route::get('/json/beneficiaries', ['uses' => 'JsonController@beneficiaries', 'as' => 'json.beneficiaries']); @@ -41,7 +42,7 @@ Route::group(['before' => 'auth'], function () { // transaction controller: - Route::get('/transactions/create/{what}', ['uses' => 'TransactionController@create', 'as' => 'transactions.create'])->where(['what' => 'withdrawal|deposit|transfer']); + Route::get('/transactions/create/{what}', ['uses' => 'TransactionController@create', 'as' => 'transactions.create'])->where(['what' => 'withdrawal|deposit|transfer']); Route::get('/transaction/show/{id}',['uses' => 'TransactionController@show','as' => 'transactions.show']); Route::get('/transaction/edit/{id}',['uses' => 'TransactionController@edit','as' => 'transactions.edit']); Route::get('/transaction/delete/{id}',['uses' => 'TransactionController@delete','as' => 'transactions.delete']); @@ -69,8 +70,9 @@ Route::group(['before' => 'csrf|auth'], function () { Route::get('/accounts/store', ['uses' => 'AccountController@store', 'as' => 'accounts.store']); // limit controller: - Route::post('/limits/store', ['uses' => 'LimitController@store', 'as' => 'budgets.limits.store']); + Route::post('/budgets/limits/store', ['uses' => 'LimitController@store', 'as' => 'budgets.limits.store']); Route::post('/budgets/limits/destroy/{id?}',['uses' => 'LimitController@destroy','as' => 'budgets.limits.destroy']); + Route::post('/budgets/limits/update/{id?}',['uses' => 'LimitController@update','as' => 'budgets.limits.update']); // transaction controller: Route::post('/transactions/store/{what}', ['uses' => 'TransactionController@store', 'as' => 'transactions.store']) diff --git a/app/views/budgets/index-date.blade.php b/app/views/budgets/index-date.blade.php index 5a29d2842c..80e7bcb094 100644 --- a/app/views/budgets/index-date.blade.php +++ b/app/views/budgets/index-date.blade.php @@ -13,6 +13,7 @@ {{{$rep->limit->budget->name}}} + @@ -30,10 +31,15 @@ @endif - +
+ + +
@if($rep->limit->repeats == 1) auto repeats @endif + Add another limit @endforeach diff --git a/app/views/index.blade.php b/app/views/index.blade.php index 3ec780f72c..36c63f8752 100644 --- a/app/views/index.blade.php +++ b/app/views/index.blade.php @@ -9,20 +9,34 @@ @if($count > 0)
-
+
- - - - - - - + + + + + + + - - - -
+ + + +
@endif @@ -32,6 +46,7 @@

Welcome to Firefly III.

+

To get get started, choose below:

@@ -41,18 +56,19 @@

Migrate from Firefly II

+

Use this option if you have a JSON file from your current Firefly II installation.

Start from scratch

+

Use this option if you are new to Firefly (III).

-@else - + @else @@ -78,35 +94,44 @@ @endif -

Budgets

- @foreach($budgets as $budget) - - - @if($budget->count == 0) - - @else - @foreach($budget->limits as $limit) - @foreach($limit->limitrepetitions as $rep) - - - @endforeach - @endforeach - @endif - +
{{{$budget->name}}}
+ @if($budget->count == 0) +

+ No budget set for this period. +

+ @else + @foreach($budget->limits as $limit) + @foreach($limit->limitrepetitions as $rep) + @if($rep->left() < 0) + +
+
{{mf($rep->amount,false)}}
+
{{mf($rep->overspent,false)}} +
+
+ @else + +
+
{{mf($rep->spent,false)}} +
+
{{mf($rep->left,false)}} +
+
+ @endif + + + @endforeach + @endforeach + @endif @endforeach -
- {{{$budget->name}}} - - No budget set for this period. - - {{mf($rep->amount)}} - - {{mf($rep->left())}} -
@@ -117,17 +142,16 @@
+ @endif -@endif - -@stop -@section('scripts') + @stop + @section('scripts') -@stop -@section('styles') + @stop + @section('styles') -@stop \ No newline at end of file + @stop \ No newline at end of file diff --git a/app/views/limits/edit.blade.php b/app/views/limits/edit.blade.php new file mode 100644 index 0000000000..8b80d0d63f --- /dev/null +++ b/app/views/limits/edit.blade.php @@ -0,0 +1,110 @@ +@extends('layouts.default') +@section('content') +
+
+

Firefly + Edit limit of {{mf($limit->amount,false)}} + for budget {{{$limit->budget->name}}} + + @if($limit->repeats == 0) + in {{$limit->limitrepetitions[0]->startdate->format('M Y')}} ({{$limit->repeat_freq}}) + @endif + + +

+

+ Firefly uses an "envelope + system" for your budgets, which means that for each period of time (for example a month) a virtual + "envelope" can be created containing a certain amount of money. Money spent within a budget is removed from + the envelope. +

+ +

+ Firefly gives you the opportunity to create such an envelope when you create a budget. However, you can + always add more of them. +

+
+
+ +{{Form::open(['class' => 'form-horizontal','url' => route('budgets.limits.update',$limit->id)])}} + +
+
+

Mandatory fields

+ +
+ {{ Form::label('budget_id', 'Budget', ['class' => 'col-sm-3 control-label'])}} +
+ {{Form::select('budget_id',$budgets,Input::old('budget_id') ?: $limit->component_id, ['class' => + 'form-control'])}} + @if($errors->has('budget_id')) +

{{$errors->first('name')}}

+ @else + Select one of your existing budgets. + @endif +
+
+ +
+ {{ Form::label('startdate', 'Start date', ['class' => 'col-sm-3 control-label'])}} +
+ + This date indicates when the envelope "starts". The date you select + here will correct itself to the nearest [period] you select below. +
+
+ +
+ + +
+ {{Form::select('period',$periods,Input::old('period') ?: $limit->repeat_freq,['class' => 'form-control'])}} + How long will the envelope last? A week, a month, or even longer? +
+
+
+ + +
+
+ +
+ If you want, Firefly can automatically recreate the "envelope" and fill it again + when the timespan above has expired. Be careful with this option though. It makes it easier + to fall back to old habits. + Instead, you should recreate the envelope yourself each [period]. +
+
+ + +
+ {{ Form::label('amount', 'Amount', ['class' => 'col-sm-3 control-label'])}} +
+ + Of course, there needs to be money in the envelope. +
+
+ +
+ {{ Form::label('submit', ' ', ['class' => 'col-sm-3 control-label'])}} +
+ + +
+
+ +
+
+ +{{Form::open()}} + + +@stop +@section('scripts') + + +@stop \ No newline at end of file diff --git a/app/views/transactions/journals.blade.php b/app/views/transactions/journals.blade.php index 32259b19a6..39786eb10a 100644 --- a/app/views/transactions/journals.blade.php +++ b/app/views/transactions/journals.blade.php @@ -1,9 +1,9 @@ - - - - + + + + @foreach($transactions as $journal) @@ -20,14 +20,15 @@ @endif - - - + + @endforeach
 DescriptionDateAmount DescriptionDateAmount
{{{$journal->description}}}{{$journal->date->format('jS M Y')}} + {{{$journal->description}}}{{$journal->date->format('jS M Y')}} @foreach($journal->transactions as $t) @if($t->account_id == $account->id) {{mf($t->amount)}} @endif @endforeach +