This commit is contained in:
James Cole 2020-07-25 08:03:57 +02:00
parent 02ad8273eb
commit 5e1306282a
No known key found for this signature in database
GPG Key ID: B5669F9493CDE38D
2 changed files with 214 additions and 138 deletions

View File

@ -98,138 +98,56 @@ class IndexController extends Controller
public function index(Request $request, Carbon $start = null, Carbon $end = null)
{
Log::debug('Start of IndexController::index()');
// collect some basic vars:
$range = app('preferences')->get('viewRange', '1M')->data;
$start = $start ?? session('start', Carbon::now()->startOfMonth());
$end = $end ?? app('navigation')->endOfPeriod($start, $range);
$defaultCurrency = app('amount')->getDefaultCurrency();
$currencies = $this->currencyRepository->getEnabled();
$budgeted = '0';
$spent = '0';
Log::debug(sprintf('1) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
// new period stuff:
$periodTitle = app('navigation')->periodShow($start, $range);
$prevLoop = $this->getPreviousPeriods($start, $range);
$nextLoop = $this->getNextPeriods($start, $range);
Log::debug(sprintf('2) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
// get all available budgets.
$ab = $this->abRepository->get($start, $end);
$availableBudgets = [];
Log::debug(sprintf('3) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
// for each, complement with spent amount:
/** @var AvailableBudget $entry */
foreach ($ab as $entry) {
$array = $entry->toArray();
$array['start_date'] = $entry->start_date;
$array['end_date'] = $entry->end_date;
// get all available budgets:
$availableBudgets = $this->getAllAvailableBudgets($start, $end);
// spent in period:
$spentArr = $this->opsRepository->sumExpenses($entry->start_date, $entry->end_date, null, null, $entry->transactionCurrency);
$array['spent'] = $spentArr[$entry->transaction_currency_id]['sum'] ?? '0';
// get all active budgets:
$budgets = $this->getAllBudgets($start, $end, $currencies, $defaultCurrency);
$sums = $this->getSums($budgets);
// budgeted in period:
$budgeted = $this->blRepository->budgeted($entry->start_date, $entry->end_date, $entry->transactionCurrency, );
$array['budgeted'] = $budgeted;
$availableBudgets[] = $array;
unset($spentArr);
Log::debug(sprintf('4) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
}
if (0 === count($availableBudgets)) {
// get budgeted for default currency:
if (0 === count($availableBudgets)) {
$budgeted = $this->blRepository->budgeted($start, $end, $defaultCurrency,);
$spentArr = $this->opsRepository->sumExpenses($start, $end, null, null, $defaultCurrency);
$spent = $spentArr[$defaultCurrency->id]['sum'] ?? '0';
unset($spentArr);
Log::debug(sprintf('5) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
}
// count the number of enabled currencies. This determines if we display a "+" button.
$currencies = $this->currencyRepository->getEnabled();
$enableAddButton = $currencies->count() > count($availableBudgets);
// number of days for consistent budgeting.
$activeDaysPassed = $this->activeDaysPassed($start, $end); // see method description.
$activeDaysLeft = $this->activeDaysLeft($start, $end); // see method description.
Log::debug(sprintf('6) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
// get all budgets, and paginate them into $budgets.
$collection = $this->repository->getActiveBudgets();
$budgets = [];
Log::debug(sprintf('7) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
// complement budget with budget limits in range, and expenses in currency X in range.
/** @var Budget $current */
foreach ($collection as $current) {
$array = $current->toArray();
$array['spent'] = [];
$array['budgeted'] = [];
$array['attachments'] = $this->repository->getAttachments($current);
$array['auto_budget'] = $this->repository->getAutoBudget($current);
$budgetLimits = $this->blRepository->getBudgetLimits($current, $start, $end);
Log::debug(sprintf('8) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
/** @var BudgetLimit $limit */
foreach ($budgetLimits as $limit) {
$currency = $limit->transactionCurrency ?? $defaultCurrency;
$array['budgeted'][] = [
'id' => $limit->id,
'amount' => number_format((float) $limit->amount, $currency->decimal_places, '.', ''),
'start_date' => $limit->start_date->formatLocalized($this->monthAndDayFormat),
'end_date' => $limit->end_date->formatLocalized($this->monthAndDayFormat),
'in_range' => $limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end),
'currency_id' => $currency->id,
'currency_symbol' => $currency->symbol,
'currency_name' => $currency->name,
'currency_decimal_places' => $currency->decimal_places,
];
Log::debug(sprintf('9) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
}
/** @var TransactionCurrency $currency */
foreach ($currencies as $currency) {
$spentArr = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$current]), $currency);
if (isset($spentArr[$currency->id]['sum'])) {
$array['spent'][$currency->id]['spent'] = $spentArr[$currency->id]['sum'];
$array['spent'][$currency->id]['currency_id'] = $currency->id;
$array['spent'][$currency->id]['currency_symbol'] = $currency->symbol;
$array['spent'][$currency->id]['currency_decimal_places'] = $currency->decimal_places;
Log::debug(sprintf('10) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
}
}
$budgets[] = $array;
}
// get all inactive budgets, and simply list them:
$inactive = $this->repository->getInactiveBudgets();
Log::debug(sprintf('11) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
return view(
'budgets.index',
compact(
'availableBudgets',
'budgeted',
'spent',
'prevLoop',
'nextLoop',
'budgets',
'currencies',
'enableAddButton',
'periodTitle',
'defaultCurrency',
'activeDaysPassed',
'activeDaysLeft',
'inactive',
'budgets',
'start',
'end'
'budgets.index', compact(
'availableBudgets', 'budgeted', 'spent', 'prevLoop', 'nextLoop', 'budgets', 'currencies', 'enableAddButton', 'periodTitle',
'defaultCurrency', 'activeDaysPassed', 'activeDaysLeft', 'inactive', 'budgets', 'start', 'end', 'sums'
)
);
}
/**
* @param Request $request
*
* @param BudgetRepositoryInterface $repository
*
* @return JsonResponse
@ -250,4 +168,154 @@ class IndexController extends Controller
return response()->json(['OK']);
}
/**
* @param array $budgets
*
* @return array
*/
private function getSums(array $budgets): array
{
$sums = [
'budgeted' => [],
'spent' => [],
'left' => [],
];
/** @var array $budget */
foreach ($budgets as $budget) {
/** @var array $spent */
foreach ($budget['spent'] as $spent) {
$currencyId = $spent['currency_id'];
$sums['spent'][$currencyId]
= $sums['spent'][$currencyId]
?? [
'amount' => '0',
'currency_id' => $spent['currency_id'],
'currency_symbol' => $spent['currency_symbol'],
'currency_decimal_places' => $spent['currency_decimal_places'],
];
$sums['spent'][$currencyId]['amount'] = bcadd($sums['spent'][$currencyId]['amount'], $spent['spent']);
}
/** @var array $budgeted */
foreach ($budget['budgeted'] as $budgeted) {
$currencyId = $budgeted['currency_id'];
$sums['budgeted'][$currencyId]
= $sums['budgeted'][$currencyId]
?? [
'amount' => '0',
'currency_id' => $budgeted['currency_id'],
'currency_symbol' => $budgeted['currency_symbol'],
'currency_decimal_places' => $budgeted['currency_decimal_places'],
];
$sums['budgeted'][$currencyId]['amount'] = bcadd($sums['budgeted'][$currencyId]['amount'], $budgeted['amount']);
// also calculate how much left from budgeted:
$sums['left'][$currencyId] = $sums['left'][$currencyId]
?? [
'amount' => '0',
'currency_id' => $budgeted['currency_id'],
'currency_symbol' => $budgeted['currency_symbol'],
'currency_decimal_places' => $budgeted['currency_decimal_places'],
];
}
}
// final calculation for 'left':
foreach ($sums['budgeted'] as $currencyId => $info) {
$spent = $sums['spent'][$currencyId]['amount'] ?? '0';
$budgeted = $sums['budgeted'][$currencyId]['amount'] ?? '0';
$sums['left'][$currencyId]['amount'] = bcadd($spent, $budgeted);
}
return $sums;
}
/**
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
private function getAllAvailableBudgets(Carbon $start, Carbon $end): array
{
// get all available budgets.
$ab = $this->abRepository->get($start, $end);
$availableBudgets = [];
// for each, complement with spent amount:
/** @var AvailableBudget $entry */
foreach ($ab as $entry) {
$array = $entry->toArray();
$array['start_date'] = $entry->start_date;
$array['end_date'] = $entry->end_date;
// spent in period:
$spentArr = $this->opsRepository->sumExpenses($entry->start_date, $entry->end_date, null, null, $entry->transactionCurrency);
$array['spent'] = $spentArr[$entry->transaction_currency_id]['sum'] ?? '0';
// budgeted in period:
$budgeted = $this->blRepository->budgeted($entry->start_date, $entry->end_date, $entry->transactionCurrency,);
$array['budgeted'] = $budgeted;
$availableBudgets[] = $array;
unset($spentArr);
}
return $availableBudgets;
}
/**
* @param Carbon $start
* @param Carbon $end
* @param Collection $currencies
* @param TransactionCurrency $defaultCurrency
*
* @return array
*/
private function getAllBudgets(Carbon $start, Carbon $end, Collection $currencies, TransactionCurrency $defaultCurrency): array
{
// get all budgets, and paginate them into $budgets.
$collection = $this->repository->getActiveBudgets();
$budgets = [];
Log::debug(sprintf('7) Start is "%s", end is "%s"', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
// complement budget with budget limits in range, and expenses in currency X in range.
/** @var Budget $current */
foreach ($collection as $current) {
$array = $current->toArray();
$array['spent'] = [];
$array['budgeted'] = [];
$array['attachments'] = $this->repository->getAttachments($current);
$array['auto_budget'] = $this->repository->getAutoBudget($current);
$budgetLimits = $this->blRepository->getBudgetLimits($current, $start, $end);
/** @var BudgetLimit $limit */
foreach ($budgetLimits as $limit) {
$currency = $limit->transactionCurrency ?? $defaultCurrency;
$array['budgeted'][] = [
'id' => $limit->id,
'amount' => number_format((float) $limit->amount, $currency->decimal_places, '.', ''),
'start_date' => $limit->start_date->formatLocalized($this->monthAndDayFormat),
'end_date' => $limit->end_date->formatLocalized($this->monthAndDayFormat),
'in_range' => $limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end),
'currency_id' => $currency->id,
'currency_symbol' => $currency->symbol,
'currency_name' => $currency->name,
'currency_decimal_places' => $currency->decimal_places,
];
}
/** @var TransactionCurrency $currency */
foreach ($currencies as $currency) {
$spentArr = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$current]), $currency);
if (isset($spentArr[$currency->id]['sum'])) {
$array['spent'][$currency->id]['spent'] = $spentArr[$currency->id]['sum'];
$array['spent'][$currency->id]['currency_id'] = $currency->id;
$array['spent'][$currency->id]['currency_symbol'] = $currency->symbol;
$array['spent'][$currency->id]['currency_decimal_places'] = $currency->decimal_places;
}
}
$budgets[] = $array;
}
return $budgets;
}
}

View File

@ -216,11 +216,11 @@
<table class="table table-bordered sortable-table table-striped sortable" id="budgetList">
<thead>
<tr>
<th data-defaultsort="disabled" class="hidden-sm hidden-xs" style="width:10%;">&nbsp;</th>
<th data-defaultsign="az">{{ 'budget'|_ }}</th>
<th data-defaultsign="_19" style="width:25%;">{{ 'budgeted'|_ }}</th>
<th data-defaultsign="_19" class="hidden-sm hidden-xs">{{ 'spent'|_ }} ({{ 'per_day'|_|lower }})</th>
<th data-defaultsign="_19">{{ 'left'|_ }} ({{ 'per_day'|_|lower }})</th>
<th class="hidden-sm hidden-xs" style="width:10%;">&nbsp;</th>
<th>{{ 'budget'|_ }}</th>
<th style="width:25%;">{{ 'budgeted'|_ }}</th>
<th class="hidden-sm hidden-xs">{{ 'spent'|_ }} ({{ 'per_day'|_|lower }})</th>
<th>{{ 'left'|_ }} ({{ 'per_day'|_|lower }})</th>
</tr>
</thead>
<tbody>
@ -228,12 +228,12 @@
<tr data-id="{{ budget.id }}">
<td class="hidden-sm hidden-xs">
<div class="btn-group btn-group-xs">
<a href="#" class="handle btn btn-default"><i class="fa fa-fw fa-arrows-v"></i></a>
<a href="#" class="handle object-handle btn btn-default"><i class="fa fa-fw fa-bars"></i></a>
<a href="{{ route('budgets.edit', budget.id) }}" class="btn btn-xs btn-default"><i class="fa fa-fw fa-pencil"></i></a>
<a href="{{ route('budgets.delete', budget.id) }}" class="btn btn-xs btn-danger"><i class="fa fa-fw fa-trash-o"></i></a>
</div>
</td>
<td data-value="{{ budget.name }}">
<td>
<a href="{{ route('budgets.show',budget.id) }}" data-id="{{ budget.id }}">{{ budget.name }}</a>
{% if budget.auto_budget %}
{% if 1 == budget.auto_budget.auto_budget_type %}
@ -247,7 +247,7 @@
<i class="fa fa-paperclip"></i>
{% endif %}
</td>
<td data-value="-1">
<td>
{% if 0==budget.budgeted|length %}
<div class="input-group">
<div class="input-group-addon">{{ defaultCurrency.symbol }}</div>
@ -290,15 +290,19 @@
</a>
{% endif %}
</td>
<td class="hidden-sm hidden-xs spent" data-id="{{ budget.id }}">
<td class="hidden-sm hidden-xs spent" data-id="{{ budget.id }}" style="text-align:right;">
{% for spentInfo in budget.spent %}
{{ formatAmountBySymbol(spentInfo.spent, spentInfo.currency_symbol, spentInfo.currency_decimal_places) }}
({{ formatAmountBySymbol(spentInfo.spent / activeDaysPassed, spentInfo.currency_symbol, spentInfo.currency_decimal_places) }})
<br/>
{% endfor %}
{% for budgetLimit in budget.budgeted %}
{% if null == budget.spent[budgetLimit.currency_id] %}
{{ formatAmountBySymbol(0, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }}<br/>
{% endif %}
{% endfor %}
</td>
<td class="left" data-id="{{ budget.id }}">
<td class="left" data-id="{{ budget.id }}" style="text-align: right;">
{% for spentInfo in budget.spent %}
{% set countLimit = 0 %}
{% for budgetLimit in budget.budgeted %}
@ -324,41 +328,45 @@
<br/>
{% endif %}
{% endfor %}
<!-- only makes sense to list what's left for budgeted amounts.-->
<!--
{% if budget.budgeted|length > 0 %}
{% for budgetLimit in budget.budgeted %}
{% for spentInfo in budget.spent %}
{% if spentInfo.currency_id == budgetLimit.currency_id %}
<span data-currency="{{ spentInfo.currency_id }}" data-limit="{{ budgetLimit.id }}" class="amount_left">
{{ formatAmountBySymbol(spentInfo.spent + budgetLimit.amount, spentInfo.currency_symbol, spentInfo.currency_decimal_places) }}
{% if spentInfo.spent + budgetLimit.amount > 0 %}
({{ formatAmountBySymbol((spentInfo.spent + budgetLimit.amount) / activeDaysLeft, spentInfo.currency_symbol, spentInfo.currency_decimal_places) }})
{% else %}
({{ formatAmountBySymbol(0, spentInfo.currency_symbol, spentInfo.currency_decimal_places) }})
{% endif %}
{% if null == budget.spent[budgetLimit.currency_id] %}
<span class="left_span" data-currency="{{ spentInfo.currency_id }}" data-limit="{{ budgetLimit.id }}"
data-value="{{ spentInfo.spent + budgetLimit.amount }}" class="amount_left">
{{ formatAmountBySymbol(budgetLimit.amount, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }}
({{ formatAmountBySymbol(budgetLimit.amount / activeDaysLeft, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }})
</span>
<br/>
{% endif %}
{% endfor %}
{% endfor %}
{% endif %}
-->
{#{{ "-1"|formatAmount }}#}
{#{{ (repAmount + budgetInformation[budget.id]['spent'])|formatAmount }}#}
{#{% if repAmount + budgetInformation[budget.id]['spent'] > 0 %}#}
{#({{ "-1"|formatAmount }})#}
{#({{ ((repAmount + budgetInformation[budget.id]['spent']) / activeDaysLeft)|formatAmount }})#}
{#{% endif %}#}
</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td>&nbsp;</td>
<td><em>{{ 'sum'|_ }}</em></td>
<td style="text-align:right;">
{% for arr in sums.budgeted %}
{{ formatAmountBySymbol(arr.amount, arr.currency_symbol, arr.currency_decimal_places) }}<br/>
{% endfor %}
</td>
<td style="text-align:right;">
{% for arr in sums.spent %}
{{ formatAmountBySymbol(arr.amount, arr.currency_symbol, arr.currency_decimal_places) }}
({{ formatAmountBySymbol(arr.amount / activeDaysPassed, arr.currency_symbol, arr.currency_decimal_places) }})
<br/>
{% endfor %}
</td>
<td style="text-align: right;">
{% for arr in sums.left %}
{{ formatAmountBySymbol(arr.amount, arr.currency_symbol, arr.currency_decimal_places) }}
({{ formatAmountBySymbol(arr.amount / activeDaysLeft, arr.currency_symbol, arr.currency_decimal_places) }})
<br/>
{% endfor %}
</td>
</tr>
</tfoot>
</table>
</div>
<div class="box-footer">