From 36d8dee853c3f92a4711ec6583ca7223610c9460 Mon Sep 17 00:00:00 2001
From: Sander Dorigo
Date: Mon, 13 Oct 2014 17:54:20 +0200
Subject: [PATCH] Building a chart for the recurring transactions.
---
app/controllers/ChartController.php | 189 ++++++++++++++----
app/controllers/RecurringController.php | 6 +-
...14_08_23_113221_create_reminders_table.php | 1 -
app/filters.php | 1 +
app/lib/Firefly/Helper/Controllers/Json.php | 7 +-
app/lib/Firefly/Helper/Toolkit/Toolkit.php | 123 ++++++++++++
.../Helper/Toolkit/ToolkitInterface.php | 9 +-
.../Recurring/EloquentRecurringTrigger.php | 5 +-
app/models/Reminder.php | 72 +------
app/models/TransactionJournal.php | 16 ++
app/routes.php | 1 +
app/views/index.blade.php | 26 ++-
public/assets/javascript/firefly/index.js | 38 +++-
13 files changed, 373 insertions(+), 121 deletions(-)
diff --git a/app/controllers/ChartController.php b/app/controllers/ChartController.php
index f6301fd9ab..546972335d 100644
--- a/app/controllers/ChartController.php
+++ b/app/controllers/ChartController.php
@@ -1,8 +1,10 @@
'Overview for budget ' . $budget->name,
- 'subtitle' => 'All envelopes',
- 'series' => [
+ 'subtitle' => 'All envelopes',
+ 'series' => [
[
- 'type' => 'line',
+ 'type' => 'line',
'yAxis' => 1,
- 'name' => 'Amount in envelope',
- 'data' => $envelope
+ 'name' => 'Amount in envelope',
+ 'data' => $envelope
],
[
'type' => 'column',
@@ -71,10 +73,10 @@ class ChartController extends BaseController
'data' => $expense
],
[
- 'type' => 'line',
+ 'type' => 'line',
'yAxis' => 1,
- 'name' => 'Spent percentage for envelope',
- 'data' => $left
+ 'name' => 'Spent percentage for envelope',
+ 'data' => $left
]
@@ -111,14 +113,14 @@ class ChartController extends BaseController
$return = [
'chart_title' => 'Overview for budget ' . $budget->name,
- 'subtitle' =>
+ 'subtitle' =>
'Between ' . $rep->startdate->format('M jS, Y') . ' and ' . $rep->enddate->format('M jS, Y'),
- 'series' => [
+ 'series' => [
[
- 'type' => 'column',
- 'name' => 'Expenses per day',
+ 'type' => 'column',
+ 'name' => 'Expenses per day',
'yAxis' => 1,
- 'data' => $expense
+ 'data' => $expense
],
[
'type' => 'line',
@@ -175,8 +177,8 @@ class ChartController extends BaseController
}
$return = [
'chart_title' => 'Overview for ' . $budget->name,
- 'subtitle' => 'Not organized by an envelope',
- 'series' => [
+ 'subtitle' => 'Not organized by an envelope',
+ 'series' => [
[
'type' => 'column',
'name' => 'Expenses per day',
@@ -245,11 +247,11 @@ class ChartController extends BaseController
// create a serie for the repetition.
$currentSerie = [
- 'type' => 'spline',
- 'id' => 'rep-' . $repetition->id,
+ 'type' => 'spline',
+ 'id' => 'rep-' . $repetition->id,
'yAxis' => 1,
- 'name' => 'Envelope #' . $repetition->id . ' in ' . $repetition->periodShow(),
- 'data' => []
+ 'name' => 'Envelope #' . $repetition->id . ' in ' . $repetition->periodShow(),
+ 'data' => []
];
$current = clone $repetition->startdate;
while ($current <= $repetition->enddate) {
@@ -271,11 +273,11 @@ class ChartController extends BaseController
$return = [
'chart_title' => 'Overview for budget ' . $budget->name,
- 'subtitle' =>
+ 'subtitle' =>
'Between ' . Session::get('start')->format('M jS, Y') . ' and ' . Session::get('end')->format(
'M jS, Y'
),
- 'series' => $series
+ 'series' => $series
];
return Response::json($return);
@@ -296,8 +298,8 @@ class ChartController extends BaseController
$serie = $this->_chart->categoryShowChart($category, $range, $start, $end);
$data = [
'chart_title' => $category->name,
- 'subtitle' => 'View more',
- 'series' => $serie
+ 'subtitle' => 'View more',
+ 'series' => $serie
];
return Response::json($data);
@@ -336,8 +338,8 @@ class ChartController extends BaseController
'View more';
$data = [
'chart_title' => count($accounts) == 1 ? $accounts[0]->name : 'All accounts',
- 'subtitle' => $url,
- 'series' => []
+ 'subtitle' => $url,
+ 'series' => []
];
foreach ($accounts as $account) {
@@ -431,11 +433,11 @@ class ChartController extends BaseController
if ($limit > 0 || $expenses > 0) {
$data['labels'][] = $budget->name;
$data['series'][0]['data'][] = [
- 'y' => $limit,
+ 'y' => $limit,
'url' => route('budgets.show', [$budget->id, $id]) . '?' . $parameter
];
$data['series'][1]['data'][] = [
- 'y' => $expenses,
+ 'y' => $expenses,
'url' => route('budgets.show', [$budget->id, $id]) . '?' . $parameter
];
}
@@ -444,26 +446,26 @@ class ChartController extends BaseController
$set = \Auth::user()->transactionjournals()->whereNotIn(
'transaction_journals.id', function ($query) use ($start, $end) {
$query->select('transaction_journals.id')->from('transaction_journals')
- ->leftJoin(
- 'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=',
- 'transaction_journals.id'
- )
- ->leftJoin('components', 'components.id', '=', 'component_transaction_journal.component_id')
- ->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
- ->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
- ->where('components.class', 'Budget');
+ ->leftJoin(
+ 'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=',
+ 'transaction_journals.id'
+ )
+ ->leftJoin('components', 'components.id', '=', 'component_transaction_journal.component_id')
+ ->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
+ ->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
+ ->where('components.class', 'Budget');
}
)->before($end)->after($start)->lessThan(0)->transactionTypes(['Withdrawal'])->sum('amount');
// This can be debugged by using get(['transaction_journals.*','transactions.amount']);
$data['labels'][] = 'No budget';
$data['series'][0]['data'][] = [
- 'y' => 0,
- 'url' => route('budgets.nobudget','session')
+ 'y' => 0,
+ 'url' => route('budgets.nobudget', 'session')
];
$data['series'][1]['data'][] = [
- 'y' => floatval($set) * -1,
- 'url' => route('budgets.nobudget','session')
+ 'y' => floatval($set) * -1,
+ 'url' => route('budgets.nobudget', 'session')
];
return Response::json($data);
@@ -482,4 +484,111 @@ class ChartController extends BaseController
}
+
+ /**
+ * This method checks all recurring transactions, calculates the current "moment" and returns
+ * a list of yet to be paid (and paid) recurring transactions. This list can be used to show a beautiful chart
+ * to the end user who will love it and cherish it.
+ *
+ * @throws FireflyException
+ */
+ public function homeRecurring()
+ {
+ /** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */
+ $toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface');
+ $recurringTransactions = \Auth::user()->recurringtransactions()->get();
+ $sessionStart = \Session::get('start');
+ $sessionEnd = \Session::get('end');
+ $paid = [];
+ $unpaid = [];
+
+ /** @var \RecurringTransaction $recurring */
+ foreach ($recurringTransactions as $recurring) {
+ /*
+ * Start a loop starting at the $date.
+ */
+ $start = clone $recurring->date;
+ $end = Carbon::now();
+
+ /*
+ * The jump we make depends on the $repeat_freq
+ */
+ $current = clone $start;
+
+ \Log::debug('Now looping recurring transaction #' . $recurring->id . ': ' . $recurring->name);
+
+ while ($current <= $end) {
+ /*
+ * Get end of period for $current:
+ */
+ $currentEnd = clone $current;
+ $toolkit->endOfPeriod($currentEnd, $recurring->repeat_freq);
+ \Log::debug('Now at $current: ' . $current->format('D d F Y') . ' - ' . $currentEnd->format('D d F Y'));
+
+ /*
+ * In the current session range?
+ */
+ if ($sessionEnd >= $current and $currentEnd >= $sessionStart) {
+ /*
+ * Lets see if we've already spent money on this recurring transaction (it hath recurred).
+ */
+ /** @var Collection $set */
+ $set = \Auth::user()->transactionjournals()->where('recurring_transaction_id', $recurring->id)
+ ->after($current)->before($currentEnd)->get();
+ if (count($set) > 1) {
+ \Log::error('Recurring #' . $recurring->id . ', dates [' . $current . ',' . $currentEnd . ']. Found multiple hits. Cannot handle this!');
+ throw new FireflyException('Cannot handle multiple transactions. See logs.');
+ } else if (count($set) == 0) {
+ $unpaid[] = $recurring;
+ } else {
+ $paid[] = $set->get(0);
+ }
+
+ }
+
+
+ /*
+ * Add some time for the next loop!
+ */
+ $toolkit->addPeriod($current, $recurring->repeat_freq, intval($recurring->skip));
+
+ }
+
+ }
+ /*
+ * Loop paid and unpaid to make two haves for a pie chart.
+ */
+ $unPaidColours = $toolkit->colorRange('AA4643', 'FFFFFF', count($unpaid) == 0 ? 1 : count($unpaid));
+ $paidColours = $toolkit->colorRange('4572A7', 'FFFFFF', count($paid) == 0 ? 1 : count($paid));
+ $serie = [
+ 'type' => 'pie',
+ 'name' => 'Amount',
+ 'data' => []
+ ];
+
+ /** @var TransactionJournal $entry */
+ foreach ($paid as $index => $entry) {
+ $transactions = $entry->transactions()->get();
+ $amount = max(floatval($transactions[0]->amount), floatval($transactions[1]->amount));
+ $serie['data'][] = [
+ 'name' => $entry->description,
+ 'y' => $amount,
+ 'color' => $paidColours[$index]
+ ];
+ }
+
+
+ /** @var RecurringTransaction $entry */
+ foreach ($unpaid as $index => $entry) {
+ $amount = (floatval($entry->amount_max) + floatval($entry->amount_min)) / 2;
+ $serie['data'][] = [
+ 'name' => $entry->name,
+ 'y' => $amount,
+ 'color' => $unPaidColours[$index]
+ ];
+ }
+
+ return Response::json([$serie]);
+
+ }
}
\ No newline at end of file
diff --git a/app/controllers/RecurringController.php b/app/controllers/RecurringController.php
index a8f8cec1e9..1fe8e051af 100644
--- a/app/controllers/RecurringController.php
+++ b/app/controllers/RecurringController.php
@@ -108,6 +108,10 @@ class RecurringController extends BaseController
*/
public function rescan(RecurringTransaction $recurringTransaction)
{
+ if (intval($recurringTransaction->active) == 0) {
+ Session::flash('warning', 'Inactive recurring transactions cannot be scanned.');
+ return Redirect::back();
+ }
// do something!
/** @var \Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface $repo */
$repo = App::make('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
@@ -117,7 +121,7 @@ class RecurringController extends BaseController
foreach ($set as $journal) {
Event::fire('recurring.rescan', [$recurringTransaction, $journal]);
}
- Session::flash('success','Rescanned everything.');
+ Session::flash('success', 'Rescanned everything.');
return Redirect::back();
diff --git a/app/database/migrations/2014_08_23_113221_create_reminders_table.php b/app/database/migrations/2014_08_23_113221_create_reminders_table.php
index 24b654a35f..12a04c3b00 100644
--- a/app/database/migrations/2014_08_23_113221_create_reminders_table.php
+++ b/app/database/migrations/2014_08_23_113221_create_reminders_table.php
@@ -27,7 +27,6 @@ class CreateRemindersTable extends Migration
'reminders', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
- $table->string('class', 40);
$table->integer('user_id')->unsigned();
$table->date('startdate');
$table->date('enddate')->nullable();
diff --git a/app/filters.php b/app/filters.php
index 9a1c96aebc..5b4cf13296 100644
--- a/app/filters.php
+++ b/app/filters.php
@@ -10,6 +10,7 @@ App::before(
$toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface');
$toolkit->getDateRange();
$toolkit->checkImportJobs();
+ Event::fire('recurring.verify');
}
}
diff --git a/app/lib/Firefly/Helper/Controllers/Json.php b/app/lib/Firefly/Helper/Controllers/Json.php
index a74a954d92..80b87286f7 100644
--- a/app/lib/Firefly/Helper/Controllers/Json.php
+++ b/app/lib/Firefly/Helper/Controllers/Json.php
@@ -355,7 +355,7 @@ class Json implements JsonInterface
* Loop set and create entries to return.
*/
foreach ($set as $entry) {
- $data['data'][] = [
+ $set = [
'name' => ['name' => $entry->name, 'url' => route('recurring.show', $entry->id)],
'match' => explode(' ', $entry->match),
@@ -370,6 +370,11 @@ class Json implements JsonInterface
'delete' => route('recurring.delete', $entry->id)
]
];
+ if (intval($entry->skip) > 0) {
+ $set['repeat_freq'] = $entry->repeat_freq . ' (skip ' . $entry->skip . ')';
+ }
+ $data['data'][] = $set;
+
}
return $data;
diff --git a/app/lib/Firefly/Helper/Toolkit/Toolkit.php b/app/lib/Firefly/Helper/Toolkit/Toolkit.php
index 0266c01728..51941a2508 100644
--- a/app/lib/Firefly/Helper/Toolkit/Toolkit.php
+++ b/app/lib/Firefly/Helper/Toolkit/Toolkit.php
@@ -381,4 +381,127 @@ class Toolkit implements ToolkitInterface
}
return $selectList;
}
+
+ /**
+ * @param string $start
+ * @param string $end
+ * @param int $steps
+ */
+ public function colorRange($start, $end, $steps = 5)
+ {
+ if (strlen($start) != 6) {
+ throw new FireflyException('Start, ' . e($start) . ' should be a six character HTML colour.');
+ }
+ if (strlen($end) != 6) {
+ throw new FireflyException('End, ' . e($end) . ' should be a six character HTML colour.');
+ }
+ if ($steps < 1) {
+ throw new FireflyException('Steps must be > 1');
+ }
+
+ $start = '#' . $start;
+ $end = '#' . $end;
+ /*
+ * Split html colours.
+ */
+ list($rs, $gs, $bs) = sscanf($start, "#%02x%02x%02x");
+ list($re, $ge, $be) = sscanf($end, "#%02x%02x%02x");
+
+ $stepr = ($re - $rs) / $steps;
+ $stepg = ($ge - $gs) / $steps;
+ $stepb = ($be - $bs) / $steps;
+
+ $return = [];
+ for ($i = 0; $i <= $steps; $i++) {
+ $cr = $rs + ($stepr * $i);
+ $cg = $gs + ($stepg * $i);
+ $cb = $bs + ($stepb * $i);
+
+ $return[] = $this->rgb2html($cr, $cg, $cb);
+ }
+
+ return $return;
+ }
+
+ protected function rgb2html($r, $g = -1, $b = -1)
+ {
+ $r = dechex($r < 0 ? 0 : ($r > 255 ? 255 : $r));
+ $g = dechex($g < 0 ? 0 : ($g > 255 ? 255 : $g));
+ $b = dechex($b < 0 ? 0 : ($b > 255 ? 255 : $b));
+
+ $color = (strlen($r) < 2 ? '0' : '') . $r;
+ $color .= (strlen($g) < 2 ? '0' : '') . $g;
+ $color .= (strlen($b) < 2 ? '0' : '') . $b;
+ return '#' . $color;
+ }
+
+ /**
+ * @param Carbon $currentEnd
+ * @param $repeatFreq
+ * @throws FireflyException
+ */
+ public function endOfPeriod(Carbon $currentEnd, $repeatFreq)
+ {
+ switch ($repeatFreq) {
+ default:
+ throw new FireflyException('Cannot do getFunctionForRepeatFreq for $repeat_freq ' . $repeatFreq);
+ break;
+ case 'daily':
+ $currentEnd->addDay();
+ break;
+ case 'weekly':
+ $currentEnd->addWeek()->subDay();
+ break;
+ case 'monthly':
+ $currentEnd->addMonth()->subDay();
+ break;
+ case 'quarterly':
+ $currentEnd->addMonths(3)->subDay();
+ break;
+ case 'half-year':
+ $currentEnd->addMonths(6)->subDay();
+ break;
+ case 'yearly':
+ $currentEnd->addYear()->subDay();
+ break;
+ }
+ }
+
+ /**
+ * @param Carbon $date
+ * @param $repeatFreq
+ * @param $skip
+ * @return Carbon
+ * @throws FireflyException
+ */
+ public function addPeriod(Carbon $date, $repeatFreq, $skip)
+ {
+ $add = ($skip + 1);
+ switch ($repeatFreq) {
+ default:
+ throw new FireflyException('Cannot do getFunctionForRepeatFreq for $repeat_freq ' . $repeatFreq);
+ break;
+ case 'daily':
+ $date->addDays($add);
+ break;
+ case 'weekly':
+ $date->addWeeks($add);
+ break;
+ case 'monthly':
+ $date->addMonths($add);
+ break;
+ case 'quarterly':
+ $months = $add * 3;
+ $date->addMonths($months);
+ break;
+ case 'half-year':
+ $months = $add * 6;
+ $date->addMonths($months);
+ break;
+ case 'yearly':
+ $date->addYears($add);
+ break;
+ }
+ return $date;
+ }
}
\ No newline at end of file
diff --git a/app/lib/Firefly/Helper/Toolkit/ToolkitInterface.php b/app/lib/Firefly/Helper/Toolkit/ToolkitInterface.php
index 3fd58a6b7d..3c09e686c2 100644
--- a/app/lib/Firefly/Helper/Toolkit/ToolkitInterface.php
+++ b/app/lib/Firefly/Helper/Toolkit/ToolkitInterface.php
@@ -21,7 +21,7 @@ interface 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
*/
@@ -33,4 +33,11 @@ interface ToolkitInterface
public function checkImportJobs();
+ /**
+ * @param string $start
+ * @param string $end
+ * @param int $steps
+ */
+ public function colorRange($start, $end, $steps = 5);
+
}
\ No newline at end of file
diff --git a/app/lib/Firefly/Trigger/Recurring/EloquentRecurringTrigger.php b/app/lib/Firefly/Trigger/Recurring/EloquentRecurringTrigger.php
index c8f1403e53..e8649214a1 100644
--- a/app/lib/Firefly/Trigger/Recurring/EloquentRecurringTrigger.php
+++ b/app/lib/Firefly/Trigger/Recurring/EloquentRecurringTrigger.php
@@ -3,6 +3,7 @@
namespace Firefly\Trigger\Recurring;
use Carbon\Carbon;
+use Firefly\Exception\FireflyException;
use Illuminate\Events\Dispatcher;
/**
@@ -81,11 +82,7 @@ class EloquentRecurringTrigger
*/
public function subscribe(Dispatcher $events)
{
- //Event::fire('recurring.rematch', [$recurringTransaction, $journal]);
$events->listen('recurring.rescan', 'Firefly\Trigger\Recurring\EloquentRecurringTrigger@rescan');
-// $events->listen('recurring.destroy', 'Firefly\Trigger\Recurring\EloquentRecurringTrigger@destroy');
-// $events->listen('recurring.store', 'Firefly\Trigger\Recurring\EloquentRecurringTrigger@store');
-// $events->listen('recurring.update', 'Firefly\Trigger\Recurring\EloquentRecurringTrigger@update');
}
/**
diff --git a/app/models/Reminder.php b/app/models/Reminder.php
index d720bb3fec..ad18a86c40 100644
--- a/app/models/Reminder.php
+++ b/app/models/Reminder.php
@@ -2,6 +2,8 @@
use Carbon\Carbon;
use Firefly\Database\SingleTableInheritanceEntity;
+use LaravelBook\Ardent\Ardent;
+
/**
* Reminder
@@ -10,33 +12,24 @@ use Firefly\Database\SingleTableInheritanceEntity;
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $class
- * @property integer $piggybank_id
- * @property integer $recurring_transaction_id
* @property integer $user_id
* @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $enddate
* @property boolean $active
- * @property-read \Piggybank $piggybank
- * @property-read \RecurringTransaction $recurringTransaction
* @property-read \User $user
- * @method static \Illuminate\Database\Query\Builder|\Reminder whereId($value)
- * @method static \Illuminate\Database\Query\Builder|\Reminder whereCreatedAt($value)
- * @method static \Illuminate\Database\Query\Builder|\Reminder whereUpdatedAt($value)
- * @method static \Illuminate\Database\Query\Builder|\Reminder whereClass($value)
- * @method static \Illuminate\Database\Query\Builder|\Reminder wherePiggybankId($value)
- * @method static \Illuminate\Database\Query\Builder|\Reminder whereRecurringTransactionId($value)
- * @method static \Illuminate\Database\Query\Builder|\Reminder whereUserId($value)
- * @method static \Illuminate\Database\Query\Builder|\Reminder whereStartdate($value)
- * @method static \Illuminate\Database\Query\Builder|\Reminder whereEnddate($value)
- * @method static \Illuminate\Database\Query\Builder|\Reminder whereActive($value)
- * @method static \Reminder validOn($date)
- * @method static \Reminder validOnOrAfter($date)
+ * @method static \Illuminate\Database\Query\Builder|\Reminder whereId($value)
+ * @method static \Illuminate\Database\Query\Builder|\Reminder whereCreatedAt($value)
+ * @method static \Illuminate\Database\Query\Builder|\Reminder whereUpdatedAt($value)
+ * @method static \Illuminate\Database\Query\Builder|\Reminder whereClass($value)
+ * @method static \Illuminate\Database\Query\Builder|\Reminder whereUserId($value)
+ * @method static \Illuminate\Database\Query\Builder|\Reminder whereStartdate($value)
+ * @method static \Illuminate\Database\Query\Builder|\Reminder whereEnddate($value)
+ * @method static \Illuminate\Database\Query\Builder|\Reminder whereActive($value)
*/
-class Reminder extends SingleTableInheritanceEntity
+class Reminder extends Ardent
{
protected $table = 'reminders';
- protected $subclassField = 'class';
/**
@@ -47,49 +40,6 @@ class Reminder extends SingleTableInheritanceEntity
return ['created_at', 'updated_at', 'startdate', 'enddate'];
}
- /**
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function piggybank()
- {
- return $this->belongsTo('Piggybank');
- }
-
- public function recurringTransaction()
- {
- return $this->belongsTo('RecurringTransaction');
- }
-
- public function render()
- {
- return '';
-
-
- }
-
- public function scopeValidOn($query, Carbon $date)
- {
- return $query->where('startdate', '<=', $date->format('Y-m-d'))->where('enddate', '>=', $date->format('Y-m-d'))
- ->where('active', 1);
- }
-
- public function scopeValidOnOrAfter($query, Carbon $date)
- {
- return $query->where(
- function ($q) use ($date) {
- $q->where('startdate', '<=', $date->format('Y-m-d'))->where(
- 'enddate', '>=', $date->format('Y-m-d')
- );
- $q->orWhere(
- function ($q) use ($date) {
- $q->where('startdate', '>=', $date);
- $q->where('enddate', '>=', $date);
- }
- );
- }
- )->where('active', 1);
- }
-
/**
* User
*
diff --git a/app/models/TransactionJournal.php b/app/models/TransactionJournal.php
index 432ee0aa7f..41c8f79805 100644
--- a/app/models/TransactionJournal.php
+++ b/app/models/TransactionJournal.php
@@ -223,6 +223,22 @@ use LaravelBook\Ardent\Builder;
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
+ * @property-read \Illuminate\Database\Eloquent\Collection|\
+ * 'Budget[] $budgets
+ * @property-read \Illuminate\Database\Eloquent\Collection|\
+ * 'Category[] $categories
+ * @property-read \Illuminate\Database\Eloquent\Collection|\
+ * 'Budget[] $budgets
+ * @property-read \Illuminate\Database\Eloquent\Collection|\
+ * 'Category[] $categories
+ * @property-read \Illuminate\Database\Eloquent\Collection|\
+ * 'Budget[] $budgets
+ * @property-read \Illuminate\Database\Eloquent\Collection|\
+ * 'Category[] $categories
+ * @property-read \Illuminate\Database\Eloquent\Collection|\
+ * 'Budget[] $budgets
+ * @property-read \Illuminate\Database\Eloquent\Collection|\
+ * 'Category[] $categories
*/
class TransactionJournal extends Ardent
{
diff --git a/app/routes.php b/app/routes.php
index df3cfeced2..535b161678 100644
--- a/app/routes.php
+++ b/app/routes.php
@@ -170,6 +170,7 @@ Route::group(['before' => 'auth'], function () {
Route::get('/chart/home/budgets', ['uses' => 'ChartController@homeBudgets', 'as' => 'chart.budgets']);
Route::get('/chart/home/info/{accountnameA}/{day}/{month}/{year}', ['uses' => 'ChartController@homeAccountInfo', 'as' => 'chart.info']);
Route::get('/chart/categories/show/{category}', ['uses' => 'ChartController@categoryShowChart','as' => 'chart.showcategory']);
+ Route::get('/chart/home/recurring', ['uses' => 'ChartController@homeRecurring', 'as' => 'chart.recurring']);
// (new charts for budgets)
Route::get('/chart/budget/{budget}/default', ['uses' => 'ChartController@budgetDefault', 'as' => 'chart.budget.default']);
Route::get('chart/budget/{budget}/no_envelope', ['uses' => 'ChartController@budgetNoLimits', 'as' => 'chart.budget.nolimit']);
diff --git a/app/views/index.blade.php b/app/views/index.blade.php
index 353d5d703b..c9137158cc 100644
--- a/app/views/index.blade.php
+++ b/app/views/index.blade.php
@@ -20,7 +20,7 @@
-
+
Use this option if you are new to Firefly (III).
@@ -29,9 +29,10 @@
@else
-
+
+
+
+
+
+
+ Savings
+
+
+ Bla bla
+
+
@@ -65,6 +75,16 @@
@include('partials.date_nav')
+
+
+
+ Recurring transactions
+
+
+
+
@foreach($transactions as $data)
diff --git a/public/assets/javascript/firefly/index.js b/public/assets/javascript/firefly/index.js
index 26e245a0e9..8d34f0a355 100644
--- a/public/assets/javascript/firefly/index.js
+++ b/public/assets/javascript/firefly/index.js
@@ -17,7 +17,7 @@ $(function () {
allowDecimals: false,
labels: {
formatter: function () {
- if(this.value >= 1000 || this.value <= -1000) {
+ if (this.value >= 1000 || this.value <= -1000) {
return '\u20AC ' + (this.value / 1000) + 'k';
}
return '\u20AC ' + this.value;
@@ -36,10 +36,10 @@ $(function () {
text: null
}
},
- legend: {enabled:false},
+ legend: {enabled: false},
tooltip: {
formatter: function () {
- return this.series.name + ': \u20AC ' + Highcharts.numberFormat(this.y,2);
+ return this.series.name + ': \u20AC ' + Highcharts.numberFormat(this.y, 2);
}
},
plotOptions: {
@@ -101,7 +101,7 @@ $(function () {
},
labels: {
formatter: function () {
- if(this.value >= 1000 || this.value <= -1000) {
+ if (this.value >= 1000 || this.value <= -1000) {
return '\u20AC ' + (this.value / 1000) + 'k';
}
return '\u20AC ' + this.value;
@@ -165,17 +165,17 @@ $(function () {
},
tooltip: {
formatter: function () {
- return this.series.name + ': \u20AC ' + Highcharts.numberFormat(this.y,2);
+ return this.series.name + ': \u20AC ' + Highcharts.numberFormat(this.y, 2);
}
},
yAxis: {
min: 0,
- title: {text:null},
+ title: {text: null},
labels: {
overflow: 'justify',
formatter: function () {
- if(this.value >= 1000 || this.value <= -1000) {
+ if (this.value >= 1000 || this.value <= -1000) {
return '\u20AC ' + (this.value / 1000) + 'k';
}
return '\u20AC ' + this.value;
@@ -188,7 +188,7 @@ $(function () {
cursor: 'pointer',
events: {
click: function (e) {
- if(e.point.url != null) {
+ if (e.point.url != null) {
window.location = e.point.url;
}
}
@@ -202,7 +202,7 @@ $(function () {
}
},
legend: {
- enabled: false,
+ enabled: false
},
credits: {
enabled: false
@@ -211,5 +211,25 @@ $(function () {
});
});
+ $.getJSON('chart/home/recurring').success(function (data) {
+ $('#recurring').highcharts({
+ title: {
+ text: null
+ },
+ credits: {
+ enabled: false
+ },
+ plotOptions: {
+ pie: {
+ allowPointSelect: true,
+ cursor: 'pointer',
+ dataLabels: {
+ enabled: false
+ }
+ }
+ },
+ series: data
+ });
+ });
});
\ No newline at end of file