This commit is contained in:
James Cole 2019-09-04 09:20:26 +02:00
parent 2bff6b49e6
commit 5c468e1c49
8 changed files with 218 additions and 384 deletions

View File

@ -1,223 +0,0 @@
<?php
/**
* BudgetReportHelper.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Report;
use Carbon\Carbon;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\NoBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use Illuminate\Support\Collection;
use Log;
/**
* Class BudgetReportHelper.
*
* @codeCoverageIgnore
*/
class BudgetReportHelper implements BudgetReportHelperInterface
{
/** @var BudgetLimitRepositoryInterface */
private $blRepository;
/** @var NoBudgetRepositoryInterface */
private $noBudgetRepository;
/** @var OperationsRepositoryInterface */
private $opsRepository;
/** @var BudgetRepositoryInterface The budget repository interface. */
private $repository;
/**
* BudgetReportHelper constructor.
*/
public function __construct()
{
$this->repository = app(BudgetRepositoryInterface::class);
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
$this->opsRepository = app(OperationsRepositoryInterface::class);
$this->noBudgetRepository = app(NoBudgetRepositoryInterface::class);
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
}
/**
* Get the full budget report.
*
* TODO one big method is very complex.
*
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts
*
* @return array
*/
public function getBudgetReport(Carbon $start, Carbon $end, Collection $accounts): array
{
$set = $this->repository->getBudgets();
$array = [
'budgets' => [],
'sums' => [],
];
/** @var Budget $budget */
foreach ($set as $budget) {
$entry = [
'budget_id' => $budget->id,
'budget_name' => $budget->name,
'no_budget' => false,
'rows' => [],
];
// get multi currency expenses first:
$budgetLimits = $this->blRepository->getBudgetLimits($budget, $start, $end);
$expenses = $this->opsRepository->spentInPeriodMc(new Collection([$budget]), $accounts, $start, $end);
$defaultCurrency = app('amount')->getDefaultCurrencyByUser($budget->user);
Log::debug(sprintf('Default currency for getBudgetReport is %s', $defaultCurrency->code));
if (0 === count($expenses)) {
// list the budget limits, basic amounts.
/** @var BudgetLimit $limit */
foreach ($budgetLimits as $limit) {
$currency = $limit->transactionCurrency ?? $defaultCurrency;
Log::debug(sprintf('Default currency for limit #%d is %s', $limit->id, $currency->code));
$row = [
'limit_id' => $limit->id,
'start_date' => $limit->start_date,
'end_date' => $limit->end_date,
'budgeted' => $limit->amount,
'spent' => '0',
'left' => $limit->amount,
'overspent' => '0',
'currency_id' => $currency->id,
'currency_code' => $currency->code,
'currency_name' => $currency->name,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
];
$entry['rows'][] = $row;
}
}
foreach ($expenses as $expense) {
$limit = $this->budgetLimitInCurrency($expense['currency_id'], $budgetLimits);
$row = [
'limit_id' => null,
'start_date' => null,
'end_date' => null,
'budgeted' => null,
'spent' => $expense['amount'],
'left' => null,
'overspent' => '0',
'currency_id' => $expense['currency_id'],
'currency_code' => $expense['currency_name'],
'currency_name' => $expense['currency_name'],
'currency_symbol' => $expense['currency_symbol'],
'currency_decimal_places' => $expense['currency_decimal_places'],
];
if (null !== $limit) {
// yes
$row['start_date'] = $limit->start_date;
$row['end_date'] = $limit->end_date;
$row['budgeted'] = $limit->amount;
$row['limit_id'] = $limit->id;
// less than zero? Set to 0.0
$row['left'] = -1 === bccomp(bcadd($limit->amount, $row['spent']), '0') ? '0' : bcadd($limit->amount, $row['spent']);
// spent > budgeted? then sum, otherwise other sum
$row['overspent'] = 1 === bccomp(bcmul($row['spent'],'-1'), $row['budgeted']) ? bcadd($row['spent'], $row['budgeted']) : '0';
}
$entry['rows'][] = $row;
}
$array['budgets'][] = $entry;
}
$noBudget = $this->noBudgetRepository->spentInPeriodWoBudgetMc($accounts, $start, $end);
$noBudgetEntry = [
'budget_id' => null,
'budget_name' => null,
'no_budget' => true,
'rows' => [],
];
foreach ($noBudget as $row) {
$noBudgetEntry['rows'][] = [
'limit_id' => null,
'start_date' => null,
'end_date' => null,
'budgeted' => null,
'spent' => $row['amount'],
'left' => null,
'overspent' => null,
'currency_id' => $row['currency_id'],
'currency_code' => $row['currency_code'],
'currency_name' => $row['currency_name'],
'currency_symbol' => $row['currency_symbol'],
'currency_decimal_places' => $row['currency_decimal_places'],
];
}
$array['budgets'][] = $noBudgetEntry;
// fill sums:
/** @var array $budget */
foreach ($array['budgets'] as $budget) {
/** @var array $row */
foreach ($budget['rows'] as $row) {
$currencyId = $row['currency_id'];
$array['sums'][$currencyId] = $array['sums'][$currencyId] ?? [
'currency_id' => $row['currency_id'],
'currency_code' => $row['currency_code'],
'currency_name' => $row['currency_name'],
'currency_symbol' => $row['currency_symbol'],
'currency_decimal_places' => $row['currency_decimal_places'],
'budgeted' => '0',
'spent' => '0',
'left' => '0',
'overspent' => '0',
];
$array['sums'][$currencyId]['budgeted'] = bcadd($array['sums'][$currencyId]['budgeted'], $row['budgeted'] ?? '0');
$array['sums'][$currencyId]['spent'] = bcadd($array['sums'][$currencyId]['spent'], $row['spent'] ?? '0');
$array['sums'][$currencyId]['left'] = bcadd($array['sums'][$currencyId]['left'], $row['left'] ?? '0');
$array['sums'][$currencyId]['overspent'] = bcadd($array['sums'][$currencyId]['overspent'], $row['overspent'] ?? '0');
}
}
return $array;
}
/**
* Returns from the collection the budget limit with the indicated currency ID
*
* @param int $currencyId
* @param Collection $budgetLimits
*
* @return BudgetLimit|null
*/
private function budgetLimitInCurrency(int $currencyId, Collection $budgetLimits): ?BudgetLimit
{
return $budgetLimits->first(
static function (BudgetLimit $limit) use ($currencyId) {
return $limit->transaction_currency_id === $currencyId;
}
);
}
}

