Code improvements for budgets.

This commit is contained in:
James Cole 2016-04-25 13:20:42 +02:00
parent b4f18dbe77
commit 607d0115f0
5 changed files with 114 additions and 38 deletions

View File

@ -3,6 +3,7 @@
use Amount;
use Auth;
use Carbon\Carbon;
use Config;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Requests\BudgetFormRequest;
use FireflyIII\Models\Budget;
@ -142,18 +143,22 @@ class BudgetController extends Controller
*/
public function index(BudgetRepositoryInterface $repository, ARI $accountRepository)
{
$budgets = $repository->getActiveBudgets();
$inactive = $repository->getInactiveBudgets();
$spent = '0';
$budgeted = '0';
$range = Preferences::get('viewRange', '1M')->data;
$budgets = $repository->getActiveBudgets();
$inactive = $repository->getInactiveBudgets();
$spent = '0';
$budgeted = '0';
$range = Preferences::get('viewRange', '1M')->data;
$repeatFreq = Config::get('firefly.range_to_repeat_freq.' . $range);
/** @var Carbon $date */
$date = session('start', new Carbon);
$start = Navigation::startOfPeriod($date, $range);
$end = Navigation::endOfPeriod($start, $range);
/** @var Carbon $start */
$start = session('start', new Carbon);
/** @var Carbon $end */
$end = session('end', new Carbon);
$key = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd');
$budgetIncomeTotal = Preferences::get($key, 1000)->data;
$period = Navigation::periodShow($start, $range);
$periodStart = $start->formatLocalized($this->monthAndDayFormat);
$periodEnd = $end->formatLocalized($this->monthAndDayFormat);
$accounts = $accountRepository->getAccounts(['Default account', 'Asset account', 'Cash account']);
/**
@ -164,8 +169,9 @@ class BudgetController extends Controller
// loop the budgets:
/** @var Budget $budget */
foreach ($budgets as $budget) {
$budget->spent = $repository->balanceInPeriod($budget, $start, $end, $accounts);
$budget->currentRep = $repository->getCurrentRepetition($budget, $start, $end);
$budget->spent = $repository->balanceInPeriod($budget, $start, $end, $accounts);
$budget->currentRep = $repository->getCurrentRepetition($budget, $repeatFreq, $start, $end);
$budget->otherRepetitions = $repository->getValidRepetitions($budget, $start, $end, $budget->currentRep);
if (!is_null($budget->currentRep->id)) {
$budgeted = bcadd($budgeted, $budget->currentRep->amount);
}
@ -178,7 +184,12 @@ class BudgetController extends Controller
$defaultCurrency = Amount::getDefaultCurrency();
return view(
'budgets.index', compact('budgetMaximum', 'period', 'range', 'budgetIncomeTotal', 'defaultCurrency', 'inactive', 'budgets', 'spent', 'budgeted')
'budgets.index', compact(
'budgetMaximum', 'periodStart', 'periodEnd',
'period', 'range', 'budgetIncomeTotal',
'defaultCurrency', 'inactive', 'budgets',
'spent', 'budgeted'
)
);
}

View File

@ -408,14 +408,16 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
/**
* @param Budget $budget
* @param string $repeatFreq
* @param Carbon $start
* @param Carbon $end
*
* @return LimitRepetition
*/
public function getCurrentRepetition(Budget $budget, Carbon $start, Carbon $end): LimitRepetition
public function getCurrentRepetition(Budget $budget, string $repeatFreq, Carbon $start, Carbon $end): LimitRepetition
{
$data = $budget->limitrepetitions()
->where('budget_limits.repeat_freq', $repeatFreq)
->where('limit_repetitions.startdate', $start->format('Y-m-d 00:00:00'))
->where('limit_repetitions.enddate', $end->format('Y-m-d 00:00:00'))
->first(['limit_repetitions.*']);
@ -844,4 +846,44 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
return $limit;
}
/**
* Returns a list of budget limits that are valid in the current given range.
* $ignore is optional. Send an empty limit rep.
*
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
* @param LimitRepetition $ignore
*
* @return Collection
*/
public function getValidRepetitions(Budget $budget, Carbon $start, Carbon $end, LimitRepetition $ignore) : Collection
{
$query = $budget->limitrepetitions()
->where( // valid when either of these are true:
function ($q) use ($start, $end) {
$q->where(
function ($query) use ($start, $end) {
// starts before start time, and the end also after start time.
$query->where('limit_repetitions.startdate', '<=', $start->format('Y-m-d 00:00:00'));
$query->where('limit_repetitions.enddate', '>=', $start->format('Y-m-d 00:00:00'));
}
);
$q->orWhere(
function ($query) use ($start, $end) {
// end after end time, and start is before end time
$query->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d 00:00:00'));
$query->where('limit_repetitions.enddate', '>=', $end->format('Y-m-d 00:00:00'));
}
);
}
);
if (!is_null($ignore->id)) {
$query->where('limit_repetitions.id', '!=', $ignore->id);
}
$data = $query->get(['limit_repetitions.*']);
return $data;
}
}

View File

