mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Finished category report.
This commit is contained in:
parent
13b96f6136
commit
5088df103f
@ -63,10 +63,18 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
$accountSummary = $this->getAccountSummary();
|
||||
$categorySummary = $this->getCategorySummary();
|
||||
$averageExpenses = $this->getAverageExpenses();
|
||||
$averageIncome = $this->getAverageIncome();
|
||||
$topExpenses = $this->getTopExpenses();
|
||||
$topIncome = $this->getTopIncome();
|
||||
|
||||
|
||||
// render!
|
||||
return view('reports.category.month', compact('accountIds', 'categoryIds', 'reportType', 'accountSummary', 'categorySummary','averageExpenses'))
|
||||
return view(
|
||||
'reports.category.month',
|
||||
compact(
|
||||
'accountIds', 'categoryIds', 'topIncome', 'reportType', 'accountSummary', 'categorySummary', 'averageExpenses', 'averageIncome', 'topExpenses'
|
||||
)
|
||||
)
|
||||
->with('start', $this->start)->with('end', $this->end)
|
||||
->with('categories', $this->categories)
|
||||
->with('accounts', $this->accounts)
|
||||
@ -203,6 +211,45 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
|
||||
}
|
||||
|
||||
private function getAverageIncome(): array
|
||||
{
|
||||
$expenses = $this->getIncome();
|
||||
$result = [];
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($expenses as $transaction) {
|
||||
// opposing name and ID:
|
||||
$opposingId = $transaction->opposing_account_id;
|
||||
|
||||
// is not set?
|
||||
if (!isset($result[$opposingId])) {
|
||||
$name = $transaction->opposing_account_name;
|
||||
$encrypted = intval($transaction->opposing_account_encrypted);
|
||||
$name = $encrypted === 1 ? Crypt::decrypt($name) : $name;
|
||||
$result[$opposingId] = [
|
||||
'name' => $name,
|
||||
'count' => 1,
|
||||
'id' => $opposingId,
|
||||
'average' => $transaction->transaction_amount,
|
||||
'sum' => $transaction->transaction_amount,
|
||||
];
|
||||
continue;
|
||||
}
|
||||
$result[$opposingId]['count']++;
|
||||
$result[$opposingId]['sum'] = bcadd($result[$opposingId]['sum'], $transaction->transaction_amount);
|
||||
$result[$opposingId]['average'] = bcdiv($result[$opposingId]['sum'], strval($result[$opposingId]['count']));
|
||||
}
|
||||
|
||||
// sort result by average:
|
||||
$average = [];
|
||||
foreach ($result as $key => $row) {
|
||||
$average[$key] = floatval($row['average']);
|
||||
}
|
||||
|
||||
array_multisort($average, SORT_DESC, $result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
@ -360,4 +407,40 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
private function getTopExpenses(): Collection
|
||||
{
|
||||
$transactions = $this->getExpenses()->sortBy('transaction_amount');
|
||||
|
||||
$transactions = $transactions->each(
|
||||
function (Transaction $transaction) {
|
||||
if (intval($transaction->opposing_account_encrypted) === 1) {
|
||||
$transaction->opposing_account_name = Crypt::decrypt($transaction->opposing_account_name);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return $transactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
private function getTopIncome(): Collection
|
||||
{
|
||||
$transactions = $this->getIncome()->sortByDesc('transaction_amount');
|
||||
|
||||
$transactions = $transactions->each(
|
||||
function (Transaction $transaction) {
|
||||
if (intval($transaction->opposing_account_encrypted) === 1) {
|
||||
$transaction->opposing_account_name = Crypt::decrypt($transaction->opposing_account_name);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return $transactions;
|
||||
}
|
||||
}
|
@ -66,57 +66,6 @@ function colorizeData(data) {
|
||||
return newData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param URI
|
||||
* @param container
|
||||
* @param chartType
|
||||
* @param options
|
||||
* @param colorData
|
||||
*/
|
||||
function drawAChart(URI, container, chartType, options, colorData) {
|
||||
if ($('#' + container).length === 0) {
|
||||
console.log('No container called ' + container + ' was found.');
|
||||
return;
|
||||
}
|
||||
|
||||
// var result = true;
|
||||
// if (options.beforeDraw) {
|
||||
// result = options.beforeDraw(data, {url: URL, container: container});
|
||||
// }
|
||||
// if (result === false) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
$.getJSON(URI).done(function (data) {
|
||||
|
||||
if (colorData) {
|
||||
data = colorizeData(data);
|
||||
}
|
||||
|
||||
if (allCharts.hasOwnProperty(container)) {
|
||||
console.log('Will draw updated ' + chartType + ' chart');
|
||||
allCharts[container].data.datasets = data.datasets;
|
||||
allCharts[container].data.labels = data.labels;
|
||||
allCharts[container].update();
|
||||
} else {
|
||||
// new chart!
|
||||
console.log('Will draw new ' + chartType + 'chart');
|
||||
var ctx = document.getElementById(container).getContext("2d");
|
||||
allCharts[container] = new Chart(ctx, {
|
||||
type: chartType,
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
}
|
||||
|
||||
}).fail(function () {
|
||||
console.log('Failed to draw ' + chartType + ' in container ' + container);
|
||||
$('#' + container).addClass('general-chart-error');
|
||||
});
|
||||
console.log('URL for ' + chartType + ' chart : ' + URL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function to draw a line chart:
|
||||
* @param URI
|
||||
@ -182,3 +131,60 @@ function pieChart(URI, container) {
|
||||
drawAChart(URI, container, chartType, options, colorData);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param URI
|
||||
* @param container
|
||||
* @param chartType
|
||||
* @param options
|
||||
* @param colorData
|
||||
*/
|
||||
function drawAChart(URI, container, chartType, options, colorData) {
|
||||
if ($('#' + container).length === 0) {
|
||||
console.log('No container called ' + container + ' was found.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$.getJSON(URI).done(function (data) {
|
||||
|
||||
|
||||
if (data.labels.length === 0) {
|
||||
console.log(chartType + " chart in " + container + " has no data.");
|
||||
// remove the chart container + parent
|
||||
var holder = $('#' + container).parent().parent();
|
||||
if (holder.hasClass('box')) {
|
||||
// remove box
|
||||
holder.remove();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (colorData) {
|
||||
data = colorizeData(data);
|
||||
}
|
||||
|
||||
if (allCharts.hasOwnProperty(container)) {
|
||||
console.log('Will draw updated ' + chartType + ' chart');
|
||||
allCharts[container].data.datasets = data.datasets;
|
||||
allCharts[container].data.labels = data.labels;
|
||||
allCharts[container].update();
|
||||
} else {
|
||||
// new chart!
|
||||
console.log('Will draw new ' + chartType + 'chart');
|
||||
var ctx = document.getElementById(container).getContext("2d");
|
||||
allCharts[container] = new Chart(ctx, {
|
||||
type: chartType,
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
}
|
||||
|
||||
}).fail(function () {
|
||||
console.log('Failed to draw ' + chartType + ' in container ' + container);
|
||||
$('#' + container).addClass('general-chart-error');
|
||||
});
|
||||
console.log('URL for ' + chartType + ' chart : ' + URL);
|
||||
}
|
||||
|
@ -55,6 +55,10 @@ $(function () {
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// trigger list thing
|
||||
listLengthInitial();
|
||||
|
||||
});
|
||||
|
||||
function currencySelect(e) {
|
||||
@ -108,3 +112,30 @@ accounting.settings = {
|
||||
decimal: "."
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function listLengthInitial() {
|
||||
"use strict";
|
||||
$('.overListLength').hide();
|
||||
$('.listLengthTrigger').unbind('click').click(triggerList)
|
||||
}
|
||||
|
||||
function triggerList(e) {
|
||||
"use strict";
|
||||
var link = $(e.target);
|
||||
var table = link.parent().parent().parent().parent();
|
||||
console.log('data-hidden = ' + table.attr('data-hidden'));
|
||||
if (table.attr('data-hidden') === 'no') {
|
||||
// hide all elements, return false.
|
||||
table.find('.overListLength').hide();
|
||||
table.attr('data-hidden', 'yes');
|
||||
link.text(showFullList);
|
||||
return false;
|
||||
}
|
||||
// show all, return false
|
||||
table.find('.overListLength').show();
|
||||
table.attr('data-hidden', 'no');
|
||||
link.text(showOnlyTop);
|
||||
|
||||
return false;
|
||||
}
|
@ -43,29 +43,6 @@ function drawChart() {
|
||||
getBoxAmounts();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Removes a chart box if there is nothing for the chart to draw.
|
||||
// *
|
||||
// * @param data
|
||||
// * @param options
|
||||
// * @returns {boolean}
|
||||
// */
|
||||
// function beforeDrawIsEmpty(data, options) {
|
||||
// "use strict";
|
||||
//
|
||||
// // check if chart holds data.
|
||||
// if (data.labels.length === 0) {
|
||||
// // remove the chart container + parent
|
||||
// console.log(options.container + ' appears empty. Removed.');
|
||||
// $('#' + options.container).parent().parent().remove();
|
||||
//
|
||||
// // return false so script stops.
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
|
||||
function getBoxAmounts() {
|
||||
"use strict";
|
||||
var boxes = ['in', 'out', 'bills-unpaid', 'bills-paid'];
|
||||
|
@ -27,32 +27,6 @@ function triggerInfoClick() {
|
||||
$('.firefly-info-button').unbind('click').click(clickInfoButton);
|
||||
}
|
||||
|
||||
function listLengthInitial() {
|
||||
"use strict";
|
||||
$('.overListLength').hide();
|
||||
$('.listLengthTrigger').unbind('click').click(triggerList)
|
||||
}
|
||||
|
||||
function triggerList(e) {
|
||||
"use strict";
|
||||
var link = $(e.target);
|
||||
var table = link.parent().parent().parent().parent();
|
||||
console.log('data-hidden = ' + table.attr('data-hidden'));
|
||||
if (table.attr('data-hidden') === 'no') {
|
||||
// hide all elements, return false.
|
||||
table.find('.overListLength').hide();
|
||||
table.attr('data-hidden', 'yes');
|
||||
link.text(showFullList);
|
||||
return false;
|
||||
}
|
||||
// show all, return false
|
||||
table.find('.overListLength').show();
|
||||
table.attr('data-hidden', 'no');
|
||||
link.text(showOnlyTop);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function clickInfoButton(e) {
|
||||
"use strict";
|
||||
// find all data tags, regardless of what they are:
|
||||
|
@ -698,8 +698,10 @@ return [
|
||||
'everything_else' => 'Everything else',
|
||||
'income_and_expenses' => 'Income and expenses',
|
||||
'spent_average' => 'Spent (average)',
|
||||
'income_average' => 'Income (average)',
|
||||
'transaction_count' => 'Transaction count',
|
||||
|
||||
'average_spending_per_account' => 'Average spending per account',
|
||||
'average_income_per_account' => 'Average income per account',
|
||||
// charts:
|
||||
'chart' => 'Chart',
|
||||
'dayOfMonth' => 'Day of the month',
|
||||
|
@ -16,31 +16,27 @@
|
||||
<table class="table table-hover sortable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'name'|_ }}</th>
|
||||
<th>{{ 'earned'|_ }}</th>
|
||||
<th>{{ 'spent'|_ }}</th>
|
||||
<th data-defaultsign="az">{{ 'name'|_ }}</th>
|
||||
<th data-defaultsign="_19">{{ 'earned'|_ }}</th>
|
||||
<th data-defaultsign="_19">{{ 'spent'|_ }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for account in accounts %}
|
||||
<tr>
|
||||
<td>
|
||||
<td data-value="{{ account.name }}">
|
||||
<a href="{{ route('accounts.show', account.id) }}" title="{{ account.name }}">{{ account.name }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{% if accountSummary[account.id] %}
|
||||
{{ accountSummary[account.id].earned|formatAmount }}
|
||||
{% else %}
|
||||
{{ 0|formatAmount }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if accountSummary[account.id] %}
|
||||
{{ accountSummary[account.id].spent|formatAmount }}
|
||||
{% else %}
|
||||
{{ 0|formatAmount }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% if accountSummary[account.id] %}
|
||||
<td data-value="{{ accountSummary[account.id].earned }}">{{ accountSummary[account.id].earned|formatAmount }}</td>
|
||||
{% else %}
|
||||
<td data-value="0">{{ 0|formatAmount }}</td>
|
||||
{% endif %}
|
||||
{% if accountSummary[account.id] %}
|
||||
<td data-value="{{ accountSummary[account.id].spent }}">{{ accountSummary[account.id].spent|formatAmount }}</td>
|
||||
{% else %}
|
||||
<td data-value="0">{{ 0|formatAmount }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
@ -56,31 +52,27 @@
|
||||
<table class="table table-hover sortable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'name'|_ }}</th>
|
||||
<th>{{ 'earned'|_ }}</th>
|
||||
<th>{{ 'spent'|_ }}</th>
|
||||
<th data-defaultsign="az">{{ 'name'|_ }}</th>
|
||||
<th data-defaultsign="_19">{{ 'earned'|_ }}</th>
|
||||
<th data-defaultsign="_19">{{ 'spent'|_ }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for category in categories %}
|
||||
<tr>
|
||||
<td>
|
||||
<td data-value="{{ category.name }}">
|
||||
<a href="{{ route('categories.show', category.id) }}" title="{{ category.name }}">{{ category.name }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{% if categorySummary[category.id] %}
|
||||
{{ categorySummary[category.id].earned|formatAmount }}
|
||||
{% else %}
|
||||
{{ 0|formatAmount }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if categorySummary[category.id] %}
|
||||
{{ categorySummary[category.id].spent|formatAmount }}
|
||||
{% else %}
|
||||
{{ 0|formatAmount }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% if categorySummary[category.id] %}
|
||||
<td data-value="{{ categorySummary[category.id].earned }}">{{ categorySummary[category.id].earned|formatAmount }}</td>
|
||||
{% else %}
|
||||
<td data-value="0">{{ 0|formatAmount }}</td>
|
||||
{% endif %}
|
||||
{% if categorySummary[category.id] %}
|
||||
<td data-value="{{ categorySummary[category.id].spent }}">{{ categorySummary[category.id].spent|formatAmount }}</td>
|
||||
{% else %}
|
||||
<td data-value="0">{{ 0|formatAmount }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
@ -162,12 +154,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{#
|
||||
big chart here
|
||||
Show income / expenses per period. Differs per report: month = per day, year = per month, multi-year = per year.
|
||||
In a bar chart, possibly grouped by expense/revenue account.
|
||||
#}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="box">
|
||||
@ -178,9 +164,10 @@
|
||||
<table class="table table-hover sortable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'account'|_ }}</th>
|
||||
<th>{{ 'spent_average'|_ }}</th>
|
||||
<th>{{ 'transaction_count'|_ }}</th>
|
||||
<th data-defaultsign="az">{{ 'account'|_ }}</th>
|
||||
<th data-defaultsign="_19">{{ 'spent_average'|_ }}</th>
|
||||
<th data-defaultsign="_19">{{ 'total'|_ }}</th>
|
||||
<th data-defaultsign="_19">{{ 'transaction_count'|_ }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -189,10 +176,13 @@
|
||||
<td data-value="{{ row.name }}">
|
||||
<a href="{{ route('accounts.show', row.id) }}">{{ row.name }}</a>
|
||||
</td>
|
||||
<td>
|
||||
<td data-value="{{ row.average }}">
|
||||
{{ row.average|formatAmount }}
|
||||
</td>
|
||||
<td>
|
||||
<td data-value="{{ row.sum }}">
|
||||
{{ row.sum|formatAmount }}
|
||||
</td>
|
||||
<td data-value="{{ row.count }}">
|
||||
{{ row.count }}
|
||||
</td>
|
||||
</tr>
|
||||
@ -203,69 +193,175 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'expenses'|_ }} ({{ trans('firefly.topX', {number: 10}) }})</h3>
|
||||
{% if topExpenses.count > 0 %}
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'expenses'|_ }} ({{ trans('firefly.topX', {number: listLength}) }})</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<table class="table table-hover sortable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-defaultsort="disabled">{{ 'description'|_ }}</th>
|
||||
<th data-defaultsign="month">{{ 'date'|_ }}</th>
|
||||
<th data-defaultsign="az">{{ 'account'|_ }}</th>
|
||||
<th data-defaultsign="_19">{{ 'amount'|_ }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in topExpenses %}
|
||||
{% if loop.index > listLength %}
|
||||
<tr class="overListLength">
|
||||
{% else %}
|
||||
<tr>
|
||||
{% endif %}
|
||||
<td data-sortable="false">
|
||||
<a href="{{ route('transactions.show', row.journal_id) }}">
|
||||
{% if row.transaction_description|length > 0 %}
|
||||
{{ row.transaction_description }} ({{ row.description }})
|
||||
{% else %}
|
||||
{{ row.description }}
|
||||
{% endif %}
|
||||
</a>
|
||||
</td>
|
||||
<td data-value="{{ row.date.format('Y-m-d') }}">
|
||||
{{ row.date.formatLocalized(monthAndDayFormat) }}
|
||||
</td>
|
||||
<td data-value="{{ row.opposing_account_name }}">
|
||||
<a href="{{ route('accounts.show', row.opposing_account_id) }}">
|
||||
{{ row.opposing_account_name }}
|
||||
</a>
|
||||
</td>
|
||||
<td data-value="{{ row.transaction_amount }}">
|
||||
{{ row.transaction_amount|formatAmount }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
{% if topExpenses.count > listLength %}
|
||||
<tr>
|
||||
<td colspan="3" class="active">
|
||||
<a href="#" class="listLengthTrigger">{{ trans('firefly.show_full_list',{number:incomeTopLength}) }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'average_income_per_account'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% if averageIncome|length > 0 %}
|
||||
<div class="col-lg-6">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'average_income_per_account'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<table class="table table-hover sortable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-defaultsign="az">{{ 'account'|_ }}</th>
|
||||
<th data-defaultsign="_19">{{ 'income_average'|_ }}</th>
|
||||
<th data-defaultsign="_19">{{ 'total'|_ }}</th>
|
||||
<th data-defaultsign="_19">{{ 'transaction_count'|_ }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in averageIncome %}
|
||||
<tr>
|
||||
<td data-value="{{ row.name }}">
|
||||
<a href="{{ route('accounts.show', row.id) }}">{{ row.name }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ row.average|formatAmount }}
|
||||
</td>
|
||||
<td>
|
||||
{{ row.sum|formatAmount }}
|
||||
</td>
|
||||
<td>
|
||||
{{ row.count }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="col-lg-6">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'income'|_ }} ({{ trans('firefly.topX', {number: 10}) }})</h3>
|
||||
{% if topIncome.count > 0 %}
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'income'|_ }} ({{ trans('firefly.topX', {number: listLength}) }})</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<table class="table table-hover sortable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-defaultsort="disabled">{{ 'description'|_ }}</th>
|
||||
<th>{{ 'date'|_ }}</th>
|
||||
<th data-defaultsign="az">{{ 'account'|_ }}</th>
|
||||
<th>{{ 'amount'|_ }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in topIncome %}
|
||||
{% if loop.index > listLength %}
|
||||
<tr class="overListLength">
|
||||
{% else %}
|
||||
<tr>
|
||||
{% endif %}
|
||||
<td>
|
||||
<a href="{{ route('transactions.show', row.journal_id) }}">
|
||||
{% if row.transaction_description|length > 0 %}
|
||||
{{ row.transaction_description }} ({{ row.description }})
|
||||
{% else %}
|
||||
{{ row.description }}
|
||||
{% endif %}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ row.date.formatLocalized(monthAndDayFormat) }}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ route('accounts.show', row.opposing_account_id) }}">
|
||||
{{ row.opposing_account_name }}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ row.transaction_amount|formatAmount }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
{% if topIncome.count > listLength %}
|
||||
<tr>
|
||||
<td colspan="3" class="active">
|
||||
<a href="#" class="listLengthTrigger">{{ trans('firefly.show_full_list',{number:incomeTopLength}) }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3">
|
||||
List of spending (withdrawals) by account, if relevant. Grouped:<br>
|
||||
|
||||
BC: 456
|
||||
AH: 123
|
||||
|
||||
order by size
|
||||
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
List of spending (withdrawals) by transaction, if relevant. Not grouped<br>
|
||||
|
||||
more groceries: 456
|
||||
groceries: 123
|
||||
|
||||
ordered by size. top x list?
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
Same but for income
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script type="text/javascript" src="js/lib/Chart.bundle.min.js"></script>
|
||||
<script type="text/javascript" src="js/ff/charts.defaults.js"></script>
|
||||
<script type="text/javascript" src="js/ff/charts.js"></script>
|
||||
<script type="text/javascript" src="js/lib/bootstrap-sortable.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
// to report another URL:
|
||||
@ -273,8 +369,6 @@
|
||||
var endDate = '{{ end.format('Ymd') }}';
|
||||
var accountIds = '{{ accountIds }}';
|
||||
var categoryIds = '{{ categoryIds }}';
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@ -284,4 +378,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block styles %}
|
||||
<link rel="stylesheet" href="css/bootstrap-sortable.css" type="text/css" media="all"/>
|
||||
{% endblock %}
|
@ -25,7 +25,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
{% if categories.getCategories.count > expenseTopLength %}
|
||||
{% if categories.getCategories.count > listLength %}
|
||||
<tr>
|
||||
<td colspan="2" class="active">
|
||||
<a href="#" class="listLengthTrigger">{{ trans('firefly.show_full_list',{number:incomeTopLength}) }}</a>
|
||||
|
@ -24,7 +24,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
{% if expenses.getExpenses|length > expenseTopLength %}
|
||||
{% if expenses.getExpenses|length > listLength %}
|
||||
<tr>
|
||||
<td colspan="2" class="active">
|
||||
<a href="#" class="listLengthTrigger">{{ trans('firefly.show_full_list',{number:incomeTopLength}) }}</a>
|
||||
|
Loading…
Reference in New Issue
Block a user