View File

@ -1,43 +0,0 @@
<?php
/**
* BudgetReportHelperInterface.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Helpers\Report;
use Carbon\Carbon;
use Illuminate\Support\Collection;
/**
* Interface BudgetReportHelperInterface.
*/
interface BudgetReportHelperInterface
{
/**
* Generates the budget report.
*
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts
*
* @return array
*/
public function getBudgetReport(Carbon $start, Carbon $end, Collection $accounts): array;
}

View File

@ -23,10 +23,13 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Report;
use Carbon\Carbon;
use FireflyIII\Helpers\Report\BudgetReportHelperInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\NoBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use FireflyIII\Support\Http\Controllers\BasicDataSupport;
@ -41,8 +44,14 @@ class BudgetController extends Controller
{
use BasicDataSupport;
/** @var BudgetLimitRepositoryInterface */
private $blRepository;
/** @var NoBudgetRepositoryInterface */
private $nbRepository;
/** @var OperationsRepositoryInterface */
private $opsRepository;
/** @var BudgetRepositoryInterface */
private $repository;
/**
* ExpenseReportController constructor.
@ -55,6 +64,9 @@ class BudgetController extends Controller
$this->middleware(
function ($request, $next) {
$this->opsRepository = app(OperationsRepositoryInterface::class);
$this->repository = app(BudgetRepositoryInterface::class);
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
$this->nbRepository = app(NoBudgetRepositoryInterface::class);
return $next($request);
}
@ -184,9 +196,9 @@ class BudgetController extends Controller
$currencyId = $currency['currency_id'];
foreach ($currency['budgets'] as $budget) {
foreach ($budget['transaction_journals'] as $journal) {
$destinationId = $journal['destination_account_id'];
$key = sprintf('%d-%d', $destinationId, $currency['currency_id']);
$result[$key] = $result[$key] ?? [
$destinationId = $journal['destination_account_id'];
$key = sprintf('%d-%d', $destinationId, $currency['currency_id']);
$result[$key] = $result[$key] ?? [
'transactions' => 0,
'sum' => '0',
'avg' => '0',
@ -260,10 +272,12 @@ class BudgetController extends Controller
// add currency info to report array:
$report[$budgetId]['currencies'][$currencyId] = $report[$budgetId]['currencies'][$currencyId] ?? [
'sum' => '0',
'sum_pct' => '0',
'currency_id' => $currency['currency_id'],
'currency_symbol' => $currency['currency_symbol'],
'currency_name' => $currency['currency_name'],
'currency_decimal_places' => $currency['currency_decimal_places'],
];
$report[$budgetId]['currencies'][$currencyId]['sum'] = bcadd($report[$budgetId]['currencies'][$currencyId]['sum'], $journal['amount']);
$sums[$currencyId]['sum'] = bcadd($sums[$currencyId]['sum'], $journal['amount']);
@ -271,6 +285,20 @@ class BudgetController extends Controller
}
}
// loop again to get percentages.
foreach ($report as $budgetId => $data) {
foreach ($data['currencies'] as $currencyId => $data) {
$sum = $data['sum'] ?? '0';
$total = $sums[$currencyId]['sum'] ?? '0';
$pct = '0';
if (0 !== bccomp($sum, '0') && 0 !== bccomp($total, '9')) {
$pct = round(bcmul(bcdiv($sum, $total), '100'));
}
$report[$budgetId]['currencies'][$currencyId]['sum_pct'] = $pct;
}
}
return view('reports.budget.partials.budgets', compact('sums', 'report'));
}
@ -286,26 +314,136 @@ class BudgetController extends Controller
*/
public function general(Collection $accounts, Carbon $start, Carbon $end)
{
// chart properties for cache:
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('budget-report');
$cache->addProperty($accounts->pluck('id')->toArray());
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
$report = [
'budgets' => [],
'sums' => [],
];
$budgets = $this->repository->getBudgets();
$defaultCurrency = app('amount')->getDefaultCurrency();
/** @var Budget $budget */
foreach ($budgets as $budget) {
$budgetId = $budget->id;
$report['budgets'][$budgetId] = $report['budgets'][$budgetId] ?? [
'budget_id' => $budgetId,
'budget_name' => $budget->name,
'no_budget' => false,
'budget_limits' => [],
];
// get all budget limits for budget in period:
$limits = $this->blRepository->getBudgetLimits($budget, $start, $end);
/** @var BudgetLimit $limit */
foreach ($limits as $limit) {
$limitId = $limit->id;
$currency = $limit->transactionCurrency ?? $defaultCurrency;
$expenses = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, $accounts, new Collection([$budget]));
$spent = $expenses[$currency->id]['sum'] ?? '0';
$left = -1 === bccomp(bcadd($limit->amount, $spent), '0') ? '0' : bcadd($limit->amount, $spent);
$overspent = 1 === bccomp(bcmul($spent, '-1'), $limit->amount) ? bcadd($spent, $limit->amount) : '0';
$report['budgets'][$budgetId]['budget_limits'][$limitId] = $report['budgets'][$budgetId]['budget_limits'][$limitId] ?? [
'budget_limit_id' => $limitId,
'start_date' => $limit->start_date,
'end_date' => $limit->end_date,
'budgeted' => $limit->amount,
'budgeted_pct' => '0',
'spent' => $spent,
'spent_pct' => '0',
'left' => $left,
'overspent' => $overspent,
'currency_id' => $currency->id,
'currency_code' => $currency->code,
'currency_name' => $currency->name,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
];
// make sum information:
$report['sums'][$currency->id] = $report['sums'][$currency->id] ?? [
'budgeted' => '0',
'spent' => '0',
'left' => '0',
'overspent' => '0',
'currency_id' => $currency->id,
'currency_code' => $currency->code,
'currency_name' => $currency->name,
'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places,
];
$report['sums'][$currency->id]['budgeted'] = bcadd($report['sums'][$currency->id]['budgeted'], $limit->amount);
$report['sums'][$currency->id]['spent'] = bcadd($report['sums'][$currency->id]['spent'], $spent);
$report['sums'][$currency->id]['left'] = bcadd($report['sums'][$currency->id]['left'], bcadd($limit->amount, $spent));
$report['sums'][$currency->id]['overspent'] = bcadd($report['sums'][$currency->id]['overspent'], $overspent);
}
}
$helper = app(BudgetReportHelperInterface::class);
$budgets = $helper->getBudgetReport($start, $end, $accounts);
try {
$result = view('reports.partials.budgets', compact('budgets'))->render();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
Log::debug(sprintf('Could not render reports.partials.budgets: %s', $e->getMessage()));
$result = 'Could not render view.';
// add no budget info.
$report['budgets'][0] = $report['budgets'][0] ?? [
'budget_id' => null,
'budget_name' => null,
'no_budget' => true,
'budget_limits' => [],
];
$noBudget = $this->nbRepository->sumExpenses($start, $end);
foreach ($noBudget as $noBudgetEntry) {
$report['budgets'][0]['budget_limits'][] = [
'budget_limit_id' => null,
'start_date' => $start,
'end_date' => $end,
'budgeted' => '0',
'budgeted_pct' => '0',
'spent' => $noBudgetEntry['sum'],
'spent_pct' => '0',
'left' => '0',
'overspent' => '0',
'currency_id' => $noBudgetEntry['currency_id'],
'currency_code' => $noBudgetEntry['currency_code'],
'currency_name' => $noBudgetEntry['currency_name'],
'currency_symbol' => $noBudgetEntry['currency_symbol'],
'currency_decimal_places' => $noBudgetEntry['currency_decimal_places'],
];
$report['sums'][$noBudgetEntry['currency_id']]['spent'] = bcadd($report['sums'][$noBudgetEntry['currency_id']]['spent'], $noBudgetEntry['sum']);
}
// make percentages based on total amount.
foreach ($report['budgets'] as $budgetId => $data) {
foreach ($data['budget_limits'] as $limitId => $entry) {
$currencyId = $entry['currency_id'];
$spent = $entry['spent'];
$totalSpent = $report['sums'][$currencyId]['spent'] ?? '0';
$spentPct = '0';
$budgeted = $entry['budgeted'];
$totalBudgeted = $report['sums'][$currencyId]['budgeted'] ?? '0';;
$budgetedPct = '0';
if (0 !== bccomp($spent, '0') && 0 !== bccomp($totalSpent, '0')) {
$spentPct = round(bcmul(bcdiv($spent, $totalSpent), '100'));
}
if (0 !== bccomp($budgeted, '0') && 0 !== bccomp($totalBudgeted, '0')) {
$budgetedPct = round(bcmul(bcdiv($budgeted, $totalBudgeted), '100'));
}
$report['budgets'][$budgetId]['budget_limits'][$limitId]['spent_pct'] = $spentPct;
$report['budgets'][$budgetId]['budget_limits'][$limitId]['budgeted_pct'] = $budgetedPct;
}
}
// var_dump($noBudget);
//
//
// echo '<pre>';
// print_r($report);
// exit;
// try {
$result = view('reports.partials.budgets', compact('report'))->render();
// @codeCoverageIgnoreStart
// } catch (Throwable $e) {
// Log::debug(sprintf('Could not render reports.partials.budgets: %s', $e->getMessage()));
// $result = 'Could not render view.';
// }
// @codeCoverageIgnoreEnd
$cache->store($result);
return $result;
}

View File

@ -33,8 +33,6 @@ use FireflyIII\Helpers\Help\Help;
use FireflyIII\Helpers\Help\HelpInterface;
use FireflyIII\Helpers\Report\BalanceReportHelper;
use FireflyIII\Helpers\Report\BalanceReportHelperInterface;
use FireflyIII\Helpers\Report\BudgetReportHelper;
use FireflyIII\Helpers\Report\BudgetReportHelperInterface;
use FireflyIII\Helpers\Report\NetWorth;
use FireflyIII\Helpers\Report\NetWorthInterface;
use FireflyIII\Helpers\Report\PopupReport;
@ -189,7 +187,6 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind(ReportHelperInterface::class, ReportHelper::class);
$this->app->bind(FiscalHelperInterface::class, FiscalHelper::class);
$this->app->bind(BalanceReportHelperInterface::class, BalanceReportHelper::class);
$this->app->bind(BudgetReportHelperInterface::class, BudgetReportHelper::class);
$class = (string)config(sprintf('firefly.cer_providers.%s', (string)config('firefly.cer_provider')));
if ('' === $class) {
throw new FireflyException('Invalid currency exchange rate provider. Cannot continue.');

View File

@ -36,6 +36,7 @@ return [
'currentBalance' => 'Current balance',
'linked_to_rules' => 'Relevant rules',
'active' => 'Is active?',
'percentage' => 'pct.',
'transaction_type' => 'Type',
'lastActivity' => 'Last activity',
'balanceDiff' => 'Balance difference',

View File

@ -3,6 +3,7 @@
<tr>
<th data-defaultsign="az">{{ 'name'|_ }}</th>
<th data-defaultsign="_19" style="text-align: right;">{{ 'spent'|_ }}</th>
<th data-defaultsign="_19">{{ trans('list.percentage') }}</th>
</tr>
</thead>
<tbody>
@ -13,6 +14,7 @@
<a href="{{ route('budgets.show', budget.id) }}" title="{{ budget.name }}">{{ budget.name }}</a>
</td>
<td style="text-align: right;">&mdash;</td>
<td>&nbsp;</td>
</tr>
{% endif %}
{% for currency in budget.currencies %}
@ -23,6 +25,7 @@
<td data-value="{{ currency.sum }}" style="text-align: right;">
{{ formatAmountBySymbol(currency.sum, currency.currency_symbol, currency.currency_decimal_places) }}
</td>
<td data-value="{{ currency.sum_pct }}">{{ currency.sum_pct }}%</td>
</tr>
{% endfor %}
{% endfor %}
@ -34,6 +37,7 @@
<td style="text-align: right;">
{{ formatAmountBySymbol(sum.sum, sum.currency_symbol, sum.currency_decimal_places) }}
</td>
<td>&nbsp;</td>
</tr>
{% endfor %}
</tfoot>

View File

@ -4,147 +4,110 @@
<th data-defaultsign="az">{{ 'budget'|_ }}</th>
<th data-defaultsign="month" class="hidden-xs">{{ 'date'|_ }}</th>
<th data-defaultsign="_19" style="text-align: right;" class="hidden-xs">{{ 'budgeted'|_ }}</th>
<th data-defaultsign="_19" class="hidden-xs">{{ trans('list.percentage') }}</th>
<th data-defaultsign="_19" style="text-align: right;">{{ 'spent'|_ }}</th>
<th data-defaultsign="_19" class="hidden-xs">{{ trans('list.percentage') }}</th>
<th data-defaultsort="disabled" class="hidden-xs">&nbsp;</th>
<th data-defaultsign="_19" style="text-align: right;" class="hidden-xs">{{ 'left'|_ }}</th>
<th data-defaultsign="_19" style="text-align: right;">{{ 'overspent'|_ }}</th>
</tr>
</thead>
<tbody>
{% for budget in budgets.budgets %}
{% for row in budget.rows %}
{% for budget in report.budgets %}
{% for budget_limit in budget.budget_limits %}
<tr>
<!-- budget name, always visible -->
{% if budget.no_budget %}
<td data-value="zzz">
<em>{{ 'no_budget'|_ }} ({{ row.currency_name }})</em>
<em>{{ 'no_budget'|_ }} ({{ budget_limit.currency_name }})</em>
</td>
{% else %}
<td data-value="{{ budget.budget_name }}">
<a href="{{ route('budgets.show',budget.budget_id) }}">{{ budget.budget_name }}</a>
<a href="{{ route('budgets.show', [budget.budget_id]) }}">{{ budget.budget_name }}</a>
</td>
{% endif %}
<!-- date, hidden on mobile -->
<td class="hidden-xs" data-value="{{ row.start_date.format('Y-m-d')|default('0000-00-00') }}">
{% if null != row.limit_id %}
<a href="{{ route('budgets.show.limit', [budget.budget_id, row.limit_id]) }}">
{{ row.start_date.formatLocalized(monthAndDayFormat) }}
<td class="hidden-xs" data-value="{{ budget_limit.start_date.format('Y-m-d')|default('0000-00-00') }}">
{% if null != budget_limit.budget_limit_id %}
<a href="{{ route('budgets.show.limit', [budget.budget_id, budget_limit.budget_limit_id]) }}">
{{ budget_limit.start_date.formatLocalized(monthAndDayFormat) }}
&mdash;
{{ row.end_date.formatLocalized(monthAndDayFormat) }}
{{ budget_limit.end_date.formatLocalized(monthAndDayFormat) }}
</a>
{% endif %}
</td>
<!-- budgeted, hidden on mobile -->
<td data-value="{{ row.budgeted|default(0) }}" style="text-align: right;" class="hidden-xs">
{% if null != row.budgeted %}
{{ formatAmountBySymbol(row.budgeted, row.currency_symbol, row.currency_decimal_places) }}
<td data-value="{{ budget_limit.budgeted|default(0) }}" style="text-align: right;" class="hidden-xs">
{% if null != budget_limit.budgeted %}
{{ formatAmountBySymbol(budget_limit.budgeted, budget_limit.currency_symbol, budget_limit.currency_decimal_places) }}
{% endif %}
</td>
<!-- percentage, hidden -->
<td data-value="{{ budget_limit.budgeted_pct|default(0) }}" class="hidden-xs">
{{ budget_limit.budgeted_pct }}%
</td>
<!-- spent, visible on mobile -->
<td data-value="{{ row.spent|default(0) }}" style="text-align: right;">
{{ formatAmountBySymbol(row.spent, row.currency_symbol, row.currency_decimal_places) }}
<td data-value="{{ budget_limit.spent|default(0) }}" style="text-align: right;">
{{ formatAmountBySymbol(budget_limit.spent, budget_limit.currency_symbol, budget_limit.currency_decimal_places) }}
</td>
<!-- percentage, hidden -->
<td data-value="{{ budget_limit.spent_pct|default(0) }}" class="hidden-xs">
{{ budget_limit.spent_pct }}%
</td>
<!-- info button, not visible on mobile -->
<td class="hidden-xs">
{% if row.spent != 0 %}
{% if budget_limit.spent != 0 %}
<i class="fa fa-fw text-muted fa-info-circle firefly-info-button"
data-location="budget-spent-amount" data-currency-id="{{ row.currency_id }}" data-budget-id="{{ budget.budget_id }}"></i>
data-location="budget-spent-amount" data-currency-id="{{ budget_limit.currency_id }}" data-budget-id="{{ budget.budget_id }}"></i>
{% endif %}
</td>
<!-- left, hidden on mobile -->
<td data-value="{{ row.left|default(0) }}" style="text-align: right;" class="hidden-xs">
{% if null != row.left %}
{{ formatAmountBySymbol(row.left, row.currency_symbol, row.currency_decimal_places) }}
<td data-value="{{ budget_limit.left|default(0) }}" style="text-align: right;" class="hidden-xs">
{% if null != budget_limit.left %}
{{ formatAmountBySymbol(budget_limit.left, budget_limit.currency_symbol, budget_limit.currency_decimal_places) }}
{% endif %}
</td>
<!-- overspent, visible. -->
<td data-value="{{ row.overspent|default(0) }}" style="text-align: right;">
{% if null != row.overspent %}
{{ formatAmountBySymbol(row.overspent, row.currency_symbol, row.currency_decimal_places) }}
<td data-value="{{ budget_limit.overspent|default(0) }}" style="text-align: right;">
{% if null != budget_limit.overspent %}
{{ formatAmountBySymbol(budget_limit.overspent, budget_limit.currency_symbol, budget_limit.currency_decimal_places) }}
{% endif %}
</td>
</tr>
{% endfor %}
{#
{% set sum_budgeted = sum_budgeted + line.budgeted %}
{% set sum_spent = sum_spent + line.spent %}
{% set sum_left = sum_left + line.left %}
{% set sum_overspent = sum_overspent + line.overspent %}
<tr>
<!-- Budget name, always visible -->
{% if line.type == 'no-budget' %}
<td data-value="zzzzzzz">
<em>{{ 'no_budget'|_ }}</em>
</td>
{% else %}
<td data-value="{{ line.name }}">
<a href="{{ route('budgets.show',line.id) }}">{{ line.name }}</a>
</td>
{% endif %}
<!-- date, hidden on mobile -->
{% if line.type == 'budget-line' %}
<td class="hidden-xs" data-value="{{ line.start.format('Y-m-d') }}">
<a href="{{ route('budgets.show.limit', [line.id, line.limit]) }}">
{{ line.start.formatLocalized(monthAndDayFormat) }}
&mdash;
{{ line.end.formatLocalized(monthAndDayFormat) }}
</a>
</td>
{% else %}
<td data-value="0000-00-00" class="hidden-xs">
</td>
{% endif %}
<!-- budgeted, hidden on mobile -->
<td data-value="{{ line.budgeted }}" style="text-align: right;" class="hidden-xs">
{{ line.budgeted|formatAmount }}
</td>
<!-- spent, visible on mobile -->
<td data-value="{{ line.spent }}" style="text-align: right;">
{{ line.spent|formatAmount }}
</td>
<!-- info button, not visible on mobile -->
<td class="hidden-xs">
{% if line.spent != 0 %}
<i class="fa fa-fw text-muted fa-info-circle firefly-info-button"
data-location="budget-spent-amount" data-budget-id="{{ line.id }}"></i>
{% endif %}
</td>
<!-- left, hidden on mobile -->
<td data-value="{{ line.left }}" style="text-align: right;" class="hidden-xs">
{{ line.left|formatAmount }}
</td>
<!-- overspent, visible. -->
<td data-value="{{ line.overspent }}" style="text-align: right;">
{{ line.overspent|formatAmount }}
</td>
#}
</tr>
{% endfor %}
</tbody>
<tfoot>
{% for sum in budgets.sums %}
{% for sum in report.sums %}
<tr>
<td colspan="2"><em>{{ 'sum'|_ }} ({{ sum.currency_name }})</em></td>
<td style="text-align: right;">{{ formatAmountBySymbol(sum.budgeted, sum.currency_symbol, sum.decimal_places) }}</td>
<td style="text-align: right;">{{ formatAmountBySymbol(sum.spent, sum.currency_symbol, sum.decimal_places) }}</td>
<td style="text-align: right;">{{ formatAmountBySymbol(sum.budgeted, sum.currency_symbol, sum.currency_decimal_places) }}</td>
<td>&nbsp;</td>
<td style="text-align: right;">{{ formatAmountBySymbol(sum.left, sum.currency_symbol, sum.decimal_places) }}</td>
<td style="text-align: right;">{{ formatAmountBySymbol(sum.overspent, sum.currency_symbol, sum.decimal_places) }}</td>
<td style="text-align: right;">{{ formatAmountBySymbol(sum.spent, sum.currency_symbol, sum.currency_decimal_places) }}</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td style="text-align: right;">{{ formatAmountBySymbol(sum.left, sum.currency_symbol, sum.currency_decimal_places) }}</td>
<td style="text-align: right;">{{ formatAmountBySymbol(sum.overspent, sum.currency_symbol, sum.currency_decimal_places) }}</td>
</tr>
{% endfor %}
{% endfor %}
{#<tr>
<td>&nbsp;</td>
</tr>
#}
{#
<tr>
<!-- title, visible -->

View File

@ -25,7 +25,6 @@ namespace Tests\Feature\Controllers\Report;
use Amount;
use Carbon\Carbon;
use FireflyIII\Helpers\Fiscal\FiscalHelperInterface;
use FireflyIII\Helpers\Report\BudgetReportHelperInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Support\Collection;
use Log;
@ -58,7 +57,6 @@ class BudgetControllerTest extends TestCase
{
$this->mockDefaultSession();
$return = [];
$helper = $this->mock(BudgetReportHelperInterface::class);
$fiscalHelper = $this->mock(FiscalHelperInterface::class);
$date = new Carbon;
@ -66,7 +64,6 @@ class BudgetControllerTest extends TestCase
//Amount::shouldReceive('formatAnything')->atLeast()->once()->andReturn('x');
$fiscalHelper->shouldReceive('endOfFiscalYear')->atLeast()->once()->andReturn($date);
$fiscalHelper->shouldReceive('startOfFiscalYear')->atLeast()->once()->andReturn($date);
$helper->shouldReceive('getBudgetReport')->andReturn($return);
$this->be($this->user());
$response = $this->get(route('report-data.budget.general', ['1', '20120101', '20120131']));