mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-19 19:01:58 +00:00
First start making the category report also multi-currency
This commit is contained in:
@@ -95,7 +95,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
|||||||
->render();
|
->render();
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
Log::error(sprintf('Cannot render reports.category.month: %s', $e->getMessage()));
|
Log::error(sprintf('Cannot render reports.category.month: %s', $e->getMessage()));
|
||||||
$result = 'Could not render report view.';
|
$result = sprintf('Could not render report view: %s', $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
@@ -116,6 +116,8 @@ class BudgetController extends Controller
|
|||||||
* @param Collection $budgets
|
* @param Collection $budgets
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
public function accounts(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end)
|
public function accounts(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end)
|
||||||
{
|
{
|
||||||
@@ -392,6 +394,8 @@ class BudgetController extends Controller
|
|||||||
'currency_name' => $currency['currency_name'],
|
'currency_name' => $currency['currency_name'],
|
||||||
'currency_symbol' => $currency['currency_symbol'],
|
'currency_symbol' => $currency['currency_symbol'],
|
||||||
'currency_decimal_places' => $currency['currency_decimal_places'],
|
'currency_decimal_places' => $currency['currency_decimal_places'],
|
||||||
|
'budget_id' => $budget['id'],
|
||||||
|
'budget_name' => $budget['name'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@ namespace FireflyIII\Http\Controllers\Report;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\Category;
|
use FireflyIII\Models\Category;
|
||||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Category\NoCategoryRepositoryInterface;
|
use FireflyIII\Repositories\Category\NoCategoryRepositoryInterface;
|
||||||
@@ -41,6 +42,27 @@ class CategoryController extends Controller
|
|||||||
{
|
{
|
||||||
use BasicDataSupport;
|
use BasicDataSupport;
|
||||||
|
|
||||||
|
|
||||||
|
/** @var OperationsRepositoryInterface */
|
||||||
|
private $opsRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ExpenseReportController constructor.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
$this->opsRepository = app(OperationsRepositoryInterface::class);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show overview of expenses in category.
|
* Show overview of expenses in category.
|
||||||
*
|
*
|
||||||
@@ -146,6 +168,61 @@ class CategoryController extends Controller
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $accounts
|
||||||
|
* @param Collection $categories
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function accounts(Collection $accounts, Collection $categories, Carbon $start, Carbon $end)
|
||||||
|
{
|
||||||
|
$spent = $this->opsRepository->listExpenses($start, $end, $accounts, $categories);
|
||||||
|
$report = [];
|
||||||
|
$sums = [];
|
||||||
|
/** @var Account $account */
|
||||||
|
foreach ($accounts as $account) {
|
||||||
|
$accountId = $account->id;
|
||||||
|
$report[$accountId] = $report[$accountId] ?? [
|
||||||
|
'name' => $account->name,
|
||||||
|
'id' => $account->id,
|
||||||
|
'iban' => $account->iban,
|
||||||
|
'currencies' => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop expenses.
|
||||||
|
foreach ($spent as $currency) {
|
||||||
|
$currencyId = $currency['currency_id'];
|
||||||
|
$sums[$currencyId] = $sums[$currencyId] ?? [
|
||||||
|
'currency_id' => $currency['currency_id'],
|
||||||
|
'currency_symbol' => $currency['currency_symbol'],
|
||||||
|
'currency_name' => $currency['currency_name'],
|
||||||
|
'currency_decimal_places' => $currency['currency_decimal_places'],
|
||||||
|
'sum' => '0',
|
||||||
|
];
|
||||||
|
foreach ($currency['categories'] as $category) {
|
||||||
|
foreach ($category['transaction_journals'] as $journal) {
|
||||||
|
$sourceAccountId = $journal['source_account_id'];
|
||||||
|
$report[$sourceAccountId]['currencies'][$currencyId] = $report[$sourceAccountId]['currencies'][$currencyId] ?? [
|
||||||
|
'currency_id' => $currency['currency_id'],
|
||||||
|
'currency_symbol' => $currency['currency_symbol'],
|
||||||
|
'currency_name' => $currency['currency_name'],
|
||||||
|
'currency_decimal_places' => $currency['currency_decimal_places'],
|
||||||
|
'sum' => '0',
|
||||||
|
];
|
||||||
|
$report[$sourceAccountId]['currencies'][$currencyId]['sum'] = bcadd(
|
||||||
|
$report[$sourceAccountId]['currencies'][$currencyId]['sum'], $journal['amount']
|
||||||
|
);
|
||||||
|
$sums[$currencyId]['sum'] = bcadd($sums[$currencyId]['sum'], $journal['amount']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('reports.category.partials.accounts', compact('sums', 'report'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show overview of income in category.
|
* Show overview of income in category.
|
||||||
|
@@ -78,7 +78,7 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
if (null === $categories || (null !== $categories && 0 === $categories->count())) {
|
if (null === $categories || (null !== $categories && 0 === $categories->count())) {
|
||||||
$collector->setCategories($this->getCategories());
|
$collector->setCategories($this->getCategories());
|
||||||
}
|
}
|
||||||
$collector->withCategoryInformation();
|
$collector->withCategoryInformation()->withAccountInformation();
|
||||||
$journals = $collector->getExtractedJournals();
|
$journals = $collector->getExtractedJournals();
|
||||||
$array = [];
|
$array = [];
|
||||||
|
|
||||||
@@ -115,8 +115,9 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
|
|
||||||
|
|
||||||
$array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [
|
$array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [
|
||||||
'amount' => app('steam')->negative($journal['amount']),
|
'amount' => app('steam')->negative($journal['amount']),
|
||||||
'date' => $journal['date'],
|
'date' => $journal['date'],
|
||||||
|
'source_account_id' => $journal['source_account_id'],
|
||||||
];
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -155,8 +156,8 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
$array = [];
|
$array = [];
|
||||||
|
|
||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
$currencyId = (int)$journal['currency_id'];
|
$currencyId = (int)$journal['currency_id'];
|
||||||
$categoryId = (int)$journal['category_id'];
|
$categoryId = (int)$journal['category_id'];
|
||||||
$categoryName = (string)$journal['category_name'];
|
$categoryName = (string)$journal['category_name'];
|
||||||
|
|
||||||
// catch "no category" entries.
|
// catch "no category" entries.
|
||||||
|
57
public/v1/js/ff/reports/category/month.js
vendored
57
public/v1/js/ff/reports/category/month.js
vendored
@@ -17,28 +17,26 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** global: categoryIncomeUri, categoryExpenseUri, accountIncomeUri, accountExpenseUri, mainUri */
|
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
drawChart();
|
drawChart();
|
||||||
|
|
||||||
$('#categories-in-pie-chart-checked').on('change', function () {
|
|
||||||
redrawPieChart(categoryIncomeUri, 'categories-in-pie-chart');
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#categories-out-pie-chart-checked').on('change', function () {
|
// $('#categories-in-pie-chart-checked').on('change', function () {
|
||||||
redrawPieChart(categoryExpenseUri, 'categories-out-pie-chart');
|
// redrawPieChart(categoryIncomeUri, 'categories-in-pie-chart');
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
$('#accounts-in-pie-chart-checked').on('change', function () {
|
// $('#categories-out-pie-chart-checked').on('change', function () {
|
||||||
redrawPieChart(accountIncomeUri, 'accounts-in-pie-chart');
|
// redrawPieChart(categoryExpenseUri, 'categories-out-pie-chart');
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
$('#accounts-out-pie-chart-checked').on('change', function () {
|
// $('#accounts-in-pie-chart-checked').on('change', function () {
|
||||||
redrawPieChart(accountExpenseUri, 'accounts-out-pie-chart');
|
// redrawPieChart(accountIncomeUri, 'accounts-in-pie-chart');
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
|
// $('#accounts-out-pie-chart-checked').on('change', function () {
|
||||||
|
// redrawPieChart(accountExpenseUri, 'accounts-out-pie-chart');
|
||||||
|
// });
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -46,28 +44,21 @@ $(function () {
|
|||||||
function drawChart() {
|
function drawChart() {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
loadAjaxPartial('accountsHolder', accountsUri);
|
||||||
|
|
||||||
|
|
||||||
// month view:
|
// month view:
|
||||||
doubleYChart(mainUri, 'in-out-chart');
|
//doubleYChart(mainUri, 'in-out-chart');
|
||||||
|
|
||||||
// draw pie chart of income, depending on "show other transactions too":
|
// draw pie chart of income, depending on "show other transactions too":
|
||||||
redrawPieChart(categoryIncomeUri, 'categories-in-pie-chart');
|
// redrawPieChart(categoryIncomeUri, 'categories-in-pie-chart');
|
||||||
redrawPieChart(categoryExpenseUri, 'categories-out-pie-chart');
|
// redrawPieChart(categoryExpenseUri, 'categories-out-pie-chart');
|
||||||
redrawPieChart(accountIncomeUri, 'accounts-in-pie-chart');
|
// redrawPieChart(accountIncomeUri, 'accounts-in-pie-chart');
|
||||||
redrawPieChart(accountExpenseUri, 'accounts-out-pie-chart');
|
// redrawPieChart(accountExpenseUri, 'accounts-out-pie-chart');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function redrawPieChart(uri, container) {
|
function redrawPieChart(uri, container) {
|
||||||
"use strict";
|
"use strict";
|
||||||
var checkbox = $('#' + container + '-checked');
|
multiCurrencyPieChart(uri, container);
|
||||||
|
|
||||||
var others = '0';
|
|
||||||
// check if box is checked:
|
|
||||||
if (checkbox.prop('checked')) {
|
|
||||||
others = '1';
|
|
||||||
}
|
|
||||||
uri = uri.replace('OTHERS', others);
|
|
||||||
|
|
||||||
pieChart(uri, container);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
<th data-defaultsort="disabled">{{ 'description'|_ }}</th>
|
<th data-defaultsort="disabled">{{ 'description'|_ }}</th>
|
||||||
<th data-defaultsign="month">{{ 'date'|_ }}</th>
|
<th data-defaultsign="month">{{ 'date'|_ }}</th>
|
||||||
<th data-defaultsign="az">{{ 'account'|_ }}</th>
|
<th data-defaultsign="az">{{ 'account'|_ }}</th>
|
||||||
|
<th data-defaultsign="az">{{ 'budget'|_ }}</th>
|
||||||
<th data-defaultsign="_19" style="text-align: right;">{{ 'amount'|_ }}</th>
|
<th data-defaultsign="_19" style="text-align: right;">{{ 'amount'|_ }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -28,6 +29,11 @@
|
|||||||
{{ row.destination_account_name }}
|
{{ row.destination_account_name }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td data-sortable="false">
|
||||||
|
<a href="{{ route('budgets.show', row.budget_id) }}">
|
||||||
|
{{ row.budget_name }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
|
||||||
<td data-value="{{ row.amount }}" style="text-align: right;">
|
<td data-value="{{ row.amount }}" style="text-align: right;">
|
||||||
{{ formatAmountBySymbol(row.amount, row.currency_symbol, row.currency_decimal_places) }}
|
{{ formatAmountBySymbol(row.amount, row.currency_symbol, row.currency_decimal_places) }}
|
||||||
|
@@ -1,434 +1,213 @@
|
|||||||
{% extends "./layout/default" %}
|
{% extends "./layout/default" %}
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
{{ Breadcrumbs.render(Route.getCurrentRoute.getName, accountIds, categoryIds, start, end) }}
|
{#{{ Breadcrumbs.render(Route.getCurrentRoute.getName, accountIds, budgetIds, start, end) }}#}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-4 col-md-6">
|
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">{{ 'accounts'|_ }}</h3>
|
<h3 class="box-title">{{ 'accounts'|_ }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body table-responsive no-padding">
|
<div class="box-body table-responsive no-padding" id="accountsHolder">
|
||||||
<table class="table table-hover sortable">
|
</div>
|
||||||
<thead>
|
{# loading indicator #}
|
||||||
<tr>
|
<div class="overlay">
|
||||||
<th data-defaultsign="az">{{ 'name'|_ }}</th>
|
<i class="fa fa-refresh fa-spin"></i>
|
||||||
<th data-defaultsign="_19" style="text-align: right;">{{ 'earned'|_ }}</th>
|
|
||||||
<th data-defaultsign="_19" style="text-align: right;">{{ 'spent'|_ }}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for account in accounts %}
|
|
||||||
<tr>
|
|
||||||
<td data-value="{{ account.name }}">
|
|
||||||
<a href="{{ route('accounts.show', account.id) }}"
|
|
||||||
title="{{ account.name }}">{{ account.name }}</a>
|
|
||||||
</td>
|
|
||||||
{% if accountSummary[account.id] %}
|
|
||||||
<td data-value="{{ accountSummary[account.id].earned }}"
|
|
||||||
style="text-align: right;">{{ accountSummary[account.id].earned|formatAmount }}</td>
|
|
||||||
{% else %}
|
|
||||||
<td data-value="0" style="text-align: right;">{{ 0|formatAmount }}</td>
|
|
||||||
{% endif %}
|
|
||||||
{% if accountSummary[account.id] %}
|
|
||||||
<td data-value="{{ accountSummary[account.id].spent }}"
|
|
||||||
style="text-align: right;">{{ accountSummary[account.id].spent|formatAmount }}</td>
|
|
||||||
{% else %}
|
|
||||||
<td data-value="0" style="text-align: right;">{{ 0|formatAmount }}</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<td>{{ 'sum'|_ }}</td>
|
|
||||||
<td style="text-align: right;">{{ accountSummary.sum.earned|formatAmount }}</td>
|
|
||||||
<td style="text-align: right;">{{ accountSummary.sum.spent|formatAmount }}</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">{{ 'categories'|_ }}</h3>
|
<h3 class="box-title">{{ 'categories'|_ }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body table-responsive no-padding">
|
<div class="box-body table-responsive no-padding" id="categoriesHolder">
|
||||||
<table class="table table-hover sortable">
|
</div>
|
||||||
<thead>
|
{# loading indicator #}
|
||||||
<tr>
|
<div class="overlay">
|
||||||
<th data-defaultsign="az">{{ 'name'|_ }}</th>
|
<i class="fa fa-refresh fa-spin"></i>
|
||||||
<th data-defaultsign="_19" style="text-align: right;">{{ 'earned'|_ }}</th>
|
|
||||||
<th data-defaultsign="_19" style="text-align: right;">{{ 'spent'|_ }}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for category in categories %}
|
|
||||||
<tr>
|
|
||||||
<td data-value="{{ category.name }}">
|
|
||||||
<a href="{{ route('categories.show', category.id) }}"
|
|
||||||
title="{{ category.name }}">{{ category.name }}</a>
|
|
||||||
</td>
|
|
||||||
{% if categorySummary[category.id] %}
|
|
||||||
<td data-value="{{ categorySummary[category.id].earned }}"
|
|
||||||
style="text-align: right;">{{ categorySummary[category.id].earned|formatAmount }}</td>
|
|
||||||
{% else %}
|
|
||||||
<td data-value="0" style="text-align: right;">{{ 0|formatAmount }}</td>
|
|
||||||
{% endif %}
|
|
||||||
{% if categorySummary[category.id] %}
|
|
||||||
<td data-value="{{ categorySummary[category.id].spent }}"
|
|
||||||
style="text-align: right;">{{ categorySummary[category.id].spent|formatAmount }}</td>
|
|
||||||
{% else %}
|
|
||||||
<td data-value="0" style="text-align: right;">{{ 0|formatAmount }}</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<td>{{ 'sum'|_ }}</td>
|
|
||||||
<td style="text-align: right;">{{ categorySummary.sum.earned|formatAmount }}</td>
|
|
||||||
<td style="text-align: right;">{{ categorySummary.sum.spent|formatAmount }}</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if categories.count > 1 %}
|
</div>
|
||||||
<div class="col-lg-2 col-md-3">
|
<div class="row">
|
||||||
<div class="box">
|
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||||
<div class="box-header with-border">
|
|
||||||
<h3 class="box-title">{{ 'income_per_category'|_ }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="box-body">
|
|
||||||
<canvas id="categories-in-pie-chart" style="margin:0 auto;" height="150" width="150"></canvas>
|
|
||||||
<label style="font-weight:normal;">
|
|
||||||
<input type="checkbox" id="categories-in-pie-chart-checked">
|
|
||||||
<small>{{ 'include_income_not_in_category'|_ }}</small>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-2 col-md-3">
|
|
||||||
<div class="box">
|
|
||||||
<div class="box-header with-border">
|
|
||||||
<h3 class="box-title">{{ 'expense_per_category'|_ }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="box-body">
|
|
||||||
<canvas id="categories-out-pie-chart" style="margin:0 auto;" height="150" width="150"></canvas>
|
|
||||||
<label style="font-weight:normal;">
|
|
||||||
<input type="checkbox" id="categories-out-pie-chart-checked">
|
|
||||||
<small>{{ 'include_expense_not_in_category'|_ }}</small>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="col-lg-2 col-md-3" id="pieCharts">
|
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">{{ 'income_per_account'|_ }}</h3>
|
<h3 class="box-title">{{ 'account_per_category'|_ }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body table-responsive no-padding" id="accountPerCategoryHolder">
|
||||||
<canvas id="accounts-in-pie-chart" style="margin:0 auto;" height="150" width="150"></canvas>
|
</div>
|
||||||
<label style="font-weight:normal;">
|
{# loading indicator #}
|
||||||
<input type="checkbox" id="accounts-in-pie-chart-checked">
|
<div class="overlay">
|
||||||
<small>{{ 'include_income_not_in_account'|_ }}</small>
|
<i class="fa fa-refresh fa-spin"></i>
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-2 col-md-3">
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-4 col-md-6">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">{{ 'expense_per_account'|_ }}</h3>
|
<h3 class="box-title">{{ 'expense_per_category'|_ }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<canvas id="accounts-out-pie-chart" style="margin:0 auto;" height="150" width="150"></canvas>
|
<div style="width:100%;margin:0 auto;">
|
||||||
<label style="font-weight:normal;">
|
<canvas id="category-out-pie-chart" style="width:100%;height:250px;" height="250"></canvas>
|
||||||
<input type="checkbox" id="accounts-out-pie-chart-checked">
|
</div>
|
||||||
<small>{{ 'include_expense_not_in_account'|_ }}</small>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-lg-4 col-md-6">
|
||||||
|
<div class="box">
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<div class="box" id="incomeAndExpensesChart">
|
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">{{ 'income_and_expenses'|_ }}</h3>
|
<h3 class="box-title">{{ 'income_per_category'|_ }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<canvas id="in-out-chart" style="width:100%;height:400px;" height="400" width="100%"></canvas>
|
<div style="width:100%;margin:0 auto;">
|
||||||
|
<canvas id="category-in-pie-chart" style="width:100%;height:250px;" height="250"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4 col-md-6">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'expense_per_budget'|_ }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
<div style="width:100%;margin:0 auto;">
|
||||||
|
<canvas id="budgets-out-pie-chart" style="width:100%;height:250px;" height="250"></canvas>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<div class="col-lg-6 col-md-6">
|
||||||
{% if averageExpenses|length > 0 %}
|
<div class="box">
|
||||||
<div class="col-lg-6">
|
<div class="box-header with-border">
|
||||||
<div class="box">
|
<h3 class="box-title">{{ 'expense_per_source_account'|_ }}</h3>
|
||||||
<div class="box-header with-border">
|
</div>
|
||||||
<h3 class="box-title">{{ 'average_spending_per_account'|_ }}</h3>
|
<div class="box-body">
|
||||||
</div>
|
<div style="width:100%;margin:0 auto;">
|
||||||
<div class="box-body table-responsive no-padding">
|
<canvas id="source-accounts-out-pie-chart" style="width:100%;height:250px;" height="250"></canvas>
|
||||||
<table class="table table-hover sortable">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th data-defaultsign="az">{{ 'account'|_ }}</th>
|
|
||||||
<th data-defaultsign="_19" style="text-align: right;">{{ 'spent_average'|_ }}</th>
|
|
||||||
<th data-defaultsign="_19" style="text-align: right;">{{ 'total'|_ }}</th>
|
|
||||||
<th data-defaultsign="_19">{{ 'transaction_count'|_ }}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% set totalCount = 0 %}
|
|
||||||
{% set totalSum = 0 %}
|
|
||||||
{% for row in averageExpenses %}
|
|
||||||
{% if loop.index > listLength %}
|
|
||||||
<tr class="overListLength">
|
|
||||||
{% else %}
|
|
||||||
<tr>
|
|
||||||
{% endif %}
|
|
||||||
<td data-value="{{ row.name }}">
|
|
||||||
<a href="{{ route('accounts.show', row.id) }}">{{ row.name }}</a>
|
|
||||||
</td>
|
|
||||||
<td data-value="{{ row.average }}" style="text-align: right;">
|
|
||||||
{{ row.average|formatAmount }}
|
|
||||||
</td>
|
|
||||||
<td data-value="{{ row.sum }}" style="text-align: right;">
|
|
||||||
{{ row.sum|formatAmount }}
|
|
||||||
</td>
|
|
||||||
<td data-value="{{ row.count }}">
|
|
||||||
{{ row.count }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% set totalCount = totalCount+ row.count %}
|
|
||||||
{% set totalSum = totalSum + row.sum %}
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
{% if averageExpenses|length > listLength %}
|
|
||||||
<tr>
|
|
||||||
<td colspan="4" class="active">
|
|
||||||
<a href="#"
|
|
||||||
class="listLengthTrigger">{{ trans('firefly.show_full_list',{number:incomeTopLength}) }}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
{{ 'sum'|_ }}
|
|
||||||
</td>
|
|
||||||
<td style="text-align:right">{{ totalSum|formatAmount }}</td>
|
|
||||||
<td>{{ totalCount }}</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
</div>
|
||||||
{% if topExpenses|length > 0 %}
|
<div class="col-lg-6 col-md-6">
|
||||||
<div class="col-lg-6">
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
<div class="box">
|
<h3 class="box-title">{{ 'income_per_source_account'|_ }}</h3>
|
||||||
<div class="box-header with-border">
|
</div>
|
||||||
<h3 class="box-title">{{ 'expenses'|_ }} ({{ trans('firefly.topX', {number: listLength}) }}
|
<div class="box-body">
|
||||||
)</h3>
|
<div style="width:100%;margin:0 auto;">
|
||||||
</div>
|
<canvas id="source-accounts-in-pie-chart" style="width:100%;height:250px;" height="250"></canvas>
|
||||||
<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" style="text-align: right;">{{ 'amount'|_ }}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% set totalSum = 0 %}
|
|
||||||
{% for row in topExpenses %}
|
|
||||||
{% set totalSum = totalSum + row.amount %}
|
|
||||||
{% if loop.index > listLength %}
|
|
||||||
<tr class="overListLength">
|
|
||||||
{% else %}
|
|
||||||
<tr>
|
|
||||||
{% endif %}
|
|
||||||
<td data-sortable="false">
|
|
||||||
<a href="{{ route('transactions.show', 1+row.transaction_group_id) }}">
|
|
||||||
{% if row.group_title|length > 0 %}
|
|
||||||
{{ row.group_title }} ({{ 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.destination_account_name }}">
|
|
||||||
<a href="{{ route('accounts.show', row.destination_account_id) }}">
|
|
||||||
{{ row.destination_account_name }}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td data-value="{{ row.amount }}" style="text-align: right;">
|
|
||||||
{{ formatAmountBySymbol(row.amount, row.currency_symbol, row.currency_decimal_places) }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
{% if topExpenses|length > listLength %}
|
|
||||||
<tr>
|
|
||||||
<td colspan="3" class="active">
|
|
||||||
<a href="#"
|
|
||||||
class="listLengthTrigger">{{ trans('firefly.show_full_list',{number:incomeTopLength}) }}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
<tr>
|
|
||||||
<td colspan="3">
|
|
||||||
{{ 'sum'|_ }}
|
|
||||||
</td>
|
|
||||||
<td style="text-align:right">{{ totalSum|formatAmount }}</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% if averageIncome|length > 0 %}
|
<div class="col-lg-6 col-md-6">
|
||||||
<div class="col-lg-6">
|
<div class="box">
|
||||||
<div class="box">
|
<div class="box-header with-border">
|
||||||
<div class="box-header with-border">
|
<h3 class="box-title">{{ 'expense_per_destination_account'|_ }}</h3>
|
||||||
<h3 class="box-title">{{ 'average_income_per_account'|_ }}</h3>
|
</div>
|
||||||
</div>
|
<div class="box-body">
|
||||||
<div class="box-body">
|
<div style="width:100%;margin:0 auto;">
|
||||||
<table class="table table-hover sortable">
|
<canvas id="dest-accounts-out-pie-chart" style="width:100%;height:250px;" height="250"></canvas>
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th data-defaultsign="az">{{ 'account'|_ }}</th>
|
|
||||||
<th data-defaultsign="_19" style="text-align:right;">{{ 'income_average'|_ }}</th>
|
|
||||||
<th data-defaultsign="_19" style="text-align:right;">{{ 'total'|_ }}</th>
|
|
||||||
<th data-defaultsign="_19">{{ 'transaction_count'|_ }}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% set totalCount = 0 %}
|
|
||||||
{% set totalSum = 0 %}
|
|
||||||
{% for row in averageIncome %}
|
|
||||||
{% set totalCount = totalCount+ row.count %}
|
|
||||||
{% set totalSum = totalSum + row.sum %}
|
|
||||||
<tr>
|
|
||||||
<td data-value="{{ row.name }}">
|
|
||||||
<a href="{{ route('accounts.show', row.id) }}">{{ row.name }}</a>
|
|
||||||
</td>
|
|
||||||
<td data-value="{{ row.average }}" style="text-align:right;">
|
|
||||||
{{ (row.average*-1)|formatAmount }}
|
|
||||||
</td>
|
|
||||||
<td data-value="{{ row.sum }}" style="text-align:right;">
|
|
||||||
{{ (row.sum*-1)|formatAmount }}
|
|
||||||
</td>
|
|
||||||
<td data-value="{{ row.count }}">
|
|
||||||
{{ row.count }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
{{ 'sum'|_ }}
|
|
||||||
</td>
|
|
||||||
<td style="text-align:right">{{ (totalSum*-1)|formatAmount }}</td>
|
|
||||||
<td>{{ totalCount }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
</div>
|
||||||
|
<div class="col-lg-6 col-md-6">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'income_per_destination_account'|_ }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
<div style="width:100%;margin:0 auto;">
|
||||||
|
<canvas id="dest-accounts-in-pie-chart" style="width:100%;height:250px;" height="250"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% for category in categories %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="box main_budget_chart">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'income_and_expenses'|_ }} ({{ category.name }})</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
{#<canvas class="main_budget_canvas" data-url="{{ route('chart.category.main', [accountIds, category.id, start.format('Ymd'), end.format('Ymd')]) }}" id="in-out-chart-{{ category.id }}" style="width:100%;height:400px;" height="400" width="100%"></canvas>#}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
<div class="row">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
{% if topIncome|length > 0 %}
|
<div class="box">
|
||||||
<div class="box">
|
<div class="box-header with-border">
|
||||||
<div class="box-header with-border">
|
<h3 class="box-title">{{ 'average_spending_per_destination'|_ }}</h3>
|
||||||
<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 data-defaultsign="month">{{ 'date'|_ }}</th>
|
|
||||||
<th data-defaultsign="az">{{ 'account'|_ }}</th>
|
|
||||||
<th data-defaultsign="_19" style="text-align:right">{{ 'amount'|_ }}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% set totalSum = 0 %}
|
|
||||||
{% for row in topIncome %}
|
|
||||||
{% set totalSum = totalSum + row.amount %}
|
|
||||||
{% if loop.index > listLength %}
|
|
||||||
<tr class="overListLength">
|
|
||||||
{% else %}
|
|
||||||
<tr>
|
|
||||||
{% endif %}
|
|
||||||
<td data-sortable="false">
|
|
||||||
<a href="{{ route('transactions.show', 1+row.transaction_group_id) }}">
|
|
||||||
{% if row.group_title|length > 0 %}
|
|
||||||
{{ row.group_title }} ({{ 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.destination_account_name }}">
|
|
||||||
<a href="{{ route('accounts.show', row.destination_account_id) }}">
|
|
||||||
{{ row.destination_account_name }}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td data-value="{{ row.amount }}" style="text-align: right;">
|
|
||||||
{{ formatAmountBySymbol(row.amount*-1, row.currency_symbol, row.currency_decimal_places) }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
{% if topIncome|length > listLength %}
|
|
||||||
<tr>
|
|
||||||
<td colspan="3" class="active">
|
|
||||||
<a href="#"
|
|
||||||
class="listLengthTrigger">{{ trans('firefly.show_full_list',{number:incomeTopLength}) }}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
<tr>
|
|
||||||
<td colspan="3">
|
|
||||||
{{ 'sum'|_ }}
|
|
||||||
</td>
|
|
||||||
<td style="text-align:right">{{ (totalSum*-1)|formatAmount }}</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
<div class="box-body table-responsive no-padding" id="avgExpensesHolder">
|
||||||
|
</div>
|
||||||
|
{# loading indicator #}
|
||||||
|
<div class="overlay">
|
||||||
|
<i class="fa fa-refresh fa-spin"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'average_earning_per_source'|_ }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body table-responsive no-padding" id="avgIncomeHolder">
|
||||||
|
</div>
|
||||||
|
{# loading indicator #}
|
||||||
|
<div class="overlay">
|
||||||
|
<i class="fa fa-refresh fa-spin"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<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-responsive no-padding" id="topExpensesHolder">
|
||||||
|
</div>
|
||||||
|
{# loading indicator #}
|
||||||
|
<div class="overlay">
|
||||||
|
<i class="fa fa-refresh fa-spin"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<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-responsive no-padding" id="topIncomeHolder">
|
||||||
|
</div>
|
||||||
|
{# loading indicator #}
|
||||||
|
<div class="overlay">
|
||||||
|
<i class="fa fa-refresh fa-spin"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -447,15 +226,24 @@
|
|||||||
var accountIds = '{{ accountIds }}';
|
var accountIds = '{{ accountIds }}';
|
||||||
var categoryIds = '{{ categoryIds }}';
|
var categoryIds = '{{ categoryIds }}';
|
||||||
|
|
||||||
|
// html block URI's:
|
||||||
|
|
||||||
|
var accountsUri = '{{ route('report-data.category.accounts', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd')]) }}';
|
||||||
|
|
||||||
|
{#var categoriesUri = '{{ route('report-data.category.categories', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd')]) }}';#}
|
||||||
|
{#var accountPerCategoryUri = '{{ route('report-data.category.account-per-category', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd')]) }}';#}
|
||||||
|
{#var avgExpensesUri = '{{ route('report-data.category.avg-expenses', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd')]) }}';#}
|
||||||
|
{#var topExpensesUri = '{{ route('report-data.category.top-expenses', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd')]) }}';#}
|
||||||
|
|
||||||
|
{#var avgIncomeUri = '{{ route('report-data.category.avg-income', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd')]) }}';#}
|
||||||
|
{#var topIncomesUri = '{{ route('report-data.category.top-income', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd')]) }}';#}
|
||||||
|
|
||||||
// chart uri's
|
// chart uri's
|
||||||
var categoryIncomeUri = '{{ route('chart.category.category-income', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd'),'OTHERS']) }}';
|
{#var budgetExpenseUri = '{{ route('chart.category.category-expense', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd')]) }}';#}
|
||||||
var categoryExpenseUri = '{{ route('chart.category.category-expense', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd'),'OTHERS']) }}';
|
{#var categoryExpenseUri = '{{ route('chart.category.category-expense', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd')]) }}';#}
|
||||||
var accountIncomeUri = '{{ route('chart.category.account-income', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd'),'OTHERS']) }}';
|
{#var sourceExpenseUri = '{{ route('chart.budget.source-account-expense', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd')]) }}';#}
|
||||||
var accountExpenseUri = '{{ route('chart.category.account-expense', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd'),'OTHERS']) }}';
|
{#var destinationExpenseUri = '{{ route('chart.budget.destination-account-expense', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd')]) }}';#}
|
||||||
var mainUri = '{{ route('chart.category.main', [accountIds, categoryIds, start.format('Ymd'), end.format('Ymd')]) }}';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_VERSION }}"></script>
|
<script type="text/javascript" src="v1/js/ff/reports/all.js?v={{ FF_VERSION }}"></script>
|
||||||
<script type="text/javascript" src="v1/js/ff/reports/category/month.js?v={{ FF_VERSION }}"></script>
|
<script type="text/javascript" src="v1/js/ff/reports/category/month.js?v={{ FF_VERSION }}"></script>
|
||||||
|
|
||||||
|
32
resources/views/v1/reports/category/partials/accounts.twig
Normal file
32
resources/views/v1/reports/category/partials/accounts.twig
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<table class="table table-hover sortable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th data-defaultsign="az">{{ 'name'|_ }}</th>
|
||||||
|
<th data-defaultsign="_19" style="text-align: right;">{{ 'spent'|_ }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for account in report %}
|
||||||
|
{% for currency in account.currencies %}
|
||||||
|
<tr>
|
||||||
|
<td data-value="{{ account.name }} ({{ currency.currency_name }})">
|
||||||
|
<a href="{{ route('accounts.show', account.id) }}" title="{{ account.iban }}">{{ account.name }} ({{ currency.currency_name }})</a>
|
||||||
|
</td>
|
||||||
|
<td data-value="{{ currency.sum }}" style="text-align: right;">
|
||||||
|
{{ formatAmountBySymbol(currency.sum, currency.currency_symbol, currency.currency_decimal_places) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
{% for sum in sums %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ 'sum'|_ }} ({{ sum.currency_name }})</td>
|
||||||
|
<td style="text-align: right;">
|
||||||
|
{{ formatAmountBySymbol(sum.sum, sum.currency_symbol, sum.currency_decimal_places) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
130
routes/web.php
130
routes/web.php
@@ -82,12 +82,13 @@ Route::group(
|
|||||||
// *
|
// *
|
||||||
// */
|
// */
|
||||||
Route::group(
|
Route::group(
|
||||||
['middleware' => 'user-logged-in-no-2fa', 'prefix' => 'two-factor', 'as' => 'two-factor.', 'namespace' => 'FireflyIII\Http\Controllers\Auth'], static function () {
|
['middleware' => 'user-logged-in-no-2fa', 'prefix' => 'two-factor', 'as' => 'two-factor.', 'namespace' => 'FireflyIII\Http\Controllers\Auth'],
|
||||||
Route::post('submit', ['uses' => 'TwoFactorController@submitMFA', 'as' => 'submit']);
|
static function () {
|
||||||
Route::get('lost', ['uses' => 'TwoFactorController@lostTwoFactor', 'as' => 'lost']);
|
Route::post('submit', ['uses' => 'TwoFactorController@submitMFA', 'as' => 'submit']);
|
||||||
// Route::post('', ['uses' => 'TwoFactorController@postIndex', 'as' => 'post']);
|
Route::get('lost', ['uses' => 'TwoFactorController@lostTwoFactor', 'as' => 'lost']);
|
||||||
//
|
// Route::post('', ['uses' => 'TwoFactorController@postIndex', 'as' => 'post']);
|
||||||
}
|
//
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -320,21 +321,22 @@ Route::group(
|
|||||||
* Chart\Account Controller (default report)
|
* Chart\Account Controller (default report)
|
||||||
*/
|
*/
|
||||||
Route::group(
|
Route::group(
|
||||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Chart', 'prefix' => 'chart/account', 'as' => 'chart.account.'], static function () {
|
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Chart', 'prefix' => 'chart/account', 'as' => 'chart.account.'],
|
||||||
Route::get('frontpage', ['uses' => 'AccountController@frontpage', 'as' => 'frontpage']);
|
static function () {
|
||||||
Route::get('expense', ['uses' => 'AccountController@expenseAccounts', 'as' => 'expense']);
|
Route::get('frontpage', ['uses' => 'AccountController@frontpage', 'as' => 'frontpage']);
|
||||||
Route::get('revenue', ['uses' => 'AccountController@revenueAccounts', 'as' => 'revenue']);
|
Route::get('expense', ['uses' => 'AccountController@expenseAccounts', 'as' => 'expense']);
|
||||||
Route::get('report/{accountList}/{start_date}/{end_date}', ['uses' => 'AccountController@report', 'as' => 'report']);
|
Route::get('revenue', ['uses' => 'AccountController@revenueAccounts', 'as' => 'revenue']);
|
||||||
Route::get('period/{account}/{start_date}/{end_date}', ['uses' => 'AccountController@period', 'as' => 'period']);
|
Route::get('report/{accountList}/{start_date}/{end_date}', ['uses' => 'AccountController@report', 'as' => 'report']);
|
||||||
|
Route::get('period/{account}/{start_date}/{end_date}', ['uses' => 'AccountController@period', 'as' => 'period']);
|
||||||
|
|
||||||
Route::get('income-category/{account}/all/all', ['uses' => 'AccountController@incomeCategoryAll', 'as' => 'income-category-all']);
|
Route::get('income-category/{account}/all/all', ['uses' => 'AccountController@incomeCategoryAll', 'as' => 'income-category-all']);
|
||||||
Route::get('expense-category/{account}/all/all', ['uses' => 'AccountController@expenseCategoryAll', 'as' => 'expense-category-all']);
|
Route::get('expense-category/{account}/all/all', ['uses' => 'AccountController@expenseCategoryAll', 'as' => 'expense-category-all']);
|
||||||
Route::get('expense-budget/{account}/all/all', ['uses' => 'AccountController@expenseBudgetAll', 'as' => 'expense-budget-all']);
|
Route::get('expense-budget/{account}/all/all', ['uses' => 'AccountController@expenseBudgetAll', 'as' => 'expense-budget-all']);
|
||||||
|
|
||||||
Route::get('income-category/{account}/{start_date}/{end_date}', ['uses' => 'AccountController@incomeCategory', 'as' => 'income-category']);
|
Route::get('income-category/{account}/{start_date}/{end_date}', ['uses' => 'AccountController@incomeCategory', 'as' => 'income-category']);
|
||||||
Route::get('expense-category/{account}/{start_date}/{end_date}', ['uses' => 'AccountController@expenseCategory', 'as' => 'expense-category']);
|
Route::get('expense-category/{account}/{start_date}/{end_date}', ['uses' => 'AccountController@expenseCategory', 'as' => 'expense-category']);
|
||||||
Route::get('expense-budget/{account}/{start_date}/{end_date}', ['uses' => 'AccountController@expenseBudget', 'as' => 'expense-budget']);
|
Route::get('expense-budget/{account}/{start_date}/{end_date}', ['uses' => 'AccountController@expenseBudget', 'as' => 'expense-budget']);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -342,37 +344,50 @@ Route::group(
|
|||||||
* Chart\Bill Controller
|
* Chart\Bill Controller
|
||||||
*/
|
*/
|
||||||
Route::group(
|
Route::group(
|
||||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Chart', 'prefix' => 'chart/bill', 'as' => 'chart.bill.'], static function () {
|
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Chart', 'prefix' => 'chart/bill', 'as' => 'chart.bill.'],
|
||||||
Route::get('frontpage', ['uses' => 'BillController@frontpage', 'as' => 'frontpage']);
|
static function () {
|
||||||
Route::get('single/{bill}', ['uses' => 'BillController@single', 'as' => 'single']);
|
Route::get('frontpage', ['uses' => 'BillController@frontpage', 'as' => 'frontpage']);
|
||||||
|
Route::get('single/{bill}', ['uses' => 'BillController@single', 'as' => 'single']);
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chart\Budget Controller
|
* Chart\Budget Controller
|
||||||
*/
|
*/
|
||||||
Route::group(
|
Route::group(
|
||||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Chart', 'prefix' => 'chart/budget', 'as' => 'chart.budget.'], static function () {
|
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Chart', 'prefix' => 'chart/budget', 'as' => 'chart.budget.'],
|
||||||
|
static function () {
|
||||||
|
|
||||||
Route::get('frontpage', ['uses' => 'BudgetController@frontpage', 'as' => 'frontpage']);
|
Route::get('frontpage', ['uses' => 'BudgetController@frontpage', 'as' => 'frontpage']);
|
||||||
Route::get('period/0/{currency}/{accountList}/{start_date}/{end_date}', ['uses' => 'BudgetController@periodNoBudget', 'as' => 'period.no-budget']);
|
Route::get('period/0/{currency}/{accountList}/{start_date}/{end_date}', ['uses' => 'BudgetController@periodNoBudget', 'as' => 'period.no-budget']);
|
||||||
Route::get('period/{budget}/{currency}/{accountList}/{start_date}/{end_date}', ['uses' => 'BudgetController@period', 'as' => 'period']);
|
Route::get('period/{budget}/{currency}/{accountList}/{start_date}/{end_date}', ['uses' => 'BudgetController@period', 'as' => 'period']);
|
||||||
Route::get('budget/{budget}/{budgetLimit}', ['uses' => 'BudgetController@budgetLimit', 'as' => 'budget-limit']);
|
Route::get('budget/{budget}/{budgetLimit}', ['uses' => 'BudgetController@budgetLimit', 'as' => 'budget-limit']);
|
||||||
Route::get('budget/{budget}', ['uses' => 'BudgetController@budget', 'as' => 'budget']);
|
Route::get('budget/{budget}', ['uses' => 'BudgetController@budget', 'as' => 'budget']);
|
||||||
|
|
||||||
// these charts are used in budget/show:
|
// these charts are used in budget/show:
|
||||||
Route::get('expense-category/{budget}/{budgetLimit?}', ['uses' => 'BudgetController@expenseCategory', 'as' => 'expense-category']);
|
Route::get('expense-category/{budget}/{budgetLimit?}', ['uses' => 'BudgetController@expenseCategory', 'as' => 'expense-category']);
|
||||||
Route::get('expense-asset/{budget}/{budgetLimit?}', ['uses' => 'BudgetController@expenseAsset', 'as' => 'expense-asset']);
|
Route::get('expense-asset/{budget}/{budgetLimit?}', ['uses' => 'BudgetController@expenseAsset', 'as' => 'expense-asset']);
|
||||||
Route::get('expense-expense/{budget}/{budgetLimit?}', ['uses' => 'BudgetController@expenseExpense', 'as' => 'expense-expense']);
|
Route::get('expense-expense/{budget}/{budgetLimit?}', ['uses' => 'BudgetController@expenseExpense', 'as' => 'expense-expense']);
|
||||||
|
|
||||||
// these charts are used in reports (category reports):
|
// these charts are used in reports (category reports):
|
||||||
Route::get('category/expense/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetReportController@categoryExpense', 'as' => 'category-expense']);
|
Route::get(
|
||||||
Route::get('budget/expense/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetReportController@budgetExpense', 'as' => 'budget-expense']);
|
'category/expense/{accountList}/{budgetList}/{start_date}/{end_date}',
|
||||||
Route::get('source-account/expense/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetReportController@sourceAccountExpense', 'as' => 'source-account-expense']);
|
['uses' => 'BudgetReportController@categoryExpense', 'as' => 'category-expense']
|
||||||
Route::get('destination-account/expense/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetReportController@destinationAccountExpense', 'as' => 'destination-account-expense']);
|
);
|
||||||
Route::get('operations/{accountList}/{budget}/{start_date}/{end_date}', ['uses' => 'BudgetReportController@mainChart', 'as' => 'main']);
|
Route::get(
|
||||||
}
|
'budget/expense/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetReportController@budgetExpense', 'as' => 'budget-expense']
|
||||||
|
);
|
||||||
|
Route::get(
|
||||||
|
'source-account/expense/{accountList}/{budgetList}/{start_date}/{end_date}',
|
||||||
|
['uses' => 'BudgetReportController@sourceAccountExpense', 'as' => 'source-account-expense']
|
||||||
|
);
|
||||||
|
Route::get(
|
||||||
|
'destination-account/expense/{accountList}/{budgetList}/{start_date}/{end_date}',
|
||||||
|
['uses' => 'BudgetReportController@destinationAccountExpense', 'as' => 'destination-account-expense']
|
||||||
|
);
|
||||||
|
Route::get('operations/{accountList}/{budget}/{start_date}/{end_date}', ['uses' => 'BudgetReportController@mainChart', 'as' => 'main']);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -465,12 +480,13 @@ Route::group(
|
|||||||
* Chart\Expense Controller (for expense/revenue report).
|
* Chart\Expense Controller (for expense/revenue report).
|
||||||
*/
|
*/
|
||||||
Route::group(
|
Route::group(
|
||||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Chart', 'prefix' => 'chart/expense', 'as' => 'chart.expense.'], static function () {
|
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Chart', 'prefix' => 'chart/expense', 'as' => 'chart.expense.'],
|
||||||
Route::get(
|
static function () {
|
||||||
'operations/{accountList}/{expenseList}/{start_date}/{end_date}',
|
Route::get(
|
||||||
['uses' => 'ExpenseReportController@mainChart', 'as' => 'main']
|
'operations/{accountList}/{expenseList}/{start_date}/{end_date}',
|
||||||
);
|
['uses' => 'ExpenseReportController@mainChart', 'as' => 'main']
|
||||||
}
|
);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -488,11 +504,12 @@ Route::group(
|
|||||||
* Chart\Report Controller
|
* Chart\Report Controller
|
||||||
*/
|
*/
|
||||||
Route::group(
|
Route::group(
|
||||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Chart', 'prefix' => 'chart/report', 'as' => 'chart.report.'], static function () {
|
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Chart', 'prefix' => 'chart/report', 'as' => 'chart.report.'],
|
||||||
Route::get('operations/{accountList}/{start_date}/{end_date}', ['uses' => 'ReportController@operations', 'as' => 'operations']);
|
static function () {
|
||||||
Route::get('net-worth/{accountList}/{start_date}/{end_date}/', ['uses' => 'ReportController@netWorth', 'as' => 'net-worth']);
|
Route::get('operations/{accountList}/{start_date}/{end_date}', ['uses' => 'ReportController@operations', 'as' => 'operations']);
|
||||||
|
Route::get('net-worth/{accountList}/{start_date}/{end_date}/', ['uses' => 'ReportController@netWorth', 'as' => 'net-worth']);
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -776,10 +793,15 @@ Route::group(
|
|||||||
Route::group(
|
Route::group(
|
||||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Report', 'prefix' => 'report-data/category',
|
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Report', 'prefix' => 'report-data/category',
|
||||||
'as' => 'report-data.category.'], static function () {
|
'as' => 'report-data.category.'], static function () {
|
||||||
|
|
||||||
|
// TODO still in use?
|
||||||
Route::get('operations/{accountList}/{start_date}/{end_date}', ['uses' => 'CategoryController@operations', 'as' => 'operations']);
|
Route::get('operations/{accountList}/{start_date}/{end_date}', ['uses' => 'CategoryController@operations', 'as' => 'operations']);
|
||||||
Route::get('income/{accountList}/{start_date}/{end_date}', ['uses' => 'CategoryController@income', 'as' => 'income']);
|
Route::get('income/{accountList}/{start_date}/{end_date}', ['uses' => 'CategoryController@income', 'as' => 'income']);
|
||||||
Route::get('expenses/{accountList}/{start_date}/{end_date}', ['uses' => 'CategoryController@expenses', 'as' => 'expenses']);
|
Route::get('expenses/{accountList}/{start_date}/{end_date}', ['uses' => 'CategoryController@expenses', 'as' => 'expenses']);
|
||||||
|
|
||||||
|
Route::get('accounts/{accountList}/{categoryList}/{start_date}/{end_date}', ['uses' => 'CategoryController@accounts', 'as' => 'accounts']);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -788,7 +810,7 @@ Route::group(
|
|||||||
*/
|
*/
|
||||||
Route::group(
|
Route::group(
|
||||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Report', 'prefix' => 'report-data/balance', 'as' => 'report-data.balance.'],
|
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Report', 'prefix' => 'report-data/balance', 'as' => 'report-data.balance.'],
|
||||||
function () {
|
static function () {
|
||||||
|
|
||||||
Route::get('general/{accountList}/{start_date}/{end_date}', ['uses' => 'BalanceController@general', 'as' => 'general']);
|
Route::get('general/{accountList}/{start_date}/{end_date}', ['uses' => 'BalanceController@general', 'as' => 'general']);
|
||||||
}
|
}
|
||||||
@@ -801,12 +823,16 @@ Route::group(
|
|||||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Report', 'prefix' => 'report-data/budget', 'as' => 'report-data.budget.'],
|
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Report', 'prefix' => 'report-data/budget', 'as' => 'report-data.budget.'],
|
||||||
static function () {
|
static function () {
|
||||||
|
|
||||||
|
// todo are these two routes still used?
|
||||||
Route::get('general/{accountList}/{start_date}/{end_date}/', ['uses' => 'BudgetController@general', 'as' => 'general']);
|
Route::get('general/{accountList}/{start_date}/{end_date}/', ['uses' => 'BudgetController@general', 'as' => 'general']);
|
||||||
Route::get('period/{accountList}/{start_date}/{end_date}', ['uses' => 'BudgetController@period', 'as' => 'period']);
|
Route::get('period/{accountList}/{start_date}/{end_date}', ['uses' => 'BudgetController@period', 'as' => 'period']);
|
||||||
|
|
||||||
Route::get('accounts/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetController@accounts', 'as' => 'accounts']);
|
Route::get('accounts/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetController@accounts', 'as' => 'accounts']);
|
||||||
Route::get('budgets/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetController@budgets', 'as' => 'budgets']);
|
Route::get('budgets/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetController@budgets', 'as' => 'budgets']);
|
||||||
Route::get('account-per-budget/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetController@accountPerBudget', 'as' => 'account-per-budget']);
|
Route::get(
|
||||||
|
'account-per-budget/{accountList}/{budgetList}/{start_date}/{end_date}',
|
||||||
|
['uses' => 'BudgetController@accountPerBudget', 'as' => 'account-per-budget']
|
||||||
|
);
|
||||||
Route::get('top-expenses/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetController@topExpenses', 'as' => 'top-expenses']);
|
Route::get('top-expenses/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetController@topExpenses', 'as' => 'top-expenses']);
|
||||||
Route::get('avg-expenses/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetController@avgExpenses', 'as' => 'avg-expenses']);
|
Route::get('avg-expenses/{accountList}/{budgetList}/{start_date}/{end_date}', ['uses' => 'BudgetController@avgExpenses', 'as' => 'avg-expenses']);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user