mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Fix #2383
This commit is contained in:
parent
2bff6b49e6
commit
5c468e1c49
@ -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;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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.');
|
||||
|
@ -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',
|
||||
|
@ -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;">—</td>
|
||||
<td> </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> </td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tfoot>
|
||||
|
@ -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"> </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) }}
|
||||
—
|
||||
{{ 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) }}
|
||||
—
|
||||
{{ 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> </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> </td>
|
||||
<td> </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> </td>
|
||||
|
||||
|
||||
</tr>
|
||||
#}
|
||||
{#
|
||||
<tr>
|
||||
<!-- title, visible -->
|
||||
|
@ -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']));
|
||||
|
Loading…
Reference in New Issue
Block a user