mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2024-12-27 17:31:09 -06:00
Code improvements for budgets.
This commit is contained in:
parent
b4f18dbe77
commit
607d0115f0
@ -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'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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',
|
||||
|
@ -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 }} — {{ 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">
|
||||
|
Loading…
Reference in New Issue
Block a user