mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-23 04:46:44 +00:00
New interface for budget overview.
This commit is contained in:
@@ -389,7 +389,7 @@ class UpgradeDatabase extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private function verifyCurrencyInfo()
|
private function verifyCurrencyInfo()
|
||||||
{
|
{
|
||||||
|
@@ -15,6 +15,7 @@ namespace FireflyIII\Http\Controllers;
|
|||||||
|
|
||||||
use Amount;
|
use Amount;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use Exception;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
use FireflyIII\Http\Requests\BudgetFormRequest;
|
use FireflyIII\Http\Requests\BudgetFormRequest;
|
||||||
@@ -166,16 +167,36 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param string|null $moment
|
||||||
|
*
|
||||||
* @return View
|
* @return View
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index(string $moment = null)
|
||||||
{
|
{
|
||||||
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
|
$start = session('start', new Carbon);
|
||||||
|
$end = session('end', new Carbon);
|
||||||
|
|
||||||
|
// make date if present:
|
||||||
|
if (!is_null($moment) || strlen(strval($moment)) !== 0) {
|
||||||
|
try {
|
||||||
|
$start = new Carbon($moment);
|
||||||
|
$end = Navigation::endOfPeriod($start, $range);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$next = clone $end;
|
||||||
|
$next->addDay();
|
||||||
|
$prev = clone $start;
|
||||||
|
$prev->subDay();
|
||||||
|
|
||||||
|
|
||||||
$this->repository->cleanupBudgets();
|
$this->repository->cleanupBudgets();
|
||||||
|
|
||||||
|
|
||||||
$budgets = $this->repository->getActiveBudgets();
|
$budgets = $this->repository->getActiveBudgets();
|
||||||
$inactive = $this->repository->getInactiveBudgets();
|
$inactive = $this->repository->getInactiveBudgets();
|
||||||
$start = session('start', new Carbon);
|
|
||||||
$end = session('end', new Carbon);
|
|
||||||
$periodStart = $start->formatLocalized($this->monthAndDayFormat);
|
$periodStart = $start->formatLocalized($this->monthAndDayFormat);
|
||||||
$periodEnd = $end->formatLocalized($this->monthAndDayFormat);
|
$periodEnd = $end->formatLocalized($this->monthAndDayFormat);
|
||||||
$budgetInformation = $this->collectBudgetInformation($budgets, $start, $end);
|
$budgetInformation = $this->collectBudgetInformation($budgets, $start, $end);
|
||||||
@@ -184,9 +205,17 @@ class BudgetController extends Controller
|
|||||||
$spent = array_sum(array_column($budgetInformation, 'spent'));
|
$spent = array_sum(array_column($budgetInformation, 'spent'));
|
||||||
$budgeted = array_sum(array_column($budgetInformation, 'budgeted'));
|
$budgeted = array_sum(array_column($budgetInformation, 'budgeted'));
|
||||||
|
|
||||||
|
// display info
|
||||||
|
$currentMonth = Navigation::periodShow($start, $range);
|
||||||
|
$nextText = Navigation::periodShow($next, $range);
|
||||||
|
$prevText = Navigation::periodShow($prev, $range);
|
||||||
|
|
||||||
return view(
|
return view(
|
||||||
'budgets.index',
|
'budgets.index',
|
||||||
compact('available', 'periodStart', 'periodEnd', 'budgetInformation', 'inactive', 'budgets', 'spent', 'budgeted')
|
compact(
|
||||||
|
'available', 'currentMonth', 'next', 'nextText', 'prev', 'prevText', 'periodStart', 'periodEnd', 'budgetInformation', 'inactive', 'budgets',
|
||||||
|
'spent', 'budgeted'
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -87,96 +87,151 @@
|
|||||||
{% if budgets.count == 0 and inactive.count == 0 %}
|
{% if budgets.count == 0 and inactive.count == 0 %}
|
||||||
{% include 'partials.empty' with {what: 'default', type: 'budgets',route: route('budgets.create')} %}
|
{% include 'partials.empty' with {what: 'default', type: 'budgets',route: route('budgets.create')} %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{# date thing #}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for budget in budgets %}
|
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||||
<div class="col-lg-4 col-sm-6 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">
|
<h3 class="box-title">Period thing</h3>
|
||||||
<!-- link in header -->
|
</div>
|
||||||
{% if budgetInformation[budget.id]['currentLimit'] %}
|
<div class="box-body">
|
||||||
<a href="{{ route('budgets.show.limit', [budget.id, budgetInformation[budget.id]['currentLimit'].id]) }}" class="budget-link"
|
<div class="row">
|
||||||
data-id="{{ budget.id }}">{{ budget.name }}</a>
|
<div class="col-lg-2">
|
||||||
{% else %}
|
<select class="form-control">
|
||||||
<a href="{{ route('budgets.show',budget.id) }}" class="budget-link" data-id="{{ budget.id }}">{{ budget.name }}</a>
|
<option>x</option>
|
||||||
{% endif %}
|
</select>
|
||||||
</h3>
|
</div>
|
||||||
|
<div class="col-lg-8 text-center">
|
||||||
<!-- ACTIONS MENU -->
|
<div class="btn btn-group btn-group-lg" style="padding-top:0;">
|
||||||
<div class="box-tools pull-right">
|
<a href="{{ route('budgets.index', [prev.format('Y-m-d')]) }}" class="btn btn-default" title="{{ prevText }}">←</a>
|
||||||
<div class="btn-group">
|
<a href="#" class="btn btn-default">{{ currentMonth }}</a>
|
||||||
<button class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown"><i class="fa fa-ellipsis-v"></i></button>
|
<a href="{{ route('budgets.index', [next.format('Y-m-d')]) }}" class="btn btn-default" title="{{ nextText }}">→</a>
|
||||||
<ul class="dropdown-menu" role="menu">
|
</div>
|
||||||
<li><a href="{{ route('budgets.edit',budget.id) }}"><i class="fa fa-pencil fa-fw"></i> {{ 'edit'|_ }}</a></li>
|
</div>
|
||||||
<li><a href="{{ route('budgets.delete',budget.id) }}"><i class="fa fa-trash fa-fw"></i> {{ 'delete'|_ }}</a></li>
|
<div class="col-lg-2 text-right">
|
||||||
</ul>
|
<select class="form-control">
|
||||||
|
<option>x</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
</div>
|
||||||
<table class="table">
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">Budget stuff</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body no-padding">
|
||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width:10%;"> </th>
|
||||||
|
<th>Budget</th>
|
||||||
|
<th style="width:25%;">{{ 'budgeted'|_ }}</th>
|
||||||
|
<th>Spent</th>
|
||||||
|
<th>Left</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
{% for budget in budgets %}
|
||||||
<tr>
|
<tr>
|
||||||
<td style="width:40%;">
|
|
||||||
{{ 'budgeted'|_ }}
|
|
||||||
<span class="small"><br/>
|
|
||||||
{{ session('start').formatLocalized(monthAndDayFormat) }} -
|
|
||||||
{{ session('end').formatLocalized(monthAndDayFormat) }}</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
<td>
|
||||||
<div class="form-group" style="margin-bottom:0;">
|
<div class="btn-group btn-group-xs">
|
||||||
<div class="input-group">
|
<a href="{{ route('budgets.edit',budget.id) }}" class="btn btn-xs btn-default"><i class="fa fa-fw fa-pencil"></i></a>
|
||||||
<div class="input-group-addon">{{ defaultCurrency.symbol|raw }}</div>
|
<a href="{{ route('budgets.delete',budget.id) }}" class="btn btn-xs btn-danger"><i class="fa fa-fw fa-trash-o"></i></a>
|
||||||
<input type="hidden" name="balance_currency_id" value="{{ defaultCurrency.id }}"/>
|
|
||||||
{% if budgetInformation[budget.id]['currentLimit'] %}
|
|
||||||
{% set repAmount = budgetInformation[budget.id]['currentLimit'].amount %}
|
|
||||||
{% else %}
|
|
||||||
{% set repAmount = '0' %}
|
|
||||||
{% endif %}
|
|
||||||
<input class="form-control budgetAmount" data-original="{{ repAmount }}"
|
|
||||||
data-id="{{ budget.id }}" value="{{ repAmount|round }}" autocomplete="off"
|
|
||||||
step="1" min="0" name="amount" type="number">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
<td>
|
||||||
<tr>
|
{% if budgetInformation[budget.id]['currentLimit'] %}
|
||||||
<td style="width:40%;">
|
<a href="{{ route('budgets.show.limit', [budget.id, budgetInformation[budget.id]['currentLimit'].id]) }}"
|
||||||
{{ 'spent'|_ }}
|
class="budget-link"
|
||||||
<span class="small"><br/>
|
data-id="{{ budget.id }}">{{ budget.name }}</a>
|
||||||
{{ session('start').formatLocalized(monthAndDayFormat) }} -
|
{% else %}
|
||||||
{{ session('end').formatLocalized(monthAndDayFormat) }}
|
<a href="{{ route('budgets.show',budget.id) }}" class="budget-link" data-id="{{ budget.id }}">{{ budget.name }}</a>
|
||||||
</span>
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-addon">{{ defaultCurrency.symbol|raw }}</div>
|
||||||
|
<input type="hidden" name="balance_currency_id" value="{{ defaultCurrency.id }}"/>
|
||||||
|
{% if budgetInformation[budget.id]['currentLimit'] %}
|
||||||
|
{% set repAmount = budgetInformation[budget.id]['currentLimit'].amount %}
|
||||||
|
{% else %}
|
||||||
|
{% set repAmount = '0' %}
|
||||||
|
{% endif %}
|
||||||
|
<input class="form-control budgetAmount" data-original="{{ repAmount }}"
|
||||||
|
data-id="{{ budget.id }}" value="{{ repAmount|round }}" autocomplete="off"
|
||||||
|
step="1" min="0" name="amount" type="number">
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ budgetInformation[budget.id]['spent']|formatAmount }}
|
{{ budgetInformation[budget.id]['spent']|formatAmount }}
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ (repAmount - budgetInformation[budget.id]['spent'])|formatAmount }}
|
||||||
|
</td>
|
||||||
|
{#
|
||||||
|
<div class="box-body">
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<td style="width:40%;">
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="form-group" style="margin-bottom:0;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="width:40%;">
|
||||||
|
{{ 'spent'|_ }}
|
||||||
|
<span class="small"><br/>
|
||||||
|
{{ session('start').formatLocalized(monthAndDayFormat) }} -
|
||||||
|
{{ session('end').formatLocalized(monthAndDayFormat) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% if budgetInformation[budget.id]['otherLimits'].count > 0 %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
{% for other in budgetInformation[budget.id]['otherLimits'] %}
|
||||||
|
<li>
|
||||||
|
<!-- translate -->
|
||||||
|
Budgeted
|
||||||
|
<a href="{{ route('budgets.show.limit', [budget.id, other.id]) }}">{{ other.amount|formatAmountPlain }}</a>
|
||||||
|
between
|
||||||
|
{{ other.start_date.formatLocalized(monthAndDayFormat) }}
|
||||||
|
and {{ other.end_date.formatLocalized(monthAndDayFormat) }}.
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
#}
|
||||||
</tr>
|
</tr>
|
||||||
{% if budgetInformation[budget.id]['otherLimits'].count > 0 %}
|
{% endfor %}
|
||||||
<tr>
|
</tbody>
|
||||||
<td colspan="2">
|
|
||||||
<ul class="list-unstyled">
|
|
||||||
{% for other in budgetInformation[budget.id]['otherLimits'] %}
|
|
||||||
<li>
|
|
||||||
<!-- translate -->
|
|
||||||
Budgeted
|
|
||||||
<a href="{{ route('budgets.show.limit', [budget.id, other.id]) }}">{{ other.amount|formatAmountPlain }}</a>
|
|
||||||
between
|
|
||||||
{{ other.start_date.formatLocalized(monthAndDayFormat) }}
|
|
||||||
and {{ other.end_date.formatLocalized(monthAndDayFormat) }}.
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if loop.index % 3 == 0 %}
|
|
||||||
</div><div class="row">
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if inactive|length > 0 %}
|
{% if inactive|length > 0 %}
|
||||||
@@ -200,16 +255,16 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// actually spent bar data:
|
// actually spent bar data:
|
||||||
var spent = {{ spent * -1 }}; // must be positive for the calculation to work.
|
var spent = {{ spent * -1 }}; // must be positive for the calculation to work.
|
||||||
var currencySymbol = "{{ getCurrencySymbol()|raw }}";
|
var currencySymbol = "{{ getCurrencySymbol()|raw }}";
|
||||||
|
|
||||||
// budgeted data:
|
// budgeted data:
|
||||||
var budgeted = {{ budgeted }};
|
var budgeted = {{ budgeted }};
|
||||||
var available = {{ available }};
|
var available = {{ available }};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/javascript" src="js/ff/budgets/index.js"></script>
|
<script type="text/javascript" src="js/ff/budgets/index.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@@ -134,7 +134,7 @@ Route::group(
|
|||||||
*/
|
*/
|
||||||
Route::group(
|
Route::group(
|
||||||
['middleware' => 'user-full-auth', 'prefix' => 'budgets', 'as' => 'budgets.'], function () {
|
['middleware' => 'user-full-auth', 'prefix' => 'budgets', 'as' => 'budgets.'], function () {
|
||||||
Route::get('', ['uses' => 'BudgetController@index', 'as' => 'index']);
|
Route::get('{moment?}', ['uses' => 'BudgetController@index', 'as' => 'index']);
|
||||||
Route::get('income', ['uses' => 'BudgetController@updateIncome', 'as' => 'income']);
|
Route::get('income', ['uses' => 'BudgetController@updateIncome', 'as' => 'income']);
|
||||||
Route::get('create', ['uses' => 'BudgetController@create', 'as' => 'create']);
|
Route::get('create', ['uses' => 'BudgetController@create', 'as' => 'create']);
|
||||||
Route::get('edit/{budget}', ['uses' => 'BudgetController@edit', 'as' => 'edit']);
|
Route::get('edit/{budget}', ['uses' => 'BudgetController@edit', 'as' => 'edit']);
|
||||||
|
Reference in New Issue
Block a user