From f68c1aff267864cb2d0c1f1fd37db484ed81f21c Mon Sep 17 00:00:00 2001 From: Sander Dorigo Date: Sat, 11 Oct 2014 18:52:24 +0200 Subject: [PATCH 1/3] Cleaned up the show view. --- app/views/recurring/show.blade.php | 103 +++++++++++++---------------- 1 file changed, 46 insertions(+), 57 deletions(-) diff --git a/app/views/recurring/show.blade.php b/app/views/recurring/show.blade.php index 48f68e5c65..8cfc398c74 100644 --- a/app/views/recurring/show.blade.php +++ b/app/views/recurring/show.blade.php @@ -1,68 +1,57 @@ @extends('layouts.default') @section('content') -
-
-

Use recurring transactions to track repeated withdrawals

-

-

-

-
-
-
+
+
+ {{{$recurring->name}}} - - - - - - - - - - - - - - - - - - - - - - - + @if($recurring->active) + + @else + + @endif - - -
Matches on: - @foreach(explode(' ',$recurring->match) as $word) - {{{$word}}} - @endforeach -
Between {{mf($recurring->amount_min)}} – {{mf($recurring->amount_max)}}
Repeats{{ucfirst($recurring->repeat_freq)}}
Next reminder{{$recurring->next()->format('d-m-Y')}}
Will be auto-matched - @if($recurring->automatch) - - @else - - @endif -
Is active - @if($recurring->active) - - @else - - @endif -
+ @if($recurring->automatch) + + @else + + @endif - + +
+
+ + +
+
- - +
+
+ + + + + + + + + +
+ Matching on + @foreach(explode(' ',$recurring->match) as $word) + {{{$word}}} + @endforeach + between {{mf($recurring->amount_min)}} and {{mf($recurring->amount_max)}}. + Repeats {{$recurring->repeat_freq}}.
Next reminderTODO TODO
+
+
@stop \ No newline at end of file From 7d2dab7ca070b18c0023bc3b0ab5e9b74ec34185 Mon Sep 17 00:00:00 2001 From: Sander Dorigo Date: Sat, 11 Oct 2014 21:23:31 +0200 Subject: [PATCH 2/3] First set of code. --- app/controllers/JsonController.php | 26 +- app/routes.php | 1 + app/views/recurring/show.blade.php | 39 +++ public/assets/javascript/firefly/recurring.js | 302 ++++++++++++------ 4 files changed, 260 insertions(+), 108 deletions(-) diff --git a/app/controllers/JsonController.php b/app/controllers/JsonController.php index 39dd28369d..671e771b95 100644 --- a/app/controllers/JsonController.php +++ b/app/controllers/JsonController.php @@ -19,7 +19,6 @@ class JsonController extends BaseController $this->helper = $helper; - } /** @@ -97,11 +96,32 @@ class JsonController extends BaseController return Response::json($resultSet); } + /** + * + */ + public function recurringjournals(RecurringTransaction $recurringTransaction) + { + $parameters = $this->helper->dataTableParameters(); + $parameters['transactionTypes'] = ['Withdrawal']; + $parameters['amount'] = 'negative'; + + $query = $this->helper->journalQuery($parameters); + + $query->where('recurring_transaction_id', $recurringTransaction->id); + $resultSet = $this->helper->journalDataset($parameters, $query); + + + /* + * Build return data: + */ + return Response::json($resultSet); + } + public function recurring() { $parameters = $this->helper->dataTableParameters(); - $query = $this->helper->recurringTransactionsQuery($parameters); - $resultSet = $this->helper->recurringTransactionsDataset($parameters, $query); + $query = $this->helper->recurringTransactionsQuery($parameters); + $resultSet = $this->helper->recurringTransactionsDataset($parameters, $query); return Response::json($resultSet); } diff --git a/app/routes.php b/app/routes.php index 920b590251..da830e8729 100644 --- a/app/routes.php +++ b/app/routes.php @@ -187,6 +187,7 @@ Route::group(['before' => 'auth'], function () { Route::get('/json/revenue', ['uses' => 'JsonController@revenue', 'as' => 'json.revenue']); Route::get('/json/transfers', ['uses' => 'JsonController@transfers', 'as' => 'json.transfers']); Route::get('/json/recurring', ['uses' => 'JsonController@recurring', 'as' => 'json.recurring']); + Route::get('/json/recurringjournals/{recurring}', ['uses' => 'JsonController@recurringjournals', 'as' => 'json.recurringjournals']); // limit controller: Route::get('/budgets/limits/create/{budget?}',['uses' => 'LimitController@create','as' => 'budgets.limits.create']); diff --git a/app/views/recurring/show.blade.php b/app/views/recurring/show.blade.php index 8cfc398c74..918b52d638 100644 --- a/app/views/recurring/show.blade.php +++ b/app/views/recurring/show.blade.php @@ -54,4 +54,43 @@ + +
+
+
+
+ Connected transaction journals +
+
+ + + + + + + + + + + + +
DateDescriptionAmount (€)FromToBudget / categoryID
+
+
+
+
+ +@stop + +@section('scripts') + +{{HTML::script('assets/javascript/typeahead/bootstrap3-typeahead.min.js')}} +{{HTML::script('assets/javascript/datatables/jquery.dataTables.min.js')}} +{{HTML::script('assets/javascript/datatables/dataTables.bootstrap.js')}} +{{HTML::script('assets/javascript/firefly/recurring.js')}} +@stop +@section('styles') +{{HTML::style('assets/stylesheets/datatables/dataTables.bootstrap.css')}} @stop \ No newline at end of file diff --git a/public/assets/javascript/firefly/recurring.js b/public/assets/javascript/firefly/recurring.js index 7580654bcc..06aacad3f4 100644 --- a/public/assets/javascript/firefly/recurring.js +++ b/public/assets/javascript/firefly/recurring.js @@ -1,112 +1,204 @@ $(document).ready(function () { - $('#recurringTable').DataTable( - { - serverSide: true, - ajax: URL, - paging: true, - processing: true, - order: [], - "lengthMenu": [[50, 100, 250, -1], [50, 100, 250, "All"]], - columns: [ + if ($('#recurringTable').length > 0) { + $('#recurringTable').DataTable( { - name: 'name', - data: 'name', - searchable: true, - title: 'Name', - render: function (data) { - return '' + data.name + ''; - } - }, - { - name: 'match', - data: 'match', - searchable: true, - title: 'Matches on', - render: function (data) { - var str = ''; - for (x in data) { - str += '' + data[x] + ' '; - } - return str;//return '' + data.name + ''; - } - }, - { - name: 'amount_min', - data: 'amount_min', - searchable: false, - title: '→', - render: function (data) { - return '\u20AC ' + data.toFixed(2) + ''; - } - }, - { - name: 'amount_max', - data: 'amount_max', - searchable: false, - title: '←', - render: function (data) { - return '\u20AC ' + data.toFixed(2) + ''; - } + serverSide: true, + ajax: URL, + paging: true, + processing: true, + order: [], + "lengthMenu": [[50, 100, 250, -1], [50, 100, 250, "All"]], + columns: [ + { + name: 'name', + data: 'name', + searchable: true, + title: 'Name', + render: function (data) { + return '' + data.name + ''; + } + }, + { + name: 'match', + data: 'match', + searchable: true, + title: 'Matches on', + render: function (data) { + var str = ''; + for (x in data) { + str += '' + data[x] + ' '; + } + return str;//return '' + data.name + ''; + } + }, + { + name: 'amount_min', + data: 'amount_min', + searchable: false, + title: '→', + render: function (data) { + return '\u20AC ' + data.toFixed(2) + ''; + } + }, + { + name: 'amount_max', + data: 'amount_max', + searchable: false, + title: '←', + render: function (data) { + return '\u20AC ' + data.toFixed(2) + ''; + } - }, - { - name: 'date', - data: 'date', - title: 'Expected on', - searchable: false - }, + }, + { + name: 'date', + data: 'date', + title: 'Expected on', + searchable: false + }, - { - name: 'active', - data: 'active', - searchable: false, - sortable: false, - render: function(data) { - if(data == 1) { - return ''; - } else { - return ''; + { + name: 'active', + data: 'active', + searchable: false, + sortable: false, + render: function (data) { + if (data == 1) { + return ''; + } else { + return ''; + } + }, + title: 'Is active?' + }, + { + name: 'automatch', + data: 'automatch', + sortable: false, + searchable: false, + render: function (data) { + if (data == 1) { + return ''; + } else { + return ''; + } + }, + title: 'Automatch?' + }, + { + name: 'repeat_freq', + data: 'repeat_freq', + searchable: false, + sortable: false, + title: 'Repeat frequency' + }, + { + name: 'id', + data: 'id', + searchable: false, + sortable: false, + title: '', + render: function (data, type, full, meta) { + return ''; + } } - }, - title: 'Is active?' - }, - { - name: 'automatch', - data: 'automatch', - sortable: false, - searchable: false, - render: function(data) { - if(data == 1) { - return ''; - } else { - return ''; - } - }, - title: 'Automatch?' - }, - { - name: 'repeat_freq', - data: 'repeat_freq', - searchable: false, - sortable: false, - title: 'Repeat frequency' - }, - { - name: 'id', - data: 'id', - searchable: false, - sortable: false, - title: '', - render: function (data, type, full, meta) { - return ''; - } + ] } - ] + ); } - ); -}); \ No newline at end of file + if ($('#transactionTable').length > 0) { + $('#transactionTable').DataTable( + { + serverSide: true, + ajax: URL, + paging: true, + processing: true, + order: [], + "lengthMenu": [[50, 100, 250, -1], [50, 100, 250, "All"]], + columns: [ + { + name: 'date', + data: 'date', + searchable: false + }, + { + name: 'description', + data: 'description', + render: function (data, type, full, meta) { + icon = 'glyphicon-arrow-left'; + + return ' ' + + '' + data.description + ''; + } + }, + { + name: 'amount', + data: 'amount', + 'title': 'Amount (\u20AC)', + searchable: false, + render: function (data, type, full, meta) { + return '\u20AC ' + data.toFixed(2) + ''; + } + }, + { + name: 'from', + data: 'from', + searchable: false, + render: function (data, type, full, meta) { + return '' + data.name + ''; + } + }, + { + name: 'to', + data: 'to', + searchable: false, + render: function (data, type, full, meta) { + return '' + data.name + ''; + } + }, + { + name: 'components', + data: 'components', + searchable: true, + sortable: false, + title: '', + render: function (data, type, full, meta) { + var html = ''; + if (data.budget_id > 0) { + html += ' '; + } + if (data.category_id > 0) { + html += ' '; + } + if (data.recurring_id > 0) { + html += ' '; + } + return html; + } + }, + { + name: 'id', + data: 'id', + searchable: false, + sortable: false, + title: '', + render: function (data, type, full, meta) { + return ''; + } + } + ] + } + ); + } + } +); \ No newline at end of file From 287c2e7af80f53de9b06df70642d6d1aab60278b Mon Sep 17 00:00:00 2001 From: Sander Dorigo Date: Sun, 12 Oct 2014 07:33:45 +0200 Subject: [PATCH 3/3] Added the ability to change the range preference on the fly. --- app/config/firefly.php | 10 ++- app/controllers/HomeController.php | 32 ++++++--- app/lib/Firefly/Helper/Toolkit/Toolkit.php | 84 +++++++++++++++------- app/routes.php | 1 + app/views/partials/date_nav.blade.php | 16 +++++ 5 files changed, 110 insertions(+), 33 deletions(-) diff --git a/app/config/firefly.php b/app/config/firefly.php index cb985a38c2..61ccb7820e 100644 --- a/app/config/firefly.php +++ b/app/config/firefly.php @@ -2,7 +2,7 @@ use Carbon\Carbon; return [ - 'index_periods' => ['1D', '1W', '1M', '3M', '6M', 'custom'], + 'index_periods' => ['1D', '1W', '1M', '3M', '6M','1Y', 'custom'], 'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'], 'piggybank_periods' => ['day', 'week', 'month', 'year'], 'periods_to_text' => [ @@ -21,6 +21,14 @@ return [ '6M' => 'half year', 'custom' => '(custom)' ], + 'range_to_name' => [ + '1D' => 'one day', + '1W' => 'one week', + '1M' => 'one month', + '3M' => 'three months', + '6M' => 'six months', + '1Y' => 'one year', + ], 'range_to_repeat_freq' => [ '1D' => 'weekly', '1W' => 'weekly', diff --git a/app/controllers/HomeController.php b/app/controllers/HomeController.php index 86eb6feb1b..621dea28c6 100644 --- a/app/controllers/HomeController.php +++ b/app/controllers/HomeController.php @@ -17,10 +17,10 @@ class HomeController extends BaseController protected $_reminders; /** - * @param ARI $accounts - * @param PHI $preferences + * @param ARI $accounts + * @param PHI $preferences * @param TJRI $journal - * @param RRI $reminders + * @param RRI $reminders */ public function __construct(ARI $accounts, PHI $preferences, TJRI $journal, RRI $reminders) { @@ -30,8 +30,9 @@ class HomeController extends BaseController $this->_reminders = $reminders; } - public function jobDev() { - $fullName = storage_path().DIRECTORY_SEPARATOR.'firefly-export-2014-07-23.json'; + public function jobDev() + { + $fullName = storage_path() . DIRECTORY_SEPARATOR . 'firefly-export-2014-07-23.json'; \Log::notice('Pushed start job.'); Queue::push('Firefly\Queue\Import@start', ['file' => $fullName, 'user' => 1]); @@ -40,7 +41,8 @@ class HomeController extends BaseController /* * */ - public function sessionPrev() { + public function sessionPrev() + { /** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */ $toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface'); $toolkit->prev(); @@ -51,7 +53,8 @@ class HomeController extends BaseController /* * */ - public function sessionNext() { + public function sessionNext() + { /** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */ $toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface'); $toolkit->next(); @@ -59,6 +62,19 @@ class HomeController extends BaseController //return Redirect::route('index'); } + public function rangeJump($range) + { + + $viewRange = $this->_preferences->get('viewRange', '1M'); + $valid = ['1D', '1W', '1M', '3M', '6M', '1Y',]; + + if(in_array($range,$valid)) { + $this->_preferences->set('viewRange', $range); + Session::forget('range'); + } + return Redirect::back(); + } + /** * @return \Illuminate\Http\RedirectResponse */ @@ -102,6 +118,6 @@ class HomeController extends BaseController // build the home screen: return View::make('index')->with('count', $count)->with('transactions', $transactions)->with('title', 'Firefly') - ->with('subTitle', 'What\'s playing?')->with('mainTitleIcon','fa-fire'); + ->with('subTitle', 'What\'s playing?')->with('mainTitleIcon', 'fa-fire'); } } \ No newline at end of file diff --git a/app/lib/Firefly/Helper/Toolkit/Toolkit.php b/app/lib/Firefly/Helper/Toolkit/Toolkit.php index 11efec7021..90674e381e 100644 --- a/app/lib/Firefly/Helper/Toolkit/Toolkit.php +++ b/app/lib/Firefly/Helper/Toolkit/Toolkit.php @@ -84,22 +84,23 @@ class Toolkit implements ToolkitInterface /** * */ - public function checkImportJobs() { + public function checkImportJobs() + { /* * Get all jobs. */ /** @var \Importmap $importJob */ - $importJob = \Importmap::where('user_id',\Auth::user()->id) - ->where('totaljobs','>',\DB::Raw('`jobsdone`')) - ->orderBy('created_at','DESC') - ->first(); - if(!is_null($importJob)) { - $diff = intval($importJob->totaljobs) - intval($importJob->jobsdone); - $date = new Carbon; + $importJob = \Importmap::where('user_id', \Auth::user()->id) + ->where('totaljobs', '>', \DB::Raw('`jobsdone`')) + ->orderBy('created_at', 'DESC') + ->first(); + if (!is_null($importJob)) { + $diff = intval($importJob->totaljobs) - intval($importJob->jobsdone); + $date = new Carbon; $today = new Carbon; $date->addSeconds($diff); - \Session::put('job_pct',$importJob->pct()); - \Session::put('job_text',$date->diffForHumans()); + \Session::put('job_pct', $importJob->pct()); + \Session::put('job_text', $date->diffForHumans()); } else { \Session::forget('job_pct'); \Session::forget('job_text'); @@ -134,7 +135,6 @@ class Toolkit implements ToolkitInterface */ protected function _updateStartDate($range, Carbon $start) { - $today = new Carbon; switch ($range) { case '1D': $start->startOfDay(); @@ -149,12 +149,15 @@ class Toolkit implements ToolkitInterface $start->firstOfQuarter(); break; case '6M': - if (intval($today->format('m')) >= 7) { + if (intval($start->format('m')) >= 7) { $start->startOfYear()->addMonths(6); } else { $start->startOfYear(); } break; + case '1Y': + $start->startOfYear(); + break; } return $start; @@ -170,33 +173,32 @@ class Toolkit implements ToolkitInterface */ protected function _updateEndDate($range, Carbon $start) { + $end = clone $start; switch ($range) { case '1D': - $end = clone $start; $end->endOfDay(); break; case '1W': - $end = clone $start; $end->endOfWeek(); break; case '1M': - $end = clone $start; $end->endOfMonth(); break; case '3M': - $end = clone $start; $end->lastOfQuarter(); break; case '6M': - $end = clone $start; if (intval($start->format('m')) >= 7) { $end->endOfYear(); } else { $end->startOfYear()->addMonths(6); } break; - default: - throw new FireflyException('Nothing happened with $end!'); + case '1Y': + $end->endOfYear(); + break; + default: + throw new FireflyException('_updateEndDate cannot handle $range ' . $range); break; } @@ -209,9 +211,30 @@ class Toolkit implements ToolkitInterface default: throw new FireflyException('No _periodName() for range "' . $range . '"'); break; + case '1D': + return $date->format('jS F Y'); + break; + case '1W': + return 'week ' . $date->format('W, Y'); + break; case '1M': return $date->format('F Y'); break; + case '3M': + $month = intval($date->format('m')); + return 'Q' . ceil(($month / 12) * 4) . ' ' . $date->format('Y'); + break; + case '6M': + $month = intval($date->format('m')); + $half = ceil(($month / 12) * 2); + $halfName = $half == 1 ? 'first' : 'second'; + return $halfName . ' half of ' . $date->format('d-m-Y'); + break; + case '1Y': + return $date->format('Y'); + break; + + } } @@ -231,12 +254,19 @@ class Toolkit implements ToolkitInterface $date->firstOfQuarter()->subMonths(3)->firstOfQuarter(); break; case '6M': - if (intval($date->format('m')) >= 7) { - $date->startOfYear(); - } else { + $month = intval($date->format('m')); + if ($month <= 6) { $date->startOfYear()->subMonths(6); + } else { + $date->startOfYear(); } break; + case '1Y': + $date->startOfYear()->subYear(); + break; + default: + throw new FireflyException('Cannot do _previous() on ' . $range); + break; } return $date; } @@ -254,7 +284,7 @@ class Toolkit implements ToolkitInterface $date->endOfMonth()->addDay()->startOfMonth(); break; case '3M': - $date->lastOfQuarter(); + $date->lastOfQuarter()->addDay(); break; case '6M': if (intval($date->format('m')) >= 7) { @@ -263,6 +293,12 @@ class Toolkit implements ToolkitInterface $date->startOfYear()->addMonths(6); } break; + case '1Y': + $date->startOfYear()->addYear(); + break; + default: + throw new FireflyException('Cannot do _next() on ' . $range); + break; } return $date; } @@ -311,7 +347,7 @@ class Toolkit implements ToolkitInterface * Takes any collection and tries to make a sensible select list compatible array of it. * * @param Collection $set - * @param null $titleField + * @param null $titleField * * @return mixed */ diff --git a/app/routes.php b/app/routes.php index da830e8729..d3e124e4fd 100644 --- a/app/routes.php +++ b/app/routes.php @@ -133,6 +133,7 @@ Route::group(['before' => 'auth'], function () { // some date routes: Route::get('/prev',['uses' => 'HomeController@sessionPrev', 'as' => 'sessionPrev']); Route::get('/next',['uses' => 'HomeController@sessionNext', 'as' => 'sessionNext']); + Route::get('/jump/{range}',['uses' => 'HomeController@rangeJump','as' => 'rangeJump']); // account controller: Route::get('/accounts', ['uses' => 'AccountController@index', 'as' => 'accounts.index']); diff --git a/app/views/partials/date_nav.blade.php b/app/views/partials/date_nav.blade.php index b1ee82d51e..7cce808a0d 100644 --- a/app/views/partials/date_nav.blade.php +++ b/app/views/partials/date_nav.blade.php @@ -2,6 +2,22 @@
{{{\Session::get('period')}}} + + +
+
+ + +
+
+