@ -146,14 +146,27 @@ interface BudgetRepositoryInterface
*/
public function getBudgetsAndLimitsInRange(Carbon $start, Carbon $end): Collection;
/**
* Returns a list of budget limits that are valid in the current given range.
*
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
* @param LimitRepetition $ignore
*
* @return Collection
*/
public function getValidRepetitions(Budget $budget, Carbon $start, Carbon $end, LimitRepetition $ignore) : Collection;
/**
* @param Budget $budget
* @param string $repeatFreq
* @param Carbon $start
* @param Carbon $end
*
* @return LimitRepetition
*/
public function getCurrentRepetition(Budget $budget, Carbon $start, Carbon $end): LimitRepetition;
public function getCurrentRepetition(Budget $budget, string $repeatFreq, Carbon $start, Carbon $end): LimitRepetition;
/**
* Returns all expenses for the given budget and the given accounts, in the given period.

View File

@ -459,8 +459,11 @@ return [
'store_new_budget' => 'Store new budget',
'stored_new_budget' => 'Stored new budget ":name"',
'availableIn' => 'Available in :date',
'available_between' => 'Available between :start and :end',
'transactionsWithoutBudget' => 'Expenses without budget',
'transactionsWithoutBudgetDate' => 'Expenses without budget in :date',
'transactions_no_budget' => 'Expenses without budget between :start and :end',
'spent_between' => 'Spent between :start and :end',
'createBudget' => 'New budget',
'inactiveBudgets' => 'Inactive budgets',
'without_budget_between' => 'Transactions without a budget between :start and :end',

View File

@ -9,7 +9,7 @@
<div class="col-lg-9 col-sm-8 col-md-8">
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">{{ Session.get('start').formatLocalized(monthFormat) }}</h3>
<h3 class="box-title">{{ periodStart }} &mdash; {{ periodEnd }}</h3>
<!-- ACTIONS MENU -->
<div class="box-tools pull-right">
@ -23,7 +23,7 @@
<small>{{ 'budgeted'|_ }}: <span id="budgetedAmount" class="text-success">{{ budgeted|formatAmountPlain }}</span></small>
</div>
<div class="col-lg-6 col-md-4 col-sm-3" style="text-align:right;">
<small>{{ trans('firefly.availableIn',{date : period }) }}:
<small>{{ trans('firefly.available_between',{start : periodStart, end: periodEnd }) }}:
<a href="#" class="updateIncome"><span id="budgetIncomeTotal"
data-value="{{ budgetIncomeTotal }}">{{ budgetIncomeTotal|formatAmount }}</span></a>
</small>
@ -44,7 +44,7 @@
</div>
<div class="row">
<div class="col-lg-6 col-md-4 col-sm-3">
<small>{{ 'spent'|_ }}: {{ spent|formatAmount }}</small>
<small>{{ trans('firefly.spent_between', {start: periodStart, end: periodEnd}) }}: {{ spent|formatAmount }}</small>
</div>
</div>
<div class="row">
@ -77,7 +77,7 @@
<div class="box-body">
<p>
<a href="{{ route('budgets.noBudget') }}">
{{ trans('firefly.transactionsWithoutBudgetDate', {date: period|lower }) }}
{{ trans('firefly.transactions_no_budget', {start: periodStart, end: periodEnd }) }}
</a>
</p>
</div>
@ -99,7 +99,6 @@
</div>
</div>
<p>Bla bla bla</p>
<div class="row">
{% for budget in budgets %}
<div class="col-lg-4 col-sm-6 col-md-6">
@ -132,7 +131,7 @@
<tr>
<td style="width:40%;">
{{ 'budgeted'|_ }}
<span class="small"><br />
<span class="small"><br/>
{{ session('start').formatLocalized(monthAndDayFormat) }} -
{{ session('end').formatLocalized(monthAndDayFormat) }}</span>
</td>
@ -160,35 +159,43 @@
<tr>
<td style="width:40%;">
{{ 'spent'|_ }}
<span class="small"><br />
<span class="small"><br/>
{{ session('start').formatLocalized(monthAndDayFormat) }} -
{{ session('end').formatLocalized(monthAndDayFormat) }}
</span>
</td>
<td>{{ budget.spent|formatAmount }}</a></td>
</tr>
<!--
<tr>
<td style="width:40%">
<span class="text-danger">
Conflicts
</span>
</td>
<td>
<ul class="list-unstyled">
<li>Also budgeted {{ 123|formatAmount }} between x and y.</li>
<li>Also budgeted {{ 123|formatAmount }} between x and y.</li>
</ul>
</td>
</tr>
-->
{% if budget.otherRepetitions.count > 0 %}
<tr>
<td colspan="2">
<ul class="list-unstyled">
{% for other in budget.otherRepetitions %}
{% if other.id != budget.currentRep.id %}
<li>Budgeted
<a href="{{ route('budgets.show', [budget.id, other.id]) }}">{{ other.amount|formatAmountPlain }}</a>
between
{{ other.startdate.formatLocalized(monthAndDayFormat) }}
and {{ other.enddate.formatLocalized(monthAndDayFormat) }}.
</li>
{% endif %}
{% endfor %}
</ul>
</td>
</tr>
{% endif %}
</table>
</div>
</div>
</div>
{% if loop.index % 3 == 0 %}
</div><div class="row">
{% endif %}
{% endfor %}
</div>
{% if inactive|length > 0 %}
{% if inactive|length > 0 %}
<div class="row">
<div class="col-lg-3 col-sm-4 col-md-6">
<div class="box">
<div class="box-header with-border">
@ -209,8 +216,8 @@
</div>
</div>
</div>
{% endif %}
</div>
</div>
{% endif %}
{% endblock %}
{% block scripts %}
<script type="text/javascript">