mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-25 21:16:47 +00:00
First effort towards nice charts in the budgeting overviews.
This commit is contained in:
14
app/assets/javascripts/budgets.js
Normal file
14
app/assets/javascripts/budgets.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
||||||
|
// listed below.
|
||||||
|
//
|
||||||
|
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
||||||
|
// can be referenced here using a relative path.
|
||||||
|
//
|
||||||
|
// It's not advisable to add code directly here, but if you do, it'll appear in whatever order it
|
||||||
|
// gets included (e.g. say you have require_tree . then the code will appear after all the directories
|
||||||
|
// but before any files alphabetically greater than 'application.js'
|
||||||
|
//
|
||||||
|
// The available directives right now are require, require_directory, and require_tree
|
||||||
|
//
|
||||||
|
//= require_tree highcharts
|
||||||
|
//= require firefly/budgets
|
||||||
@@ -7,7 +7,7 @@ if($('#chart').length == 1) {
|
|||||||
var options = {
|
var options = {
|
||||||
chart: {
|
chart: {
|
||||||
renderTo: 'chart',
|
renderTo: 'chart',
|
||||||
type: 'line'
|
type: 'spline'
|
||||||
},
|
},
|
||||||
|
|
||||||
series: data.series,
|
series: data.series,
|
||||||
|
|||||||
93
app/assets/javascripts/firefly/budgets.js
Normal file
93
app/assets/javascripts/firefly/budgets.js
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
$(function () {
|
||||||
|
if ($('#chart').length == 1) {
|
||||||
|
chartType = $('#instr').data('type');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(chartType == 'envelope') {
|
||||||
|
var envelopeId = $('#instr').data('envelope');
|
||||||
|
var URL = 'chart/budget/envelope/' + envelopeId;
|
||||||
|
}
|
||||||
|
if(chartType == 'no_envelope') {
|
||||||
|
var budgetId = $('#instr').data('budget');
|
||||||
|
var URL = 'chart/budget/'+budgetId+'/no_envelope';
|
||||||
|
}
|
||||||
|
if(chartType == 'session') {
|
||||||
|
var budgetId = $('#instr').data('budget');
|
||||||
|
var URL = 'chart/budget/'+budgetId+'/session';
|
||||||
|
}
|
||||||
|
if(chartType == 'default') {
|
||||||
|
var budgetId = $('#instr').data('budget');
|
||||||
|
var URL = 'chart/budget/'+budgetId+'/default';
|
||||||
|
}
|
||||||
|
|
||||||
|
// go do something with this URL.
|
||||||
|
$.getJSON(URL).success(function (data) {
|
||||||
|
var options = {
|
||||||
|
chart: {
|
||||||
|
renderTo: 'chart',
|
||||||
|
},
|
||||||
|
|
||||||
|
series: data.series,
|
||||||
|
title: {
|
||||||
|
text: data.chart_title
|
||||||
|
},
|
||||||
|
yAxis: [{ // Primary yAxis
|
||||||
|
labels: {
|
||||||
|
format: '€ {value}',
|
||||||
|
style: {
|
||||||
|
color: Highcharts.getOptions().colors[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, { // Secondary yAxis
|
||||||
|
title: {
|
||||||
|
style: {
|
||||||
|
color: Highcharts.getOptions().colors[0]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
opposite: true
|
||||||
|
}],
|
||||||
|
subtitle: {
|
||||||
|
text: data.subtitle,
|
||||||
|
useHTML: true
|
||||||
|
},
|
||||||
|
|
||||||
|
xAxis: {
|
||||||
|
floor: 0,
|
||||||
|
type: 'datetime',
|
||||||
|
dateTimeLabelFormats: {
|
||||||
|
day: '%e %b',
|
||||||
|
year: '%b'
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
text: 'Date'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plotOptions: {
|
||||||
|
line: {
|
||||||
|
shadow: true
|
||||||
|
},
|
||||||
|
series: {
|
||||||
|
cursor: 'pointer',
|
||||||
|
negativeColor: '#FF0000',
|
||||||
|
threshold: 0,
|
||||||
|
lineWidth: 1,
|
||||||
|
marker: {
|
||||||
|
radius: 2
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
credits: {
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$('#chart').highcharts(options);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
@@ -24,6 +24,289 @@ class ChartController extends BaseController
|
|||||||
$this->_accounts = $accounts;
|
$this->_accounts = $accounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function budgetDefault(\Budget $budget)
|
||||||
|
{
|
||||||
|
$expense = [];
|
||||||
|
$left = [];
|
||||||
|
// get all limit repetitions for this budget.
|
||||||
|
/** @var \Limit $limit */
|
||||||
|
foreach ($budget->limits as $limit) {
|
||||||
|
/** @var \LimitRepetition $rep */
|
||||||
|
foreach ($limit->limitrepetitions as $rep) {
|
||||||
|
$spentInRep = \Transaction::
|
||||||
|
leftJoin(
|
||||||
|
'transaction_journals', 'transaction_journals.id', '=',
|
||||||
|
'transactions.transaction_journal_id'
|
||||||
|
)
|
||||||
|
->leftJoin(
|
||||||
|
'component_transaction_journal', 'component_transaction_journal.transaction_journal_id',
|
||||||
|
'=',
|
||||||
|
'transaction_journals.id'
|
||||||
|
)->where('component_transaction_journal.component_id', '=', $budget->id)->where(
|
||||||
|
'transaction_journals.date', '>=', $rep->startdate->format('Y-m-d')
|
||||||
|
)->where('transaction_journals.date', '<=', $rep->enddate->format('Y-m-d'))->where(
|
||||||
|
'amount', '>', 0
|
||||||
|
)->sum('amount');
|
||||||
|
|
||||||
|
|
||||||
|
$pct = round(($spentInRep / $limit->amount) * 100,2);
|
||||||
|
$expense[] = [$rep->startdate->timestamp * 1000, floatval($spentInRep)];
|
||||||
|
$left[] = [$rep->startdate->timestamp * 1000, $pct];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$return = [
|
||||||
|
'chart_title' => 'Overview for budget ' . $budget->name,
|
||||||
|
'subtitle' => 'Between something something',
|
||||||
|
'series' => [
|
||||||
|
[
|
||||||
|
'type' => 'column',
|
||||||
|
'name' => 'Expenses in envelope',
|
||||||
|
'data' => $expense
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'type' => 'line',
|
||||||
|
'yAxis' => 1,
|
||||||
|
'name' => 'Spent pct for envelope',
|
||||||
|
'data' => $left
|
||||||
|
]
|
||||||
|
|
||||||
|
]
|
||||||
|
];
|
||||||
|
return Response::json($return);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param LimitRepetition $rep
|
||||||
|
*/
|
||||||
|
public function budgetLimit(\LimitRepetition $rep)
|
||||||
|
{
|
||||||
|
$budget = $rep->limit->budget;
|
||||||
|
$current = clone $rep->startdate;
|
||||||
|
$expense = [];
|
||||||
|
$leftInLimit = [];
|
||||||
|
$currentLeftInLimit = floatval($rep->limit->amount);
|
||||||
|
while ($current <= $rep->enddate) {
|
||||||
|
$spent = \Transaction::
|
||||||
|
leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
|
->leftJoin(
|
||||||
|
'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=',
|
||||||
|
'transaction_journals.id'
|
||||||
|
)->where('component_transaction_journal.component_id', '=', $budget->id)->where(
|
||||||
|
'transaction_journals.date', $current->format('Y-m-d')
|
||||||
|
)->where('amount', '>', 0)->sum('amount');
|
||||||
|
$spent = floatval($spent) == 0 ? null : floatval($spent);
|
||||||
|
$entry = [$current->timestamp * 1000, $spent];
|
||||||
|
$expense[] = $entry;
|
||||||
|
$currentLeftInLimit = $currentLeftInLimit - $spent;
|
||||||
|
$leftInLimit[] = [$current->timestamp * 1000, $currentLeftInLimit];
|
||||||
|
$current->addDay();
|
||||||
|
}
|
||||||
|
|
||||||
|
$return = [
|
||||||
|
'chart_title' => 'Overview for budget ' . $budget->name,
|
||||||
|
'subtitle' => 'Between ' . $rep->startdate->format('d M Y') . ' and ' . $rep->startdate->format('d M Y'),
|
||||||
|
'series' => [
|
||||||
|
[
|
||||||
|
'type' => 'column',
|
||||||
|
'name' => 'Expenses per day',
|
||||||
|
'yAxis' => 1,
|
||||||
|
'data' => $expense
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'type' => 'line',
|
||||||
|
'name' => 'Left in envelope',
|
||||||
|
'data' => $leftInLimit
|
||||||
|
]
|
||||||
|
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
return Response::json($return);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function budgetNoLimits(\Budget $budget)
|
||||||
|
{
|
||||||
|
$inRepetitions = [];
|
||||||
|
foreach ($budget->limits as $limit) {
|
||||||
|
foreach ($limit->limitrepetitions as $repetition) {
|
||||||
|
$set = $budget->transactionjournals()->leftJoin(
|
||||||
|
'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
|
||||||
|
)->where('transaction_types.type', 'Withdrawal')->where(
|
||||||
|
'date', '>=', $repetition->startdate->format('Y-m-d')
|
||||||
|
)->where('date', '<=', $repetition->enddate->format('Y-m-d'))->orderBy('date', 'DESC')->get(
|
||||||
|
['transaction_journals.id']
|
||||||
|
);
|
||||||
|
foreach ($set as $item) {
|
||||||
|
$inRepetitions[] = $item->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = $budget->transactionjournals()->whereNotIn(
|
||||||
|
'transaction_journals.id', $inRepetitions
|
||||||
|
)->orderBy('date', 'DESC')->orderBy(
|
||||||
|
'transaction_journals.id', 'DESC'
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
$result = $query->get(['transaction_journals.id']);
|
||||||
|
$set = [];
|
||||||
|
foreach ($result as $entry) {
|
||||||
|
$set[] = $entry->id;
|
||||||
|
}
|
||||||
|
// all transactions for these journals, grouped by date and SUM
|
||||||
|
$transactions = \Transaction::whereIn('transaction_journal_id', $set)->leftJoin(
|
||||||
|
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
|
||||||
|
)
|
||||||
|
->groupBy('transaction_journals.date')->where('amount', '>', 0)->get(
|
||||||
|
['transaction_journals.date', DB::Raw('SUM(`amount`) as `aggregate`')]
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// this set builds the chart:
|
||||||
|
$expense = [];
|
||||||
|
|
||||||
|
foreach ($transactions as $t) {
|
||||||
|
$date = new Carbon($t->date);
|
||||||
|
$expense[] = [$date->timestamp * 1000, floatval($t->aggregate)];
|
||||||
|
}
|
||||||
|
$return = [
|
||||||
|
'chart_title' => 'Overview for ' . $budget->name,
|
||||||
|
'subtitle' => 'Not organized by an envelope',
|
||||||
|
'series' => [
|
||||||
|
[
|
||||||
|
'type' => 'spline',
|
||||||
|
'name' => 'Expenses per day',
|
||||||
|
'data' => $expense
|
||||||
|
]
|
||||||
|
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
return Response::json($return);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function budgetSession(\Budget $budget)
|
||||||
|
{
|
||||||
|
$expense = [];
|
||||||
|
$repetitionSeries = [];
|
||||||
|
$current = clone Session::get('start');
|
||||||
|
$end = clone Session::get('end');
|
||||||
|
while ($current <= $end) {
|
||||||
|
$spent = \Transaction::
|
||||||
|
leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||||
|
->leftJoin(
|
||||||
|
'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=',
|
||||||
|
'transaction_journals.id'
|
||||||
|
)->where('component_transaction_journal.component_id', '=', $budget->id)->where(
|
||||||
|
'transaction_journals.date', $current->format('Y-m-d')
|
||||||
|
)->where('amount', '>', 0)->sum('amount');
|
||||||
|
$spent = floatval($spent) == 0 ? null : floatval($spent);
|
||||||
|
if (!is_null($spent)) {
|
||||||
|
$expense[] = [$current->timestamp * 1000, $spent];
|
||||||
|
}
|
||||||
|
|
||||||
|
$current->addDay();
|
||||||
|
}
|
||||||
|
|
||||||
|
// find all limit repetitions (for this budget) between start and end.
|
||||||
|
$start = clone Session::get('start');
|
||||||
|
$repetitionSeries[] = [
|
||||||
|
'type' => 'column',
|
||||||
|
'name' => 'Something something expenses',
|
||||||
|
'data' => $expense
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/** @var \Limit $limit */
|
||||||
|
foreach ($budget->limits as $limit) {
|
||||||
|
$reps = $limit->limitrepetitions()->where(
|
||||||
|
function ($q) use ($start, $end) {
|
||||||
|
// startdate is between range
|
||||||
|
$q->where(
|
||||||
|
function ($q) use ($start, $end) {
|
||||||
|
$q->where('startdate', '>=', $start->format('Y-m-d'));
|
||||||
|
$q->where('startdate', '<=', $end->format('Y-m-d'));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// or enddate is between range.
|
||||||
|
$q->orWhere(
|
||||||
|
function ($q) use ($start, $end) {
|
||||||
|
$q->where('enddate', '>=', $start->format('Y-m-d'));
|
||||||
|
$q->where('enddate', '<=', $end->format('Y-m-d'));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
->get();
|
||||||
|
$currentLeftInLimit = floatval($limit->amount);
|
||||||
|
/** @var \LimitRepetition $repetition */
|
||||||
|
foreach ($reps as $repetition) {
|
||||||
|
// create a serie for the repetition.
|
||||||
|
$currentSerie = [
|
||||||
|
'type' => 'spline',
|
||||||
|
'id' => 'rep-' . $repetition->id,
|
||||||
|
'yAxis' => 1,
|
||||||
|
'name' => 'Serie ' . $repetition->startdate->format('Y-m-d') . ' to ' .
|
||||||
|
$repetition->enddate->format('Y-m-d') . '.',
|
||||||
|
'data' => []
|
||||||
|
];
|
||||||
|
$current = clone $repetition->startdate;
|
||||||
|
while ($current <= $repetition->enddate) {
|
||||||
|
if ($current >= Session::get('start') && $current <= Session::get('end')) {
|
||||||
|
// spent on limit:
|
||||||
|
$spentSoFar = \Transaction::
|
||||||
|
leftJoin(
|
||||||
|
'transaction_journals', 'transaction_journals.id', '=',
|
||||||
|
'transactions.transaction_journal_id'
|
||||||
|
)
|
||||||
|
->leftJoin(
|
||||||
|
'component_transaction_journal', 'component_transaction_journal.transaction_journal_id',
|
||||||
|
'=',
|
||||||
|
'transaction_journals.id'
|
||||||
|
)->where('component_transaction_journal.component_id', '=', $budget->id)->where(
|
||||||
|
'transaction_journals.date', '>=', $repetition->startdate->format('Y-m-d')
|
||||||
|
)->where('transaction_journals.date', '<=', $current->format('Y-m-d'))->where(
|
||||||
|
'amount', '>', 0
|
||||||
|
)->sum('amount');
|
||||||
|
$spent = floatval($spent) == 0 ? null : floatval($spent);
|
||||||
|
$currentLeftInLimit = floatval($limit->amount) - floatval($spentSoFar);
|
||||||
|
|
||||||
|
$currentSerie['data'][] = [$current->timestamp * 1000, $currentLeftInLimit];
|
||||||
|
}
|
||||||
|
$current->addDay();
|
||||||
|
}
|
||||||
|
|
||||||
|
// do something here.
|
||||||
|
$repetitionSeries[] = $currentSerie;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$return = [
|
||||||
|
'chart_title' => 'Overview for budget ' . $budget->name,
|
||||||
|
'subtitle' => 'Between Bla bla bla',
|
||||||
|
'series' => $repetitionSeries
|
||||||
|
];
|
||||||
|
|
||||||
|
return Response::json($return);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Category $category
|
* @param Category $category
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,40 +1,41 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use LaravelBook\Ardent\Ardent;
|
use LaravelBook\Ardent\Ardent;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TransactionJournal
|
* TransactionJournal
|
||||||
*
|
*
|
||||||
* @property integer $id
|
* @property integer $id
|
||||||
* @property \Carbon\Carbon $created_at
|
* @property Carbon $created_at
|
||||||
* @property \Carbon\Carbon $updated_at
|
* @property Carbon $updated_at
|
||||||
* @property integer $user_id
|
* @property integer $user_id
|
||||||
* @property integer $transaction_type_id
|
* @property integer $transaction_type_id
|
||||||
* @property integer $transaction_currency_id
|
* @property integer $transaction_currency_id
|
||||||
* @property string $description
|
* @property string $description
|
||||||
* @property boolean $completed
|
* @property boolean $completed
|
||||||
* @property \Carbon\Carbon $date
|
* @property Carbon $date
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\
|
* @property-read \Illuminate\Database\Eloquent\Collection|\
|
||||||
* 'Budget[] $budgets
|
* 'Budget[] $budgets
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\
|
* @property-read \Illuminate\Database\Eloquent\Collection|\
|
||||||
* 'Category[] $categories
|
* 'Category[] $categories
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components
|
* @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components
|
||||||
* @property-read \TransactionCurrency $transactionCurrency
|
* @property-read \TransactionCurrency $transactionCurrency
|
||||||
* @property-read \TransactionType $transactionType
|
* @property-read \TransactionType $transactionType
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
|
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
|
||||||
* @property-read \User $user
|
* @property-read \User $user
|
||||||
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereId($value)
|
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereId($value)
|
||||||
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereCreatedAt($value)
|
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereCreatedAt($value)
|
||||||
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereUpdatedAt($value)
|
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereUpdatedAt($value)
|
||||||
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereUserId($value)
|
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereUserId($value)
|
||||||
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereTransactionTypeId($value)
|
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereTransactionTypeId($value)
|
||||||
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereTransactionCurrencyId($value)
|
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereTransactionCurrencyId($value)
|
||||||
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereDescription($value)
|
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereDescription($value)
|
||||||
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereCompleted($value)
|
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereCompleted($value)
|
||||||
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereDate($value)
|
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereDate($value)
|
||||||
* @method static \TransactionJournal after($date)
|
* @method static \TransactionJournal after($date)
|
||||||
* @method static \TransactionJournal before($date)
|
* @method static \TransactionJournal before($date)
|
||||||
*/
|
*/
|
||||||
class TransactionJournal extends Ardent
|
class TransactionJournal extends Ardent
|
||||||
{
|
{
|
||||||
@@ -87,26 +88,37 @@ class TransactionJournal extends Ardent
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $query
|
* @param $query
|
||||||
* @param \Carbon\Carbon $date
|
* @param Carbon $date
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function scopeAfter($query, \Carbon\Carbon $date)
|
public function scopeAfter($query, Carbon $date)
|
||||||
{
|
{
|
||||||
return $query->where('date', '>=', $date->format('Y-m-d'));
|
return $query->where('date', '>=', $date->format('Y-m-d'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $query
|
* @param $query
|
||||||
* @param \Carbon\Carbon $date
|
* @param Carbon $date
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function scopeBefore($query, \Carbon\Carbon $date)
|
public function scopeBefore($query, Carbon $date)
|
||||||
{
|
{
|
||||||
return $query->where('date', '<=', $date->format('Y-m-d'));
|
return $query->where('date', '<=', $date->format('Y-m-d'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $query
|
||||||
|
* @param Carbon $date
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function scopeOnDate($query, Carbon $date)
|
||||||
|
{
|
||||||
|
return $query->where('date', '=', $date->format('Y-m-d'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -75,6 +75,19 @@ Route::bind('limit', function($value, $route)
|
|||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::bind('limitrepetition', function($value, $route)
|
||||||
|
{
|
||||||
|
if(Auth::check()) {
|
||||||
|
return LimitRepetition::
|
||||||
|
where('limit_repetitions.id', $value)->
|
||||||
|
leftjoin('limits','limits.id','=','limit_repetitions.limit_id')->
|
||||||
|
leftJoin('components','components.id','=','limits.component_id')->
|
||||||
|
where('components.class','Budget')->
|
||||||
|
where('components.user_id',Auth::user()->id)->first(['limit_repetitions.*']);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
Route::bind('piggybank', function($value, $route)
|
Route::bind('piggybank', function($value, $route)
|
||||||
{
|
{
|
||||||
if(Auth::check()) {
|
if(Auth::check()) {
|
||||||
@@ -116,9 +129,15 @@ Route::group(['before' => 'auth'], function () {
|
|||||||
Route::get('/chart/home/account/{account?}', ['uses' => 'ChartController@homeAccount', 'as' => 'chart.home']);
|
Route::get('/chart/home/account/{account?}', ['uses' => 'ChartController@homeAccount', 'as' => 'chart.home']);
|
||||||
Route::get('/chart/home/categories', ['uses' => 'ChartController@homeCategories', 'as' => 'chart.categories']);
|
Route::get('/chart/home/categories', ['uses' => 'ChartController@homeCategories', 'as' => 'chart.categories']);
|
||||||
Route::get('/chart/home/budgets', ['uses' => 'ChartController@homeBudgets', 'as' => 'chart.budgets']);
|
Route::get('/chart/home/budgets', ['uses' => 'ChartController@homeBudgets', 'as' => 'chart.budgets']);
|
||||||
Route::get('/chart/home/info/{accountnameA}/{day}/{month}/{year}',
|
Route::get('/chart/home/info/{accountnameA}/{day}/{month}/{year}', ['uses' => 'ChartController@homeAccountInfo', 'as' => 'chart.info']);
|
||||||
['uses' => 'ChartController@homeAccountInfo', 'as' => 'chart.info']);
|
|
||||||
Route::get('/chart/categories/show/{category}', ['uses' => 'ChartController@categoryShowChart','as' => 'chart.showcategory']);
|
Route::get('/chart/categories/show/{category}', ['uses' => 'ChartController@categoryShowChart','as' => 'chart.showcategory']);
|
||||||
|
// (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']);
|
||||||
|
Route::get('chart/budget/{budget}/session', ['uses' => 'ChartController@budgetSession', 'as' => 'chart.budget.session']);
|
||||||
|
Route::get('chart/budget/envelope/{limitrepetition}', ['uses' => 'ChartController@budgetLimit', 'as' => 'chart.budget.limit']);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// home controller
|
// home controller
|
||||||
Route::get('/', ['uses' => 'HomeController@index', 'as' => 'index']);
|
Route::get('/', ['uses' => 'HomeController@index', 'as' => 'index']);
|
||||||
|
|||||||
@@ -9,11 +9,12 @@
|
|||||||
<!-- warning for selected limit -->
|
<!-- warning for selected limit -->
|
||||||
@if(isset($filters[0]) && is_object($filters[0]) && get_class($filters[0]) == 'Limit')
|
@if(isset($filters[0]) && is_object($filters[0]) && get_class($filters[0]) == 'Limit')
|
||||||
<p class="bg-primary" style="padding:15px;">
|
<p class="bg-primary" style="padding:15px;">
|
||||||
This view is filtered to show only the envelope from {{{$repetitions[0]['limitrepetition']->periodShow()}}}
|
This view is filtered to show only the envelope from
|
||||||
with a total amount of {{mf($repetitions[0]['limit']->amount,false)}}.
|
{{{$repetitions[0]['limitrepetition']->periodShow()}}},
|
||||||
|
which contains {{mf($repetitions[0]['limit']->amount,false)}}.
|
||||||
</p>
|
</p>
|
||||||
<p class="bg-info" style="padding:15px;">
|
<p class="bg-info" style="padding:15px;">
|
||||||
<a href="{{route('budgets.show',$budget->id)}}" class="text-info">Reset the filters.</a>
|
<a href="{{route('budgets.show',$budget->id)}}" class="text-info">Reset the filter(s).</a>
|
||||||
</p>
|
</p>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@
|
|||||||
This view is filtered to show transactions not in an envelope only.
|
This view is filtered to show transactions not in an envelope only.
|
||||||
</p>
|
</p>
|
||||||
<p class="bg-info" style="padding:15px;">
|
<p class="bg-info" style="padding:15px;">
|
||||||
<a href="{{route('budgets.show',$budget->id)}}" class="text-info">Reset the filters.</a>
|
<a href="{{route('budgets.show',$budget->id)}}" class="text-info">Reset the filter(s).</a>
|
||||||
</p>
|
</p>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="bg-info" style="padding:15px;">
|
<p class="bg-info" style="padding:15px;">
|
||||||
<a href="{{route('budgets.show',$budget->id)}}" class="text-info">Reset the filters.</a>
|
<a href="{{route('budgets.show',$budget->id)}}" class="text-info">Reset the filter(s).</a>
|
||||||
</p>
|
</p>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@@ -44,23 +45,23 @@
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||||
|
<div id="chart" style="height:300px;"></div>
|
||||||
@if(isset($filters[0]) && is_object($filters[0]) && get_class($filters[0]) == 'Limit')
|
@if(isset($filters[0]) && is_object($filters[0]) && get_class($filters[0]) == 'Limit')
|
||||||
|
<div id="instr" data-type="envelope" data-envelope="{{$repetitions[0]['limitrepetition']->id}}"></div>
|
||||||
<p class="small text-center">
|
|
||||||
A chart showing the date-range of the selected envelope, all transactions
|
|
||||||
as bars and the amount left in the envelope as a line.
|
|
||||||
</p>
|
|
||||||
@elseif(isset($filters[0]) && $filters[0] == 'no_envelope')
|
@elseif(isset($filters[0]) && $filters[0] == 'no_envelope')
|
||||||
|
<div id="instr" data-type="no_envelope" data-budget="{{$budget->id}}"></div>
|
||||||
<p class="small text-center">
|
<p class="small text-center">
|
||||||
A chart showing the date-range of all the not-enveloped stuff, and their amount.
|
A chart showing the date-range of all the not-enveloped stuff, and their amount.
|
||||||
</p>
|
</p>
|
||||||
@elseif($useSessionDates == true)
|
@elseif($useSessionDates == true)
|
||||||
|
<div id="instr" data-type="session" data-budget="{{$budget->id}}"></div>
|
||||||
<p class="small text-center">
|
<p class="small text-center">
|
||||||
Date range of session, show chart with all expenses in bars
|
Date range of session, show chart with all expenses in bars
|
||||||
find all limit repetitions, add them as individual lines and make them go down.
|
find all limit repetitions, add them as individual lines and make them go down.
|
||||||
same as the first but bigger range (potentially).
|
same as the first but bigger range (potentially).
|
||||||
</p>
|
</p>
|
||||||
@else
|
@else
|
||||||
|
<div id="instr" data-type="default" data-budget="{{$budget->id}}"></div>
|
||||||
<p class="small text-center">(For each visible repetition, a sum of the expense as a bar. A line shows
|
<p class="small text-center">(For each visible repetition, a sum of the expense as a bar. A line shows
|
||||||
the percentage spent for each rep.)</p>
|
the percentage spent for each rep.)</p>
|
||||||
@endif
|
@endif
|
||||||
@@ -107,4 +108,7 @@
|
|||||||
@endif
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
|
@stop
|
||||||
|
@section('scripts')
|
||||||
|
<?php echo javascript_include_tag('budgets'); ?>
|
||||||
@stop
|
@stop
|
||||||
Reference in New Issue
Block a user