mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Refactor budget controller.
This commit is contained in:
parent
6bc772d640
commit
b8699422c8
@ -95,8 +95,6 @@ class BudgetLimitController extends Controller
|
|||||||
{
|
{
|
||||||
$manager = new Manager;
|
$manager = new Manager;
|
||||||
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
$baseUrl = $request->getSchemeAndHttpHost() . '/api/v1';
|
||||||
$start = null;
|
|
||||||
$end = null;
|
|
||||||
$budgetId = (int)($request->get('budget_id') ?? 0);
|
$budgetId = (int)($request->get('budget_id') ?? 0);
|
||||||
$budget = $this->repository->findNull($budgetId);
|
$budget = $this->repository->findNull($budgetId);
|
||||||
$this->parameters->set('budget_id', $budgetId);
|
$this->parameters->set('budget_id', $budgetId);
|
||||||
@ -119,9 +117,11 @@ class BudgetLimitController extends Controller
|
|||||||
|
|
||||||
$collection = new Collection;
|
$collection = new Collection;
|
||||||
if (null === $budget) {
|
if (null === $budget) {
|
||||||
|
/** @noinspection PhpUndefinedVariableInspection */
|
||||||
$collection = $this->repository->getAllBudgetLimits($start, $end);
|
$collection = $this->repository->getAllBudgetLimits($start, $end);
|
||||||
}
|
}
|
||||||
if (null !== $budget) {
|
if (null !== $budget) {
|
||||||
|
/** @noinspection PhpUndefinedVariableInspection */
|
||||||
$collection = $this->repository->getBudgetLimits($budget, $start, $end);
|
$collection = $this->repository->getBudgetLimits($budget, $start, $end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +40,9 @@ use Preferences;
|
|||||||
use View;
|
use View;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Class ShowController
|
* Class ShowController
|
||||||
|
*
|
||||||
|
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||||
*/
|
*/
|
||||||
class ShowController extends Controller
|
class ShowController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -43,6 +43,8 @@ use View;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BillController.
|
* Class BillController.
|
||||||
|
*
|
||||||
|
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||||
*/
|
*/
|
||||||
class BillController extends Controller
|
class BillController extends Controller
|
||||||
{
|
{
|
||||||
@ -298,6 +300,9 @@ class BillController extends Controller
|
|||||||
* @param BillFormRequest $request
|
* @param BillFormRequest $request
|
||||||
*
|
*
|
||||||
* @return RedirectResponse
|
* @return RedirectResponse
|
||||||
|
*
|
||||||
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||||
|
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||||
*/
|
*/
|
||||||
public function store(BillFormRequest $request): RedirectResponse
|
public function store(BillFormRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
@ -316,7 +321,6 @@ class BillController extends Controller
|
|||||||
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
|
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
|
||||||
$this->attachments->saveAttachmentsForModel($bill, $files);
|
$this->attachments->saveAttachmentsForModel($bill, $files);
|
||||||
|
|
||||||
// flash messages
|
|
||||||
if (\count($this->attachments->getMessages()->get('attachments')) > 0) {
|
if (\count($this->attachments->getMessages()->get('attachments')) > 0) {
|
||||||
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore
|
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
|
276
app/Http/Controllers/Budget/AmountController.php
Normal file
276
app/Http/Controllers/Budget/AmountController.php
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* AmountController.php
|
||||||
|
* Copyright (c) 2018 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\Http\Controllers\Budget;
|
||||||
|
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
use FireflyIII\Http\Requests\BudgetIncomeRequest;
|
||||||
|
use FireflyIII\Models\Budget;
|
||||||
|
use FireflyIII\Models\TransactionType;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Support\CacheProperties;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Log;
|
||||||
|
use Preferences;
|
||||||
|
use View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class AmountController
|
||||||
|
*/
|
||||||
|
class AmountController extends Controller
|
||||||
|
{
|
||||||
|
/** @var BudgetRepositoryInterface */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
View::share('hideBudgets', true);
|
||||||
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
app('view')->share('title', trans('firefly.budgets'));
|
||||||
|
app('view')->share('mainTitleIcon', 'fa-tasks');
|
||||||
|
$this->repository = app(BudgetRepositoryInterface::class);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param BudgetRepositoryInterface $repository
|
||||||
|
* @param Budget $budget
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function amount(Request $request, BudgetRepositoryInterface $repository, Budget $budget): JsonResponse
|
||||||
|
{
|
||||||
|
$amount = (string)$request->get('amount');
|
||||||
|
$start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
|
||||||
|
$end = Carbon::createFromFormat('Y-m-d', $request->get('end'));
|
||||||
|
$budgetLimit = $this->repository->updateLimitAmount($budget, $start, $end, $amount);
|
||||||
|
$largeDiff = false;
|
||||||
|
$warnText = '';
|
||||||
|
$days = 0;
|
||||||
|
$daysInMonth = 0;
|
||||||
|
if (0 === bccomp($amount, '0')) {
|
||||||
|
$budgetLimit = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if today is between start and end, use the diff in days between end and today (days left)
|
||||||
|
// otherwise, use diff between start and end.
|
||||||
|
$today = new Carbon;
|
||||||
|
Log::debug(sprintf('Start is %s, end is %s, today is %s', $start->format('Y-m-d'), $end->format('Y-m-d'), $today->format('Y-m-d')));
|
||||||
|
if ($today->gte($start) && $today->lte($end)) {
|
||||||
|
$days = $end->diffInDays($today);
|
||||||
|
$daysInMonth = $start->diffInDays($today);
|
||||||
|
}
|
||||||
|
if ($today->lte($start) || $today->gte($end)) {
|
||||||
|
$days = $start->diffInDays($end);
|
||||||
|
$daysInMonth = $start->diffInDays($end);
|
||||||
|
}
|
||||||
|
$days = 0 === $days ? 1 : $days;
|
||||||
|
$daysInMonth = 0 === $daysInMonth ? 1 : $daysInMonth;
|
||||||
|
|
||||||
|
// calculate left in budget:
|
||||||
|
$spent = $repository->spentInPeriod(new Collection([$budget]), new Collection, $start, $end);
|
||||||
|
$currency = app('amount')->getDefaultCurrency();
|
||||||
|
$left = app('amount')->formatAnything($currency, bcadd($amount, $spent), true);
|
||||||
|
$leftPerDay = 'none';
|
||||||
|
|
||||||
|
// is user has money left, calculate.
|
||||||
|
if (1 === bccomp(bcadd($amount, $spent), '0')) {
|
||||||
|
$leftPerDay = app('amount')->formatAnything($currency, bcdiv(bcadd($amount, $spent), (string)$days), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// over or under budgeting, compared to previous budgets?
|
||||||
|
$average = $this->repository->budgetedPerDay($budget);
|
||||||
|
// current average per day:
|
||||||
|
$diff = $start->diffInDays($end);
|
||||||
|
$current = $amount;
|
||||||
|
if ($diff > 0) {
|
||||||
|
$current = bcdiv($amount, (string)$diff);
|
||||||
|
}
|
||||||
|
if (bccomp(bcmul('1.1', $average), $current) === -1) {
|
||||||
|
$largeDiff = true;
|
||||||
|
$warnText = (string)trans(
|
||||||
|
'firefly.over_budget_warn',
|
||||||
|
[
|
||||||
|
'amount' => app('amount')->formatAnything($currency, $average, false),
|
||||||
|
'over_amount' => app('amount')->formatAnything($currency, $current, false),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
app('preferences')->mark();
|
||||||
|
|
||||||
|
return response()->json(
|
||||||
|
[
|
||||||
|
'left' => $left,
|
||||||
|
'name' => $budget->name,
|
||||||
|
'limit' => $budgetLimit ? $budgetLimit->id : 0,
|
||||||
|
'amount' => $amount,
|
||||||
|
'current' => $current,
|
||||||
|
'average' => $average,
|
||||||
|
'large_diff' => $largeDiff,
|
||||||
|
'left_per_day' => $leftPerDay,
|
||||||
|
'warn_text' => $warnText,
|
||||||
|
'daysInMonth' => $daysInMonth,
|
||||||
|
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function infoIncome(Carbon $start, Carbon $end)
|
||||||
|
{
|
||||||
|
// properties for cache
|
||||||
|
$cache = new CacheProperties;
|
||||||
|
$cache->addProperty($start);
|
||||||
|
$cache->addProperty($end);
|
||||||
|
$cache->addProperty('info-income');
|
||||||
|
|
||||||
|
Log::debug(sprintf('infoIncome start is %s', $start->format('Y-m-d')));
|
||||||
|
Log::debug(sprintf('infoIncome end is %s', $end->format('Y-m-d')));
|
||||||
|
|
||||||
|
if ($cache->has()) {
|
||||||
|
// @codeCoverageIgnoreStart
|
||||||
|
$result = $cache->get();
|
||||||
|
|
||||||
|
return view('budgets.info', compact('result'));
|
||||||
|
// @codeCoverageIgnoreEnd
|
||||||
|
}
|
||||||
|
$result = [
|
||||||
|
'available' => '0',
|
||||||
|
'earned' => '0',
|
||||||
|
'suggested' => '0',
|
||||||
|
];
|
||||||
|
$currency = app('amount')->getDefaultCurrency();
|
||||||
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
|
/** @var Carbon $begin */
|
||||||
|
$begin = app('navigation')->subtractPeriod($start, $range, 3);
|
||||||
|
|
||||||
|
Log::debug(sprintf('Range is %s', $range));
|
||||||
|
Log::debug(sprintf('infoIncome begin is %s', $begin->format('Y-m-d')));
|
||||||
|
|
||||||
|
// get average amount available.
|
||||||
|
$total = '0';
|
||||||
|
$count = 0;
|
||||||
|
$currentStart = clone $begin;
|
||||||
|
while ($currentStart < $start) {
|
||||||
|
|
||||||
|
Log::debug(sprintf('Loop: currentStart is %s', $currentStart->format('Y-m-d')));
|
||||||
|
$currentEnd = app('navigation')->endOfPeriod($currentStart, $range);
|
||||||
|
$total = bcadd($total, $this->repository->getAvailableBudget($currency, $currentStart, $currentEnd));
|
||||||
|
$currentStart = app('navigation')->addPeriod($currentStart, $range, 0);
|
||||||
|
++$count;
|
||||||
|
}
|
||||||
|
Log::debug('Loop end');
|
||||||
|
|
||||||
|
if (0 === $count) {
|
||||||
|
$count = 1;
|
||||||
|
}
|
||||||
|
$result['available'] = bcdiv($total, (string)$count);
|
||||||
|
|
||||||
|
// amount earned in this period:
|
||||||
|
$subDay = clone $end;
|
||||||
|
$subDay->subDay();
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class);
|
||||||
|
$collector->setAllAssetAccounts()->setRange($begin, $subDay)->setTypes([TransactionType::DEPOSIT])->withOpposingAccount();
|
||||||
|
$result['earned'] = bcdiv((string)$collector->getJournals()->sum('transaction_amount'), (string)$count);
|
||||||
|
|
||||||
|
// amount spent in period
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class);
|
||||||
|
$collector->setAllAssetAccounts()->setRange($begin, $subDay)->setTypes([TransactionType::WITHDRAWAL])->withOpposingAccount();
|
||||||
|
$result['spent'] = bcdiv((string)$collector->getJournals()->sum('transaction_amount'), (string)$count);
|
||||||
|
// suggestion starts with the amount spent
|
||||||
|
$result['suggested'] = bcmul($result['spent'], '-1');
|
||||||
|
$result['suggested'] = 1 === bccomp($result['suggested'], $result['earned']) ? $result['earned'] : $result['suggested'];
|
||||||
|
// unless it's more than you earned. So min() of suggested/earned
|
||||||
|
|
||||||
|
$cache->store($result);
|
||||||
|
|
||||||
|
return view('budgets.info', compact('result', 'begin', 'currentEnd'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param BudgetIncomeRequest $request
|
||||||
|
*
|
||||||
|
* @return RedirectResponse
|
||||||
|
*/
|
||||||
|
public function postUpdateIncome(BudgetIncomeRequest $request): RedirectResponse
|
||||||
|
{
|
||||||
|
$start = Carbon::createFromFormat('Y-m-d', $request->string('start'));
|
||||||
|
$end = Carbon::createFromFormat('Y-m-d', $request->string('end'));
|
||||||
|
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||||
|
$amount = $request->get('amount');
|
||||||
|
$page = 0 === $request->integer('page') ? 1 : $request->integer('page');
|
||||||
|
$this->repository->cleanupBudgets();
|
||||||
|
$this->repository->setAvailableBudget($defaultCurrency, $start, $end, $amount);
|
||||||
|
app('preferences')->mark();
|
||||||
|
|
||||||
|
return redirect(route('budgets.index', [$start->format('Y-m-d')]) . '?page=' . $page);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function updateIncome(Request $request, Carbon $start, Carbon $end)
|
||||||
|
{
|
||||||
|
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||||
|
$available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end);
|
||||||
|
$available = round($available, $defaultCurrency->decimal_places);
|
||||||
|
$page = (int)$request->get('page');
|
||||||
|
|
||||||
|
return view('budgets.income', compact('available', 'start', 'end', 'page'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
106
app/Http/Controllers/Budget/CreateController.php
Normal file
106
app/Http/Controllers/Budget/CreateController.php
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* CreateController.php
|
||||||
|
* Copyright (c) 2018 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\Http\Controllers\Budget;
|
||||||
|
|
||||||
|
|
||||||
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
use FireflyIII\Http\Requests\BudgetFormRequest;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CreateController
|
||||||
|
*/
|
||||||
|
class CreateController extends Controller
|
||||||
|
{
|
||||||
|
/** @var BudgetRepositoryInterface */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
View::share('hideBudgets', true);
|
||||||
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
app('view')->share('title', trans('firefly.budgets'));
|
||||||
|
app('view')->share('mainTitleIcon', 'fa-tasks');
|
||||||
|
$this->repository = app(BudgetRepositoryInterface::class);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function create(Request $request)
|
||||||
|
{
|
||||||
|
// put previous url in session if not redirect from store (not "create another").
|
||||||
|
if (true !== session('budgets.create.fromStore')) {
|
||||||
|
$this->rememberPreviousUri('budgets.create.uri');
|
||||||
|
}
|
||||||
|
$request->session()->forget('budgets.create.fromStore');
|
||||||
|
$subTitle = (string)trans('firefly.create_new_budget');
|
||||||
|
|
||||||
|
return view('budgets.create', compact('subTitle'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param BudgetFormRequest $request
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function store(BudgetFormRequest $request): RedirectResponse
|
||||||
|
{
|
||||||
|
$data = $request->getBudgetData();
|
||||||
|
$budget = $this->repository->store($data);
|
||||||
|
$this->repository->cleanupBudgets();
|
||||||
|
$request->session()->flash('success', (string)trans('firefly.stored_new_budget', ['name' => $budget->name]));
|
||||||
|
app('preferences')->mark();
|
||||||
|
|
||||||
|
$redirect = redirect($this->getPreviousUri('budgets.create.uri'));
|
||||||
|
|
||||||
|
if (1 === (int)$request->get('create_another')) {
|
||||||
|
// @codeCoverageIgnoreStart
|
||||||
|
$request->session()->put('budgets.create.fromStore', true);
|
||||||
|
|
||||||
|
$redirect = redirect(route('budgets.create'))->withInput();
|
||||||
|
// @codeCoverageIgnoreEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
return $redirect;
|
||||||
|
}
|
||||||
|
}
|
94
app/Http/Controllers/Budget/DeleteController.php
Normal file
94
app/Http/Controllers/Budget/DeleteController.php
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* DeleteController.php
|
||||||
|
* Copyright (c) 2018 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\Http\Controllers\Budget;
|
||||||
|
|
||||||
|
|
||||||
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
use FireflyIII\Models\Budget;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class DeleteController
|
||||||
|
*/
|
||||||
|
class DeleteController extends Controller
|
||||||
|
{
|
||||||
|
/** @var BudgetRepositoryInterface */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
View::share('hideBudgets', true);
|
||||||
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
app('view')->share('title', trans('firefly.budgets'));
|
||||||
|
app('view')->share('mainTitleIcon', 'fa-tasks');
|
||||||
|
$this->repository = app(BudgetRepositoryInterface::class);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Budget $budget
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function delete(Budget $budget)
|
||||||
|
{
|
||||||
|
$subTitle = trans('firefly.delete_budget', ['name' => $budget->name]);
|
||||||
|
|
||||||
|
// put previous url in session
|
||||||
|
$this->rememberPreviousUri('budgets.delete.uri');
|
||||||
|
|
||||||
|
return view('budgets.delete', compact('budget', 'subTitle'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param Budget $budget
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
*/
|
||||||
|
public function destroy(Request $request, Budget $budget)
|
||||||
|
{
|
||||||
|
$name = $budget->name;
|
||||||
|
$this->repository->destroy($budget);
|
||||||
|
$request->session()->flash('success', (string)trans('firefly.deleted_budget', ['name' => $name]));
|
||||||
|
app('preferences')->mark();
|
||||||
|
|
||||||
|
return redirect($this->getPreviousUri('budgets.delete.uri'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
117
app/Http/Controllers/Budget/EditController.php
Normal file
117
app/Http/Controllers/Budget/EditController.php
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* EditController.php
|
||||||
|
* Copyright (c) 2018 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\Http\Controllers\Budget;
|
||||||
|
|
||||||
|
|
||||||
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
use FireflyIII\Http\Requests\BudgetFormRequest;
|
||||||
|
use FireflyIII\Models\Budget;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class EditController
|
||||||
|
*/
|
||||||
|
class EditController extends Controller
|
||||||
|
{
|
||||||
|
/** @var BudgetRepositoryInterface */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
View::share('hideBudgets', true);
|
||||||
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
app('view')->share('title', trans('firefly.budgets'));
|
||||||
|
app('view')->share('mainTitleIcon', 'fa-tasks');
|
||||||
|
$this->repository = app(BudgetRepositoryInterface::class);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param Budget $budget
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function edit(Request $request, Budget $budget)
|
||||||
|
{
|
||||||
|
$subTitle = trans('firefly.edit_budget', ['name' => $budget->name]);
|
||||||
|
|
||||||
|
// code to handle active-checkboxes
|
||||||
|
$hasOldInput = null !== $request->old('_token');
|
||||||
|
$preFilled = [
|
||||||
|
'active' => $hasOldInput ? (bool)$request->old('active') : $budget->active,
|
||||||
|
];
|
||||||
|
|
||||||
|
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||||
|
if (true !== session('budgets.edit.fromUpdate')) {
|
||||||
|
$this->rememberPreviousUri('budgets.edit.uri');
|
||||||
|
}
|
||||||
|
$request->session()->forget('budgets.edit.fromUpdate');
|
||||||
|
$request->session()->flash('preFilled', $preFilled);
|
||||||
|
|
||||||
|
return view('budgets.edit', compact('budget', 'subTitle'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param BudgetFormRequest $request
|
||||||
|
* @param Budget $budget
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function update(BudgetFormRequest $request, Budget $budget): RedirectResponse
|
||||||
|
{
|
||||||
|
$data = $request->getBudgetData();
|
||||||
|
$this->repository->update($budget, $data);
|
||||||
|
|
||||||
|
$request->session()->flash('success', (string)trans('firefly.updated_budget', ['name' => $budget->name]));
|
||||||
|
$this->repository->cleanupBudgets();
|
||||||
|
app('preferences')->mark();
|
||||||
|
|
||||||
|
$redirect = redirect($this->getPreviousUri('budgets.edit.uri'));
|
||||||
|
|
||||||
|
if (1 === (int)$request->get('return_to_edit')) {
|
||||||
|
// @codeCoverageIgnoreStart
|
||||||
|
$request->session()->put('budgets.edit.fromUpdate', true);
|
||||||
|
|
||||||
|
$redirect = redirect(route('budgets.edit', [$budget->id]))->withInput(['return_to_edit' => 1]);
|
||||||
|
// @codeCoverageIgnoreEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
return $redirect;
|
||||||
|
}
|
||||||
|
}
|
174
app/Http/Controllers/Budget/IndexController.php
Normal file
174
app/Http/Controllers/Budget/IndexController.php
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* IndexController.php
|
||||||
|
* Copyright (c) 2018 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\Http\Controllers\Budget;
|
||||||
|
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Exception;
|
||||||
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
|
use Log;
|
||||||
|
use Preferences;
|
||||||
|
use View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class IndexController
|
||||||
|
*/
|
||||||
|
class IndexController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
/** @var BudgetRepositoryInterface */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
View::share('hideBudgets', true);
|
||||||
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
app('view')->share('title', trans('firefly.budgets'));
|
||||||
|
app('view')->share('mainTitleIcon', 'fa-tasks');
|
||||||
|
$this->repository = app(BudgetRepositoryInterface::class);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param string|null $moment
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function index(Request $request, string $moment = null)
|
||||||
|
{
|
||||||
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
|
$start = session('start', new Carbon);
|
||||||
|
$end = session('end', new Carbon);
|
||||||
|
$page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page');
|
||||||
|
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
||||||
|
$days = 0;
|
||||||
|
$daysInMonth = 0;
|
||||||
|
|
||||||
|
// make date if present:
|
||||||
|
if (null !== $moment || '' !== (string)$moment) {
|
||||||
|
try {
|
||||||
|
$start = new Carbon($moment);
|
||||||
|
$end = app('navigation')->endOfPeriod($start, $range);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// start and end are already defined.
|
||||||
|
Log::debug(sprintf('start and end are already defined: %s', $e->getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if today is between start and end, use the diff in days between end and today (days left)
|
||||||
|
// otherwise, use diff between start and end.
|
||||||
|
$today = new Carbon;
|
||||||
|
if ($today->gte($start) && $today->lte($end)) {
|
||||||
|
$days = $end->diffInDays($today);
|
||||||
|
$daysInMonth = $start->diffInDays($today);
|
||||||
|
}
|
||||||
|
if ($today->lte($start) || $today->gte($end)) {
|
||||||
|
$days = $start->diffInDays($end);
|
||||||
|
$daysInMonth = $start->diffInDays($end);
|
||||||
|
}
|
||||||
|
$days = 0 === $days ? 1 : $days;
|
||||||
|
$daysInMonth = 0 === $daysInMonth ? 1 : $daysInMonth;
|
||||||
|
|
||||||
|
|
||||||
|
$next = clone $end;
|
||||||
|
$next->addDay();
|
||||||
|
$prev = clone $start;
|
||||||
|
$prev->subDay();
|
||||||
|
$prev = app('navigation')->startOfPeriod($prev, $range);
|
||||||
|
$this->repository->cleanupBudgets();
|
||||||
|
$allBudgets = $this->repository->getActiveBudgets();
|
||||||
|
$total = $allBudgets->count();
|
||||||
|
$budgets = $allBudgets->slice(($page - 1) * $pageSize, $pageSize);
|
||||||
|
$inactive = $this->repository->getInactiveBudgets();
|
||||||
|
$periodStart = $start->formatLocalized($this->monthAndDayFormat);
|
||||||
|
$periodEnd = $end->formatLocalized($this->monthAndDayFormat);
|
||||||
|
$budgetInformation = $this->repository->collectBudgetInformation($allBudgets, $start, $end);
|
||||||
|
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||||
|
$available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end);
|
||||||
|
$spent = array_sum(array_column($budgetInformation, 'spent'));
|
||||||
|
$budgeted = array_sum(array_column($budgetInformation, 'budgeted'));
|
||||||
|
|
||||||
|
// paginate budgets
|
||||||
|
$budgets = new LengthAwarePaginator($budgets, $total, $pageSize, $page);
|
||||||
|
$budgets->setPath(route('budgets.index'));
|
||||||
|
|
||||||
|
// select thing for last 12 periods:
|
||||||
|
$previousLoop = [];
|
||||||
|
/** @var Carbon $previousDate */
|
||||||
|
$previousDate = clone $start;
|
||||||
|
$count = 0;
|
||||||
|
while ($count < 12) {
|
||||||
|
$previousDate->subDay();
|
||||||
|
$previousDate = app('navigation')->startOfPeriod($previousDate, $range);
|
||||||
|
$format = $previousDate->format('Y-m-d');
|
||||||
|
$previousLoop[$format] = app('navigation')->periodShow($previousDate, $range);
|
||||||
|
++$count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// select thing for next 12 periods:
|
||||||
|
$nextLoop = [];
|
||||||
|
/** @var Carbon $nextDate */
|
||||||
|
$nextDate = clone $end;
|
||||||
|
$nextDate->addDay();
|
||||||
|
$count = 0;
|
||||||
|
|
||||||
|
while ($count < 12) {
|
||||||
|
$format = $nextDate->format('Y-m-d');
|
||||||
|
$nextLoop[$format] = app('navigation')->periodShow($nextDate, $range);
|
||||||
|
$nextDate = app('navigation')->endOfPeriod($nextDate, $range);
|
||||||
|
++$count;
|
||||||
|
$nextDate->addDay();
|
||||||
|
}
|
||||||
|
|
||||||
|
// display info
|
||||||
|
$currentMonth = app('navigation')->periodShow($start, $range);
|
||||||
|
$nextText = app('navigation')->periodShow($next, $range);
|
||||||
|
$prevText = app('navigation')->periodShow($prev, $range);
|
||||||
|
|
||||||
|
return view(
|
||||||
|
'budgets.index', compact(
|
||||||
|
'available', 'currentMonth', 'next', 'nextText', 'prev', 'allBudgets', 'prevText', 'periodStart', 'periodEnd', 'days', 'page',
|
||||||
|
'budgetInformation', 'daysInMonth',
|
||||||
|
'inactive', 'budgets', 'spent', 'budgeted', 'previousLoop', 'nextLoop', 'start', 'end'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
274
app/Http/Controllers/Budget/ShowController.php
Normal file
274
app/Http/Controllers/Budget/ShowController.php
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ShowController.php
|
||||||
|
* Copyright (c) 2018 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\Http\Controllers\Budget;
|
||||||
|
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
use FireflyIII\Models\Budget;
|
||||||
|
use FireflyIII\Models\BudgetLimit;
|
||||||
|
use FireflyIII\Models\TransactionType;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
|
use FireflyIII\Support\CacheProperties;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Preferences;
|
||||||
|
use View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class ShowController
|
||||||
|
*/
|
||||||
|
class ShowController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
/** @var BudgetRepositoryInterface */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
View::share('hideBudgets', true);
|
||||||
|
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
app('view')->share('title', trans('firefly.budgets'));
|
||||||
|
app('view')->share('mainTitleIcon', 'fa-tasks');
|
||||||
|
$this->repository = app(BudgetRepositoryInterface::class);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param JournalRepositoryInterface $repository
|
||||||
|
* @param string|null $moment
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function noBudget(Request $request, JournalRepositoryInterface $repository, string $moment = null)
|
||||||
|
{
|
||||||
|
// default values:
|
||||||
|
$moment = $moment ?? '';
|
||||||
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
|
$start = null;
|
||||||
|
$end = null;
|
||||||
|
$periods = new Collection;
|
||||||
|
|
||||||
|
// prep for "all" view.
|
||||||
|
if ('all' === $moment) {
|
||||||
|
$subTitle = trans('firefly.all_journals_without_budget');
|
||||||
|
$first = $repository->firstNull();
|
||||||
|
$start = null === $first ? new Carbon : $first->date;
|
||||||
|
$end = new Carbon;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prep for "specific date" view.
|
||||||
|
if ('all' !== $moment && \strlen($moment) > 0) {
|
||||||
|
$start = new Carbon($moment);
|
||||||
|
/** @var Carbon $end */
|
||||||
|
$end = app('navigation')->endOfPeriod($start, $range);
|
||||||
|
$subTitle = trans(
|
||||||
|
'firefly.without_budget_between',
|
||||||
|
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||||
|
);
|
||||||
|
$periods = $this->getPeriodOverview();
|
||||||
|
}
|
||||||
|
|
||||||
|
// prep for current period
|
||||||
|
if ('' === $moment) {
|
||||||
|
$start = clone session('start', app('navigation')->startOfPeriod(new Carbon, $range));
|
||||||
|
$end = clone session('end', app('navigation')->endOfPeriod(new Carbon, $range));
|
||||||
|
$periods = $this->getPeriodOverview();
|
||||||
|
$subTitle = trans(
|
||||||
|
'firefly.without_budget_between',
|
||||||
|
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$page = (int)$request->get('page');
|
||||||
|
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
||||||
|
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class);
|
||||||
|
$collector->setAllAssetAccounts()->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setLimit($pageSize)->setPage($page)
|
||||||
|
->withoutBudget()->withOpposingAccount();
|
||||||
|
$transactions = $collector->getPaginatedJournals();
|
||||||
|
$transactions->setPath(route('budgets.no-budget'));
|
||||||
|
|
||||||
|
return view('budgets.no-budget', compact('transactions', 'subTitle', 'moment', 'periods', 'start', 'end'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param Budget $budget
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function show(Request $request, Budget $budget)
|
||||||
|
{
|
||||||
|
/** @var Carbon $start */
|
||||||
|
$start = session('first', Carbon::create()->startOfYear());
|
||||||
|
$end = new Carbon;
|
||||||
|
$page = (int)$request->get('page');
|
||||||
|
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
||||||
|
$limits = $this->getLimits($budget, $start, $end);
|
||||||
|
$repetition = null;
|
||||||
|
|
||||||
|
// collector:
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class);
|
||||||
|
$collector->setAllAssetAccounts()->setRange($start, $end)->setBudget($budget)->setLimit($pageSize)->setPage($page)->withBudgetInformation();
|
||||||
|
$transactions = $collector->getPaginatedJournals();
|
||||||
|
$transactions->setPath(route('budgets.show', [$budget->id]));
|
||||||
|
|
||||||
|
$subTitle = trans('firefly.all_journals_for_budget', ['name' => $budget->name]);
|
||||||
|
|
||||||
|
return view('budgets.show', compact('limits', 'budget', 'repetition', 'transactions', 'subTitle'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param Budget $budget
|
||||||
|
* @param BudgetLimit $budgetLimit
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
public function showByBudgetLimit(Request $request, Budget $budget, BudgetLimit $budgetLimit)
|
||||||
|
{
|
||||||
|
if ($budgetLimit->budget->id !== $budget->id) {
|
||||||
|
throw new FireflyException('This budget limit is not part of this budget.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$page = (int)$request->get('page');
|
||||||
|
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
||||||
|
$subTitle = trans(
|
||||||
|
'firefly.budget_in_period',
|
||||||
|
[
|
||||||
|
'name' => $budget->name,
|
||||||
|
'start' => $budgetLimit->start_date->formatLocalized($this->monthAndDayFormat),
|
||||||
|
'end' => $budgetLimit->end_date->formatLocalized($this->monthAndDayFormat),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// collector:
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class);
|
||||||
|
$collector->setAllAssetAccounts()->setRange($budgetLimit->start_date, $budgetLimit->end_date)
|
||||||
|
->setBudget($budget)->setLimit($pageSize)->setPage($page)->withBudgetInformation();
|
||||||
|
$transactions = $collector->getPaginatedJournals();
|
||||||
|
$transactions->setPath(route('budgets.show', [$budget->id, $budgetLimit->id]));
|
||||||
|
$start = session('first', Carbon::create()->startOfYear());
|
||||||
|
$end = new Carbon;
|
||||||
|
$limits = $this->getLimits($budget, $start, $end);
|
||||||
|
|
||||||
|
return view('budgets.show', compact('limits', 'budget', 'budgetLimit', 'transactions', 'subTitle'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Budget $budget
|
||||||
|
* @param Carbon $start
|
||||||
|
* @param Carbon $end
|
||||||
|
*
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
private function getLimits(Budget $budget, Carbon $start, Carbon $end): Collection
|
||||||
|
{
|
||||||
|
// properties for cache
|
||||||
|
$cache = new CacheProperties;
|
||||||
|
$cache->addProperty($start);
|
||||||
|
$cache->addProperty($end);
|
||||||
|
$cache->addProperty($budget->id);
|
||||||
|
$cache->addProperty('get-limits');
|
||||||
|
|
||||||
|
if ($cache->has()) {
|
||||||
|
return $cache->get(); // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
|
||||||
|
$set = $this->repository->getBudgetLimits($budget, $start, $end);
|
||||||
|
$limits = new Collection();
|
||||||
|
|
||||||
|
/** @var BudgetLimit $entry */
|
||||||
|
foreach ($set as $entry) {
|
||||||
|
$entry->spent = $this->repository->spentInPeriod(new Collection([$budget]), new Collection(), $entry->start_date, $entry->end_date);
|
||||||
|
$limits->push($entry);
|
||||||
|
}
|
||||||
|
$cache->store($limits);
|
||||||
|
|
||||||
|
return $set;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
private function getPeriodOverview(): Collection
|
||||||
|
{
|
||||||
|
/** @var JournalRepositoryInterface $repository */
|
||||||
|
$repository = app(JournalRepositoryInterface::class);
|
||||||
|
$first = $repository->firstNull();
|
||||||
|
$start = null === $first ? new Carbon : $first->date;
|
||||||
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
|
$start = app('navigation')->startOfPeriod($start, $range);
|
||||||
|
$end = app('navigation')->endOfX(new Carbon, $range, null);
|
||||||
|
$entries = new Collection;
|
||||||
|
$cache = new CacheProperties;
|
||||||
|
$cache->addProperty($start);
|
||||||
|
$cache->addProperty($end);
|
||||||
|
$cache->addProperty('no-budget-period-entries');
|
||||||
|
|
||||||
|
if ($cache->has()) {
|
||||||
|
return $cache->get(); // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
||||||
|
foreach ($dates as $date) {
|
||||||
|
/** @var JournalCollectorInterface $collector */
|
||||||
|
$collector = app(JournalCollectorInterface::class);
|
||||||
|
$collector->setAllAssetAccounts()->setRange($date['start'], $date['end'])->withoutBudget()->withOpposingAccount()->setTypes(
|
||||||
|
[TransactionType::WITHDRAWAL]
|
||||||
|
);
|
||||||
|
$set = $collector->getJournals();
|
||||||
|
$sum = (string)($set->sum('transaction_amount') ?? '0');
|
||||||
|
$journals = $set->count();
|
||||||
|
/** @noinspection PhpUndefinedMethodInspection */
|
||||||
|
$dateStr = $date['end']->format('Y-m-d');
|
||||||
|
$dateName = app('navigation')->periodShow($date['end'], $date['period']);
|
||||||
|
$entries->push(['string' => $dateStr, 'name' => $dateName, 'count' => $journals, 'sum' => $sum, 'date' => clone $date['end']]);
|
||||||
|
}
|
||||||
|
$cache->store($entries);
|
||||||
|
|
||||||
|
return $entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,714 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* BudgetController.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\Http\Controllers;
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Exception;
|
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
|
||||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
|
||||||
use FireflyIII\Http\Requests\BudgetFormRequest;
|
|
||||||
use FireflyIII\Http\Requests\BudgetIncomeRequest;
|
|
||||||
use FireflyIII\Models\Budget;
|
|
||||||
use FireflyIII\Models\BudgetLimit;
|
|
||||||
use FireflyIII\Models\TransactionType;
|
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
|
||||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
|
||||||
use FireflyIII\Support\CacheProperties;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
|
||||||
use Illuminate\Http\RedirectResponse;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Log;
|
|
||||||
use Preferences;
|
|
||||||
use View;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class BudgetController.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class BudgetController extends Controller
|
|
||||||
{
|
|
||||||
/** @var BudgetRepositoryInterface */
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
|
|
||||||
View::share('hideBudgets', true);
|
|
||||||
|
|
||||||
$this->middleware(
|
|
||||||
function ($request, $next) {
|
|
||||||
app('view')->share('title', trans('firefly.budgets'));
|
|
||||||
app('view')->share('mainTitleIcon', 'fa-tasks');
|
|
||||||
$this->repository = app(BudgetRepositoryInterface::class);
|
|
||||||
|
|
||||||
return $next($request);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
* @param BudgetRepositoryInterface $repository
|
|
||||||
* @param Budget $budget
|
|
||||||
*
|
|
||||||
* @return JsonResponse
|
|
||||||
*/
|
|
||||||
public function amount(Request $request, BudgetRepositoryInterface $repository, Budget $budget): JsonResponse
|
|
||||||
{
|
|
||||||
$amount = (string)$request->get('amount');
|
|
||||||
$start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
|
|
||||||
$end = Carbon::createFromFormat('Y-m-d', $request->get('end'));
|
|
||||||
$budgetLimit = $this->repository->updateLimitAmount($budget, $start, $end, $amount);
|
|
||||||
$largeDiff = false;
|
|
||||||
$warnText = '';
|
|
||||||
$days = 0;
|
|
||||||
$daysInMonth = 0;
|
|
||||||
if (0 === bccomp($amount, '0')) {
|
|
||||||
$budgetLimit = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if today is between start and end, use the diff in days between end and today (days left)
|
|
||||||
// otherwise, use diff between start and end.
|
|
||||||
$today = new Carbon;
|
|
||||||
Log::debug(sprintf('Start is %s, end is %s, today is %s', $start->format('Y-m-d'), $end->format('Y-m-d'), $today->format('Y-m-d')));
|
|
||||||
if ($today->gte($start) && $today->lte($end)) {
|
|
||||||
$days = $end->diffInDays($today);
|
|
||||||
$daysInMonth = $start->diffInDays($today);
|
|
||||||
}
|
|
||||||
if ($today->lte($start) || $today->gte($end)) {
|
|
||||||
$days = $start->diffInDays($end);
|
|
||||||
$daysInMonth = $start->diffInDays($end);
|
|
||||||
}
|
|
||||||
$days = 0 === $days ? 1 : $days;
|
|
||||||
$daysInMonth = 0 === $daysInMonth ? 1 : $daysInMonth;
|
|
||||||
|
|
||||||
// calculate left in budget:
|
|
||||||
$spent = $repository->spentInPeriod(new Collection([$budget]), new Collection, $start, $end);
|
|
||||||
$currency = app('amount')->getDefaultCurrency();
|
|
||||||
$left = app('amount')->formatAnything($currency, bcadd($amount, $spent), true);
|
|
||||||
$leftPerDay = 'none';
|
|
||||||
|
|
||||||
// is user has money left, calculate.
|
|
||||||
if (1 === bccomp(bcadd($amount, $spent), '0')) {
|
|
||||||
$leftPerDay = app('amount')->formatAnything($currency, bcdiv(bcadd($amount, $spent), (string)$days), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// over or under budgeting, compared to previous budgets?
|
|
||||||
$average = $this->repository->budgetedPerDay($budget);
|
|
||||||
// current average per day:
|
|
||||||
$diff = $start->diffInDays($end);
|
|
||||||
$current = $amount;
|
|
||||||
if ($diff > 0) {
|
|
||||||
$current = bcdiv($amount, (string)$diff);
|
|
||||||
}
|
|
||||||
if (bccomp(bcmul('1.1', $average), $current) === -1) {
|
|
||||||
$largeDiff = true;
|
|
||||||
$warnText = (string)trans(
|
|
||||||
'firefly.over_budget_warn',
|
|
||||||
[
|
|
||||||
'amount' => app('amount')->formatAnything($currency, $average, false),
|
|
||||||
'over_amount' => app('amount')->formatAnything($currency, $current, false),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
app('preferences')->mark();
|
|
||||||
|
|
||||||
return response()->json(
|
|
||||||
[
|
|
||||||
'left' => $left,
|
|
||||||
'name' => $budget->name,
|
|
||||||
'limit' => $budgetLimit ? $budgetLimit->id : 0,
|
|
||||||
'amount' => $amount,
|
|
||||||
'current' => $current,
|
|
||||||
'average' => $average,
|
|
||||||
'large_diff' => $largeDiff,
|
|
||||||
'left_per_day' => $leftPerDay,
|
|
||||||
'warn_text' => $warnText,
|
|
||||||
'daysInMonth' => $daysInMonth,
|
|
||||||
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
*/
|
|
||||||
public function create(Request $request)
|
|
||||||
{
|
|
||||||
// put previous url in session if not redirect from store (not "create another").
|
|
||||||
if (true !== session('budgets.create.fromStore')) {
|
|
||||||
$this->rememberPreviousUri('budgets.create.uri');
|
|
||||||
}
|
|
||||||
$request->session()->forget('budgets.create.fromStore');
|
|
||||||
$subTitle = (string)trans('firefly.create_new_budget');
|
|
||||||
|
|
||||||
return view('budgets.create', compact('subTitle'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Budget $budget
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
*/
|
|
||||||
public function delete(Budget $budget)
|
|
||||||
{
|
|
||||||
$subTitle = trans('firefly.delete_budget', ['name' => $budget->name]);
|
|
||||||
|
|
||||||
// put previous url in session
|
|
||||||
$this->rememberPreviousUri('budgets.delete.uri');
|
|
||||||
|
|
||||||
return view('budgets.delete', compact('budget', 'subTitle'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
* @param Budget $budget
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
|
||||||
*/
|
|
||||||
public function destroy(Request $request, Budget $budget)
|
|
||||||
{
|
|
||||||
$name = $budget->name;
|
|
||||||
$this->repository->destroy($budget);
|
|
||||||
$request->session()->flash('success', (string)trans('firefly.deleted_budget', ['name' => $name]));
|
|
||||||
app('preferences')->mark();
|
|
||||||
|
|
||||||
return redirect($this->getPreviousUri('budgets.delete.uri'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
* @param Budget $budget
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
*/
|
|
||||||
public function edit(Request $request, Budget $budget)
|
|
||||||
{
|
|
||||||
$subTitle = trans('firefly.edit_budget', ['name' => $budget->name]);
|
|
||||||
|
|
||||||
// code to handle active-checkboxes
|
|
||||||
$hasOldInput = null !== $request->old('_token');
|
|
||||||
$preFilled = [
|
|
||||||
'active' => $hasOldInput ? (bool)$request->old('active') : $budget->active,
|
|
||||||
];
|
|
||||||
|
|
||||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
|
||||||
if (true !== session('budgets.edit.fromUpdate')) {
|
|
||||||
$this->rememberPreviousUri('budgets.edit.uri');
|
|
||||||
}
|
|
||||||
$request->session()->forget('budgets.edit.fromUpdate');
|
|
||||||
$request->session()->flash('preFilled', $preFilled);
|
|
||||||
|
|
||||||
return view('budgets.edit', compact('budget', 'subTitle'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
* @param string|null $moment
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
*/
|
|
||||||
public function index(Request $request, string $moment = null)
|
|
||||||
{
|
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
|
||||||
$start = session('start', new Carbon);
|
|
||||||
$end = session('end', new Carbon);
|
|
||||||
$page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page');
|
|
||||||
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
|
||||||
$days = 0;
|
|
||||||
$daysInMonth = 0;
|
|
||||||
|
|
||||||
// make date if present:
|
|
||||||
if (null !== $moment || '' !== (string)$moment) {
|
|
||||||
try {
|
|
||||||
$start = new Carbon($moment);
|
|
||||||
$end = app('navigation')->endOfPeriod($start, $range);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// start and end are already defined.
|
|
||||||
Log::debug(sprintf('start and end are already defined: %s', $e->getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if today is between start and end, use the diff in days between end and today (days left)
|
|
||||||
// otherwise, use diff between start and end.
|
|
||||||
$today = new Carbon;
|
|
||||||
if ($today->gte($start) && $today->lte($end)) {
|
|
||||||
$days = $end->diffInDays($today);
|
|
||||||
$daysInMonth = $start->diffInDays($today);
|
|
||||||
}
|
|
||||||
if ($today->lte($start) || $today->gte($end)) {
|
|
||||||
$days = $start->diffInDays($end);
|
|
||||||
$daysInMonth = $start->diffInDays($end);
|
|
||||||
}
|
|
||||||
$days = 0 === $days ? 1 : $days;
|
|
||||||
$daysInMonth = 0 === $daysInMonth ? 1 : $daysInMonth;
|
|
||||||
|
|
||||||
|
|
||||||
$next = clone $end;
|
|
||||||
$next->addDay();
|
|
||||||
$prev = clone $start;
|
|
||||||
$prev->subDay();
|
|
||||||
$prev = app('navigation')->startOfPeriod($prev, $range);
|
|
||||||
$this->repository->cleanupBudgets();
|
|
||||||
$allBudgets = $this->repository->getActiveBudgets();
|
|
||||||
$total = $allBudgets->count();
|
|
||||||
$budgets = $allBudgets->slice(($page - 1) * $pageSize, $pageSize);
|
|
||||||
$inactive = $this->repository->getInactiveBudgets();
|
|
||||||
$periodStart = $start->formatLocalized($this->monthAndDayFormat);
|
|
||||||
$periodEnd = $end->formatLocalized($this->monthAndDayFormat);
|
|
||||||
$budgetInformation = $this->repository->collectBudgetInformation($allBudgets, $start, $end);
|
|
||||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
|
||||||
$available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end);
|
|
||||||
$spent = array_sum(array_column($budgetInformation, 'spent'));
|
|
||||||
$budgeted = array_sum(array_column($budgetInformation, 'budgeted'));
|
|
||||||
|
|
||||||
// paginate budgets
|
|
||||||
$budgets = new LengthAwarePaginator($budgets, $total, $pageSize, $page);
|
|
||||||
$budgets->setPath(route('budgets.index'));
|
|
||||||
|
|
||||||
// select thing for last 12 periods:
|
|
||||||
$previousLoop = [];
|
|
||||||
/** @var Carbon $previousDate */
|
|
||||||
$previousDate = clone $start;
|
|
||||||
$count = 0;
|
|
||||||
while ($count < 12) {
|
|
||||||
$previousDate->subDay();
|
|
||||||
$previousDate = app('navigation')->startOfPeriod($previousDate, $range);
|
|
||||||
$format = $previousDate->format('Y-m-d');
|
|
||||||
$previousLoop[$format] = app('navigation')->periodShow($previousDate, $range);
|
|
||||||
++$count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// select thing for next 12 periods:
|
|
||||||
$nextLoop = [];
|
|
||||||
/** @var Carbon $nextDate */
|
|
||||||
$nextDate = clone $end;
|
|
||||||
$nextDate->addDay();
|
|
||||||
$count = 0;
|
|
||||||
|
|
||||||
while ($count < 12) {
|
|
||||||
$format = $nextDate->format('Y-m-d');
|
|
||||||
$nextLoop[$format] = app('navigation')->periodShow($nextDate, $range);
|
|
||||||
$nextDate = app('navigation')->endOfPeriod($nextDate, $range);
|
|
||||||
++$count;
|
|
||||||
$nextDate->addDay();
|
|
||||||
}
|
|
||||||
|
|
||||||
// display info
|
|
||||||
$currentMonth = app('navigation')->periodShow($start, $range);
|
|
||||||
$nextText = app('navigation')->periodShow($next, $range);
|
|
||||||
$prevText = app('navigation')->periodShow($prev, $range);
|
|
||||||
|
|
||||||
return view(
|
|
||||||
'budgets.index', compact(
|
|
||||||
'available', 'currentMonth', 'next', 'nextText', 'prev', 'allBudgets', 'prevText', 'periodStart', 'periodEnd', 'days', 'page',
|
|
||||||
'budgetInformation', 'daysInMonth',
|
|
||||||
'inactive', 'budgets', 'spent', 'budgeted', 'previousLoop', 'nextLoop', 'start', 'end'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
*/
|
|
||||||
public function infoIncome(Carbon $start, Carbon $end)
|
|
||||||
{
|
|
||||||
// properties for cache
|
|
||||||
$cache = new CacheProperties;
|
|
||||||
$cache->addProperty($start);
|
|
||||||
$cache->addProperty($end);
|
|
||||||
$cache->addProperty('info-income');
|
|
||||||
|
|
||||||
Log::debug(sprintf('infoIncome start is %s', $start->format('Y-m-d')));
|
|
||||||
Log::debug(sprintf('infoIncome end is %s', $end->format('Y-m-d')));
|
|
||||||
|
|
||||||
if ($cache->has()) {
|
|
||||||
// @codeCoverageIgnoreStart
|
|
||||||
$result = $cache->get();
|
|
||||||
|
|
||||||
return view('budgets.info', compact('result'));
|
|
||||||
// @codeCoverageIgnoreEnd
|
|
||||||
}
|
|
||||||
$result = [
|
|
||||||
'available' => '0',
|
|
||||||
'earned' => '0',
|
|
||||||
'suggested' => '0',
|
|
||||||
];
|
|
||||||
$currency = app('amount')->getDefaultCurrency();
|
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
|
||||||
/** @var Carbon $begin */
|
|
||||||
$begin = app('navigation')->subtractPeriod($start, $range, 3);
|
|
||||||
|
|
||||||
Log::debug(sprintf('Range is %s', $range));
|
|
||||||
Log::debug(sprintf('infoIncome begin is %s', $begin->format('Y-m-d')));
|
|
||||||
|
|
||||||
// get average amount available.
|
|
||||||
$total = '0';
|
|
||||||
$count = 0;
|
|
||||||
$currentStart = clone $begin;
|
|
||||||
while ($currentStart < $start) {
|
|
||||||
|
|
||||||
Log::debug(sprintf('Loop: currentStart is %s', $currentStart->format('Y-m-d')));
|
|
||||||
$currentEnd = app('navigation')->endOfPeriod($currentStart, $range);
|
|
||||||
$total = bcadd($total, $this->repository->getAvailableBudget($currency, $currentStart, $currentEnd));
|
|
||||||
$currentStart = app('navigation')->addPeriod($currentStart, $range, 0);
|
|
||||||
++$count;
|
|
||||||
}
|
|
||||||
Log::debug('Loop end');
|
|
||||||
|
|
||||||
if (0 === $count) {
|
|
||||||
$count = 1;
|
|
||||||
}
|
|
||||||
$result['available'] = bcdiv($total, (string)$count);
|
|
||||||
|
|
||||||
// amount earned in this period:
|
|
||||||
$subDay = clone $end;
|
|
||||||
$subDay->subDay();
|
|
||||||
/** @var JournalCollectorInterface $collector */
|
|
||||||
$collector = app(JournalCollectorInterface::class);
|
|
||||||
$collector->setAllAssetAccounts()->setRange($begin, $subDay)->setTypes([TransactionType::DEPOSIT])->withOpposingAccount();
|
|
||||||
$result['earned'] = bcdiv((string)$collector->getJournals()->sum('transaction_amount'), (string)$count);
|
|
||||||
|
|
||||||
// amount spent in period
|
|
||||||
/** @var JournalCollectorInterface $collector */
|
|
||||||
$collector = app(JournalCollectorInterface::class);
|
|
||||||
$collector->setAllAssetAccounts()->setRange($begin, $subDay)->setTypes([TransactionType::WITHDRAWAL])->withOpposingAccount();
|
|
||||||
$result['spent'] = bcdiv((string)$collector->getJournals()->sum('transaction_amount'), (string)$count);
|
|
||||||
// suggestion starts with the amount spent
|
|
||||||
$result['suggested'] = bcmul($result['spent'], '-1');
|
|
||||||
$result['suggested'] = 1 === bccomp($result['suggested'], $result['earned']) ? $result['earned'] : $result['suggested'];
|
|
||||||
// unless it's more than you earned. So min() of suggested/earned
|
|
||||||
|
|
||||||
$cache->store($result);
|
|
||||||
|
|
||||||
return view('budgets.info', compact('result', 'begin', 'currentEnd'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
* @param JournalRepositoryInterface $repository
|
|
||||||
* @param string|null $moment
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
*/
|
|
||||||
public function noBudget(Request $request, JournalRepositoryInterface $repository, string $moment = null)
|
|
||||||
{
|
|
||||||
// default values:
|
|
||||||
$moment = $moment ?? '';
|
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
|
||||||
$start = null;
|
|
||||||
$end = null;
|
|
||||||
$periods = new Collection;
|
|
||||||
|
|
||||||
// prep for "all" view.
|
|
||||||
if ('all' === $moment) {
|
|
||||||
$subTitle = trans('firefly.all_journals_without_budget');
|
|
||||||
$first = $repository->firstNull();
|
|
||||||
$start = null === $first ? new Carbon : $first->date;
|
|
||||||
$end = new Carbon;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prep for "specific date" view.
|
|
||||||
if ('all' !== $moment && \strlen($moment) > 0) {
|
|
||||||
$start = new Carbon($moment);
|
|
||||||
/** @var Carbon $end */
|
|
||||||
$end = app('navigation')->endOfPeriod($start, $range);
|
|
||||||
$subTitle = trans(
|
|
||||||
'firefly.without_budget_between',
|
|
||||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
|
||||||
);
|
|
||||||
$periods = $this->getPeriodOverview();
|
|
||||||
}
|
|
||||||
|
|
||||||
// prep for current period
|
|
||||||
if ('' === $moment) {
|
|
||||||
$start = clone session('start', app('navigation')->startOfPeriod(new Carbon, $range));
|
|
||||||
$end = clone session('end', app('navigation')->endOfPeriod(new Carbon, $range));
|
|
||||||
$periods = $this->getPeriodOverview();
|
|
||||||
$subTitle = trans(
|
|
||||||
'firefly.without_budget_between',
|
|
||||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$page = (int)$request->get('page');
|
|
||||||
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
|
||||||
|
|
||||||
/** @var JournalCollectorInterface $collector */
|
|
||||||
$collector = app(JournalCollectorInterface::class);
|
|
||||||
$collector->setAllAssetAccounts()->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setLimit($pageSize)->setPage($page)
|
|
||||||
->withoutBudget()->withOpposingAccount();
|
|
||||||
$transactions = $collector->getPaginatedJournals();
|
|
||||||
$transactions->setPath(route('budgets.no-budget'));
|
|
||||||
|
|
||||||
return view('budgets.no-budget', compact('transactions', 'subTitle', 'moment', 'periods', 'start', 'end'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param BudgetIncomeRequest $request
|
|
||||||
*
|
|
||||||
* @return RedirectResponse
|
|
||||||
*/
|
|
||||||
public function postUpdateIncome(BudgetIncomeRequest $request): RedirectResponse
|
|
||||||
{
|
|
||||||
$start = Carbon::createFromFormat('Y-m-d', $request->string('start'));
|
|
||||||
$end = Carbon::createFromFormat('Y-m-d', $request->string('end'));
|
|
||||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
|
||||||
$amount = $request->get('amount');
|
|
||||||
$page = 0 === $request->integer('page') ? 1 : $request->integer('page');
|
|
||||||
$this->repository->cleanupBudgets();
|
|
||||||
$this->repository->setAvailableBudget($defaultCurrency, $start, $end, $amount);
|
|
||||||
app('preferences')->mark();
|
|
||||||
|
|
||||||
return redirect(route('budgets.index', [$start->format('Y-m-d')]) . '?page=' . $page);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
* @param Budget $budget
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
*/
|
|
||||||
public function show(Request $request, Budget $budget)
|
|
||||||
{
|
|
||||||
/** @var Carbon $start */
|
|
||||||
$start = session('first', Carbon::create()->startOfYear());
|
|
||||||
$end = new Carbon;
|
|
||||||
$page = (int)$request->get('page');
|
|
||||||
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
|
||||||
$limits = $this->getLimits($budget, $start, $end);
|
|
||||||
$repetition = null;
|
|
||||||
|
|
||||||
// collector:
|
|
||||||
/** @var JournalCollectorInterface $collector */
|
|
||||||
$collector = app(JournalCollectorInterface::class);
|
|
||||||
$collector->setAllAssetAccounts()->setRange($start, $end)->setBudget($budget)->setLimit($pageSize)->setPage($page)->withBudgetInformation();
|
|
||||||
$transactions = $collector->getPaginatedJournals();
|
|
||||||
$transactions->setPath(route('budgets.show', [$budget->id]));
|
|
||||||
|
|
||||||
$subTitle = trans('firefly.all_journals_for_budget', ['name' => $budget->name]);
|
|
||||||
|
|
||||||
return view('budgets.show', compact('limits', 'budget', 'repetition', 'transactions', 'subTitle'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
* @param Budget $budget
|
|
||||||
* @param BudgetLimit $budgetLimit
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
* @throws FireflyException
|
|
||||||
*/
|
|
||||||
public function showByBudgetLimit(Request $request, Budget $budget, BudgetLimit $budgetLimit)
|
|
||||||
{
|
|
||||||
if ($budgetLimit->budget->id !== $budget->id) {
|
|
||||||
throw new FireflyException('This budget limit is not part of this budget.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$page = (int)$request->get('page');
|
|
||||||
$pageSize = (int)Preferences::get('listPageSize', 50)->data;
|
|
||||||
$subTitle = trans(
|
|
||||||
'firefly.budget_in_period',
|
|
||||||
[
|
|
||||||
'name' => $budget->name,
|
|
||||||
'start' => $budgetLimit->start_date->formatLocalized($this->monthAndDayFormat),
|
|
||||||
'end' => $budgetLimit->end_date->formatLocalized($this->monthAndDayFormat),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// collector:
|
|
||||||
/** @var JournalCollectorInterface $collector */
|
|
||||||
$collector = app(JournalCollectorInterface::class);
|
|
||||||
$collector->setAllAssetAccounts()->setRange($budgetLimit->start_date, $budgetLimit->end_date)
|
|
||||||
->setBudget($budget)->setLimit($pageSize)->setPage($page)->withBudgetInformation();
|
|
||||||
$transactions = $collector->getPaginatedJournals();
|
|
||||||
$transactions->setPath(route('budgets.show', [$budget->id, $budgetLimit->id]));
|
|
||||||
$start = session('first', Carbon::create()->startOfYear());
|
|
||||||
$end = new Carbon;
|
|
||||||
$limits = $this->getLimits($budget, $start, $end);
|
|
||||||
|
|
||||||
return view('budgets.show', compact('limits', 'budget', 'budgetLimit', 'transactions', 'subTitle'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param BudgetFormRequest $request
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
|
||||||
*/
|
|
||||||
public function store(BudgetFormRequest $request): RedirectResponse
|
|
||||||
{
|
|
||||||
$data = $request->getBudgetData();
|
|
||||||
$budget = $this->repository->store($data);
|
|
||||||
$this->repository->cleanupBudgets();
|
|
||||||
$request->session()->flash('success', (string)trans('firefly.stored_new_budget', ['name' => $budget->name]));
|
|
||||||
app('preferences')->mark();
|
|
||||||
|
|
||||||
$redirect = redirect($this->getPreviousUri('budgets.create.uri'));
|
|
||||||
|
|
||||||
if (1 === (int)$request->get('create_another')) {
|
|
||||||
// @codeCoverageIgnoreStart
|
|
||||||
$request->session()->put('budgets.create.fromStore', true);
|
|
||||||
|
|
||||||
$redirect = redirect(route('budgets.create'))->withInput();
|
|
||||||
// @codeCoverageIgnoreEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
return $redirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param BudgetFormRequest $request
|
|
||||||
* @param Budget $budget
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
|
||||||
*/
|
|
||||||
public function update(BudgetFormRequest $request, Budget $budget): RedirectResponse
|
|
||||||
{
|
|
||||||
$data = $request->getBudgetData();
|
|
||||||
$this->repository->update($budget, $data);
|
|
||||||
|
|
||||||
$request->session()->flash('success', (string)trans('firefly.updated_budget', ['name' => $budget->name]));
|
|
||||||
$this->repository->cleanupBudgets();
|
|
||||||
app('preferences')->mark();
|
|
||||||
|
|
||||||
$redirect = redirect($this->getPreviousUri('budgets.edit.uri'));
|
|
||||||
|
|
||||||
if (1 === (int)$request->get('return_to_edit')) {
|
|
||||||
// @codeCoverageIgnoreStart
|
|
||||||
$request->session()->put('budgets.edit.fromUpdate', true);
|
|
||||||
|
|
||||||
$redirect = redirect(route('budgets.edit', [$budget->id]))->withInput(['return_to_edit' => 1]);
|
|
||||||
// @codeCoverageIgnoreEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
return $redirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
*/
|
|
||||||
public function updateIncome(Request $request, Carbon $start, Carbon $end)
|
|
||||||
{
|
|
||||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
|
||||||
$available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end);
|
|
||||||
$available = round($available, $defaultCurrency->decimal_places);
|
|
||||||
$page = (int)$request->get('page');
|
|
||||||
|
|
||||||
return view('budgets.income', compact('available', 'start', 'end', 'page'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Budget $budget
|
|
||||||
* @param Carbon $start
|
|
||||||
* @param Carbon $end
|
|
||||||
*
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
private function getLimits(Budget $budget, Carbon $start, Carbon $end): Collection
|
|
||||||
{
|
|
||||||
// properties for cache
|
|
||||||
$cache = new CacheProperties;
|
|
||||||
$cache->addProperty($start);
|
|
||||||
$cache->addProperty($end);
|
|
||||||
$cache->addProperty($budget->id);
|
|
||||||
$cache->addProperty('get-limits');
|
|
||||||
|
|
||||||
if ($cache->has()) {
|
|
||||||
return $cache->get(); // @codeCoverageIgnore
|
|
||||||
}
|
|
||||||
|
|
||||||
$set = $this->repository->getBudgetLimits($budget, $start, $end);
|
|
||||||
$limits = new Collection();
|
|
||||||
|
|
||||||
/** @var BudgetLimit $entry */
|
|
||||||
foreach ($set as $entry) {
|
|
||||||
$entry->spent = $this->repository->spentInPeriod(new Collection([$budget]), new Collection(), $entry->start_date, $entry->end_date);
|
|
||||||
$limits->push($entry);
|
|
||||||
}
|
|
||||||
$cache->store($limits);
|
|
||||||
|
|
||||||
return $set;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
private function getPeriodOverview(): Collection
|
|
||||||
{
|
|
||||||
/** @var JournalRepositoryInterface $repository */
|
|
||||||
$repository = app(JournalRepositoryInterface::class);
|
|
||||||
$first = $repository->firstNull();
|
|
||||||
$start = null === $first ? new Carbon : $first->date;
|
|
||||||
$range = Preferences::get('viewRange', '1M')->data;
|
|
||||||
$start = app('navigation')->startOfPeriod($start, $range);
|
|
||||||
$end = app('navigation')->endOfX(new Carbon, $range, null);
|
|
||||||
$entries = new Collection;
|
|
||||||
$cache = new CacheProperties;
|
|
||||||
$cache->addProperty($start);
|
|
||||||
$cache->addProperty($end);
|
|
||||||
$cache->addProperty('no-budget-period-entries');
|
|
||||||
|
|
||||||
if ($cache->has()) {
|
|
||||||
return $cache->get(); // @codeCoverageIgnore
|
|
||||||
}
|
|
||||||
$dates = app('navigation')->blockPeriods($start, $end, $range);
|
|
||||||
foreach ($dates as $date) {
|
|
||||||
/** @var JournalCollectorInterface $collector */
|
|
||||||
$collector = app(JournalCollectorInterface::class);
|
|
||||||
$collector->setAllAssetAccounts()->setRange($date['start'], $date['end'])->withoutBudget()->withOpposingAccount()->setTypes(
|
|
||||||
[TransactionType::WITHDRAWAL]
|
|
||||||
);
|
|
||||||
$set = $collector->getJournals();
|
|
||||||
$sum = (string)($set->sum('transaction_amount') ?? '0');
|
|
||||||
$journals = $set->count();
|
|
||||||
/** @noinspection PhpUndefinedMethodInspection */
|
|
||||||
$dateStr = $date['end']->format('Y-m-d');
|
|
||||||
$dateName = app('navigation')->periodShow($date['end'], $date['period']);
|
|
||||||
$entries->push(['string' => $dateStr, 'name' => $dateName, 'count' => $journals, 'sum' => $sum, 'date' => clone $date['end']]);
|
|
||||||
}
|
|
||||||
$cache->store($entries);
|
|
||||||
|
|
||||||
return $entries;
|
|
||||||
}
|
|
||||||
}
|
|
@ -190,22 +190,31 @@ Route::group(
|
|||||||
Route::group(
|
Route::group(
|
||||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers', 'prefix' => 'budgets', 'as' => 'budgets.'], function () {
|
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers', 'prefix' => 'budgets', 'as' => 'budgets.'], function () {
|
||||||
|
|
||||||
Route::get('income/{start_date}/{end_date}', ['uses' => 'BudgetController@updateIncome', 'as' => 'income']);
|
// delete
|
||||||
Route::get('info/{start_date}/{end_date}', ['uses' => 'BudgetController@infoIncome', 'as' => 'income.info']);
|
Route::get('delete/{budget}', ['uses' => 'Budget\DeleteController@delete', 'as' => 'delete']);
|
||||||
Route::get('create', ['uses' => 'BudgetController@create', 'as' => 'create']);
|
Route::post('destroy/{budget}', ['uses' => 'Budget\DeleteController@destroy', 'as' => 'destroy']);
|
||||||
Route::get('edit/{budget}', ['uses' => 'BudgetController@edit', 'as' => 'edit']);
|
|
||||||
Route::get('delete/{budget}', ['uses' => 'BudgetController@delete', 'as' => 'delete']);
|
|
||||||
Route::get('show/{budget}', ['uses' => 'BudgetController@show', 'as' => 'show']);
|
|
||||||
Route::get('show/{budget}/{budgetLimit}', ['uses' => 'BudgetController@showByBudgetLimit', 'as' => 'show.limit']);
|
|
||||||
Route::get('list/no-budget/{moment?}', ['uses' => 'BudgetController@noBudget', 'as' => 'no-budget']);
|
|
||||||
Route::get('{moment?}', ['uses' => 'BudgetController@index', 'as' => 'index']);
|
|
||||||
|
|
||||||
|
// create
|
||||||
|
Route::get('create', ['uses' => 'Budget\CreateController@create', 'as' => 'create']);
|
||||||
|
Route::post('store', ['uses' => 'Budget\CreateController@store', 'as' => 'store']);
|
||||||
|
|
||||||
Route::post('income', ['uses' => 'BudgetController@postUpdateIncome', 'as' => 'income.post']);
|
// edit
|
||||||
Route::post('store', ['uses' => 'BudgetController@store', 'as' => 'store']);
|
Route::get('edit/{budget}', ['uses' => 'Budget\EditController@edit', 'as' => 'edit']);
|
||||||
Route::post('update/{budget}', ['uses' => 'BudgetController@update', 'as' => 'update']);
|
Route::post('update/{budget}', ['uses' => 'Budget\EditController@update', 'as' => 'update']);
|
||||||
Route::post('destroy/{budget}', ['uses' => 'BudgetController@destroy', 'as' => 'destroy']);
|
|
||||||
Route::post('amount/{budget}', ['uses' => 'BudgetController@amount', 'as' => 'amount']);
|
// show
|
||||||
|
Route::get('show/{budget}', ['uses' => 'Budget\ShowController@show', 'as' => 'show']);
|
||||||
|
Route::get('show/{budget}/{budgetLimit}', ['uses' => 'Budget\ShowController@showByBudgetLimit', 'as' => 'show.limit']);
|
||||||
|
Route::get('list/no-budget/{moment?}', ['uses' => 'Budget\ShowController@noBudget', 'as' => 'no-budget']);
|
||||||
|
|
||||||
|
// index
|
||||||
|
Route::get('{moment?}', ['uses' => 'Budget\IndexController@index', 'as' => 'index']);
|
||||||
|
|
||||||
|
// update budget amount and income amount
|
||||||
|
Route::get('income/{start_date}/{end_date}', ['uses' => 'Budget\AmountController@updateIncome', 'as' => 'income']);
|
||||||
|
Route::get('info/{start_date}/{end_date}', ['uses' => 'Budget\AmountController@infoIncome', 'as' => 'income.info']);
|
||||||
|
Route::post('income', ['uses' => 'Budget\AmountController@postUpdateIncome', 'as' => 'income.post']);
|
||||||
|
Route::post('amount/{budget}', ['uses' => 'Budget\AmountController@amount', 'as' => 'amount']);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
220
tests/Feature/Controllers/Budget/AmountControllerTest.php
Normal file
220
tests/Feature/Controllers/Budget/AmountControllerTest.php
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* AmountControllerTest.php
|
||||||
|
* Copyright (c) 2018 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 Tests\Feature\Controllers\Budget;
|
||||||
|
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Models\BudgetLimit;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Log;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class AmountControllerTest
|
||||||
|
*/
|
||||||
|
class AmountControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
Log::debug(sprintf('Now in %s.', \get_class($this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\AmountController
|
||||||
|
*/
|
||||||
|
public function testAmount(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testAmount()');
|
||||||
|
// mock stuff
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
$repository->shouldReceive('updateLimitAmount')->andReturn(new BudgetLimit);
|
||||||
|
$repository->shouldReceive('spentInPeriod')->andReturn('0');
|
||||||
|
$repository->shouldReceive('budgetedPerDay')->andReturn('10');
|
||||||
|
|
||||||
|
|
||||||
|
$data = ['amount' => 200, 'start' => '2017-01-01', 'end' => '2017-01-31'];
|
||||||
|
$this->be($this->user());
|
||||||
|
$response = $this->post(route('budgets.amount', [1]), $data);
|
||||||
|
$response->assertStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\AmountController
|
||||||
|
*/
|
||||||
|
public function testAmountLargeDiff(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testAmount()');
|
||||||
|
// mock stuff
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
$repository->shouldReceive('updateLimitAmount')->andReturn(new BudgetLimit);
|
||||||
|
$repository->shouldReceive('spentInPeriod')->andReturn('0');
|
||||||
|
$repository->shouldReceive('budgetedPerDay')->andReturn('10');
|
||||||
|
|
||||||
|
|
||||||
|
$data = ['amount' => 20000, 'start' => '2017-01-01', 'end' => '2017-01-31'];
|
||||||
|
$this->be($this->user());
|
||||||
|
$response = $this->post(route('budgets.amount', [1]), $data);
|
||||||
|
$response->assertStatus(200);
|
||||||
|
$response->assertSee('Normally you budget about \u20ac10.00 per day.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\AmountController
|
||||||
|
*/
|
||||||
|
public function testAmountOutOfRange(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testAmountOutOfRange()');
|
||||||
|
// mock stuff
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
$repository->shouldReceive('updateLimitAmount')->andReturn(new BudgetLimit);
|
||||||
|
$repository->shouldReceive('spentInPeriod')->andReturn('0');
|
||||||
|
$repository->shouldReceive('budgetedPerDay')->andReturn('10');
|
||||||
|
|
||||||
|
$today = new Carbon;
|
||||||
|
$start = $today->startOfMonth()->format('Y-m-d');
|
||||||
|
$end = $today->endOfMonth()->format('Y-m-d');
|
||||||
|
$data = ['amount' => 200, 'start' => $start, 'end' => $end];
|
||||||
|
$this->be($this->user());
|
||||||
|
$response = $this->post(route('budgets.amount', [1]), $data);
|
||||||
|
$response->assertStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\AmountController
|
||||||
|
*/
|
||||||
|
public function testAmountZero(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testAmountZero()');
|
||||||
|
// mock stuff
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
$repository->shouldReceive('updateLimitAmount')->andReturn(new BudgetLimit);
|
||||||
|
$repository->shouldReceive('spentInPeriod')->andReturn('0');
|
||||||
|
$repository->shouldReceive('budgetedPerDay')->andReturn('10');
|
||||||
|
|
||||||
|
$data = ['amount' => 0, 'start' => '2017-01-01', 'end' => '2017-01-31'];
|
||||||
|
$this->be($this->user());
|
||||||
|
$response = $this->post(route('budgets.amount', [1]), $data);
|
||||||
|
$response->assertStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\AmountController
|
||||||
|
*/
|
||||||
|
public function testInfoIncome(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testInfoIncome()');
|
||||||
|
// mock stuff
|
||||||
|
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
|
||||||
|
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
|
||||||
|
$accountRepos->shouldReceive('setUser');
|
||||||
|
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$response = $this->get(route('budgets.income.info', ['20170101', '20170131']));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\AmountController
|
||||||
|
* @dataProvider dateRangeProvider
|
||||||
|
*
|
||||||
|
* @param string $range
|
||||||
|
*/
|
||||||
|
public function testInfoIncomeExpanded(string $range): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Now in testInfoIncomeExpanded(%s)', $range));
|
||||||
|
// mock stuff
|
||||||
|
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
|
||||||
|
$accountRepos->shouldReceive('setUser');
|
||||||
|
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$this->changeDateRange($this->user(), $range);
|
||||||
|
$response = $this->get(route('budgets.income.info', ['20170301', '20170430']));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\AmountController
|
||||||
|
*/
|
||||||
|
public function testPostUpdateIncome(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testPostUpdateIncome()');
|
||||||
|
// mock stuff
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
$repository->shouldReceive('setAvailableBudget');
|
||||||
|
$repository->shouldReceive('cleanupBudgets');
|
||||||
|
|
||||||
|
$data = ['amount' => '200', 'start' => '2017-01-01', 'end' => '2017-01-31'];
|
||||||
|
$this->be($this->user());
|
||||||
|
$response = $this->post(route('budgets.income.post'), $data);
|
||||||
|
$response->assertStatus(302);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\AmountController
|
||||||
|
*/
|
||||||
|
public function testUpdateIncome(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testUpdateIncome()');
|
||||||
|
// must be in list
|
||||||
|
$this->be($this->user());
|
||||||
|
|
||||||
|
// mock stuff
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
$repository->shouldReceive('getAvailableBudget')->andReturn('1');
|
||||||
|
$repository->shouldReceive('cleanupBudgets');
|
||||||
|
|
||||||
|
$response = $this->get(route('budgets.income', ['2017-01-01', '2017-01-31']));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
}
|
||||||
|
}
|
95
tests/Feature/Controllers/Budget/CreateControllerTest.php
Normal file
95
tests/Feature/Controllers/Budget/CreateControllerTest.php
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* CreateControllerTest.php
|
||||||
|
* Copyright (c) 2018 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 Tests\Feature\Controllers\Budget;
|
||||||
|
|
||||||
|
|
||||||
|
use FireflyIII\Models\Budget;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
|
use Log;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class CreateControllerTest
|
||||||
|
*/
|
||||||
|
class CreateControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
Log::debug(sprintf('Now in %s.', \get_class($this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\CreateController
|
||||||
|
*/
|
||||||
|
public function testCreate(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testCreate()');
|
||||||
|
// mock stuff
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$response = $this->get(route('budgets.create'));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
// has bread crumb
|
||||||
|
$response->assertSee('<ol class="breadcrumb">');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\CreateController
|
||||||
|
*/
|
||||||
|
public function testStore(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testStore()');
|
||||||
|
// mock stuff
|
||||||
|
$budget = factory(Budget::class)->make();
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
$repository->shouldReceive('findNull')->andReturn($budget);
|
||||||
|
$repository->shouldReceive('store')->andReturn($budget);
|
||||||
|
$repository->shouldReceive('cleanupBudgets');
|
||||||
|
|
||||||
|
$this->session(['budgets.create.uri' => 'http://localhost']);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'name' => 'New Budget ' . random_int(1000, 9999),
|
||||||
|
];
|
||||||
|
$this->be($this->user());
|
||||||
|
$response = $this->post(route('budgets.store'), $data);
|
||||||
|
$response->assertStatus(302);
|
||||||
|
$response->assertSessionHas('success');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
85
tests/Feature/Controllers/Budget/DeleteControllerTest.php
Normal file
85
tests/Feature/Controllers/Budget/DeleteControllerTest.php
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* DeleteControllerTest.php
|
||||||
|
* Copyright (c) 2018 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 Tests\Feature\Controllers\Budget;
|
||||||
|
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
|
use Log;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class DeleteControllerTest
|
||||||
|
*/
|
||||||
|
class DeleteControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
Log::debug(sprintf('Now in %s.', \get_class($this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\DeleteController
|
||||||
|
*/
|
||||||
|
public function testDelete(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testDelete()');
|
||||||
|
// mock stuff
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$response = $this->get(route('budgets.delete', [1]));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
// has bread crumb
|
||||||
|
$response->assertSee('<ol class="breadcrumb">');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\DeleteController
|
||||||
|
*/
|
||||||
|
public function testDestroy(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testDestroy()');
|
||||||
|
// mock stuff
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
|
||||||
|
$repository->shouldReceive('destroy')->andReturn(true);
|
||||||
|
|
||||||
|
$this->session(['budgets.delete.uri' => 'http://localhost']);
|
||||||
|
$this->be($this->user());
|
||||||
|
$response = $this->post(route('budgets.destroy', [1]));
|
||||||
|
$response->assertStatus(302);
|
||||||
|
$response->assertSessionHas('success');
|
||||||
|
}
|
||||||
|
}
|
94
tests/Feature/Controllers/Budget/EditControllerTest.php
Normal file
94
tests/Feature/Controllers/Budget/EditControllerTest.php
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* EditControllerTest.php
|
||||||
|
* Copyright (c) 2018 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 Tests\Feature\Controllers\Budget;
|
||||||
|
|
||||||
|
use FireflyIII\Models\Budget;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
|
use Log;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class EditControllerTest
|
||||||
|
*/
|
||||||
|
class EditControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
Log::debug(sprintf('Now in %s.', \get_class($this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\EditController
|
||||||
|
*/
|
||||||
|
public function testEdit(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testEdit()');
|
||||||
|
// mock stuff
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$response = $this->get(route('budgets.edit', [1]));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
// has bread crumb
|
||||||
|
$response->assertSee('<ol class="breadcrumb">');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\EditController
|
||||||
|
*/
|
||||||
|
public function testUpdate(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testUpdate()');
|
||||||
|
// mock stuff
|
||||||
|
$budget = factory(Budget::class)->make();
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
$repository->shouldReceive('findNull')->andReturn($budget);
|
||||||
|
$repository->shouldReceive('update');
|
||||||
|
$repository->shouldReceive('cleanupBudgets');
|
||||||
|
|
||||||
|
$this->session(['budgets.edit.uri' => 'http://localhost']);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'name' => 'Updated Budget ' . random_int(1000, 9999),
|
||||||
|
'active' => 1,
|
||||||
|
];
|
||||||
|
$this->be($this->user());
|
||||||
|
$response = $this->post(route('budgets.update', [1]), $data);
|
||||||
|
$response->assertStatus(302);
|
||||||
|
$response->assertSessionHas('success');
|
||||||
|
}
|
||||||
|
}
|
237
tests/Feature/Controllers/Budget/IndexControllerTest.php
Normal file
237
tests/Feature/Controllers/Budget/IndexControllerTest.php
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* IndexControllerTest.php
|
||||||
|
* Copyright (c) 2018 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 Tests\Feature\Controllers\Budget;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Models\Budget;
|
||||||
|
use FireflyIII\Models\BudgetLimit;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Log;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class IndexControllerTest
|
||||||
|
*/
|
||||||
|
class IndexControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
Log::debug(sprintf('Now in %s.', \get_class($this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\IndexController
|
||||||
|
* @dataProvider dateRangeProvider
|
||||||
|
*
|
||||||
|
* @param string $range
|
||||||
|
*/
|
||||||
|
public function testIndex(string $range): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Now in testIndex(%s)', $range));
|
||||||
|
// mock stuff
|
||||||
|
$budget = factory(Budget::class)->make();
|
||||||
|
$budgetLimit = factory(BudgetLimit::class)->make();
|
||||||
|
|
||||||
|
// set budget limit to current month:
|
||||||
|
$budgetLimit->start_date = Carbon::now()->startOfMonth();
|
||||||
|
$budgetLimit->end_date = Carbon::now()->endOfMonth();
|
||||||
|
$budgetInfo = [
|
||||||
|
$budget->id => [
|
||||||
|
'spent' => '0',
|
||||||
|
'budgeted' => '0',
|
||||||
|
'currentRep' => false,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
||||||
|
|
||||||
|
$repository->shouldReceive('cleanupBudgets');
|
||||||
|
$repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget]));
|
||||||
|
$repository->shouldReceive('getInactiveBudgets')->andReturn(new Collection);
|
||||||
|
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
|
||||||
|
$repository->shouldReceive('spentInPeriod')->andReturn('-1');
|
||||||
|
$repository->shouldReceive('collectBudgetInformation')->andReturn($budgetInfo);
|
||||||
|
$repository->shouldReceive('getBudgetLimits')->andReturn(new Collection([$budgetLimit]));
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$this->changeDateRange($this->user(), $range);
|
||||||
|
$response = $this->get(route('budgets.index'));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
// has bread crumb
|
||||||
|
$response->assertSee('<ol class="breadcrumb">');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\IndexController
|
||||||
|
* @dataProvider dateRangeProvider
|
||||||
|
*
|
||||||
|
* @param string $range
|
||||||
|
*/
|
||||||
|
public function testIndexOutOfRange(string $range): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Now in testIndexOutOfRange(%s)', $range));
|
||||||
|
// mock stuff
|
||||||
|
$budget = factory(Budget::class)->make();
|
||||||
|
$budgetLimit = factory(BudgetLimit::class)->make();
|
||||||
|
$budgetInfo = [
|
||||||
|
$budget->id => [
|
||||||
|
'spent' => '0',
|
||||||
|
'budgeted' => '0',
|
||||||
|
'currentRep' => false,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
// set budget limit to current month:
|
||||||
|
$budgetLimit->start_date = Carbon::now()->startOfMonth();
|
||||||
|
$budgetLimit->end_date = Carbon::now()->endOfMonth();
|
||||||
|
|
||||||
|
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
||||||
|
|
||||||
|
$repository->shouldReceive('cleanupBudgets');
|
||||||
|
$repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget]));
|
||||||
|
$repository->shouldReceive('getInactiveBudgets')->andReturn(new Collection);
|
||||||
|
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
|
||||||
|
$repository->shouldReceive('spentInPeriod')->andReturn('-1');
|
||||||
|
$repository->shouldReceive('getBudgetLimits')->andReturn(new Collection([$budgetLimit]));
|
||||||
|
$repository->shouldReceive('collectBudgetInformation')->andReturn($budgetInfo);
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$today = new Carbon;
|
||||||
|
$today->startOfMonth();
|
||||||
|
$this->changeDateRange($this->user(), $range);
|
||||||
|
$response = $this->get(route('budgets.index', [$today->format('Y-m-d')]));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
// has bread crumb
|
||||||
|
$response->assertSee('<ol class="breadcrumb">');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\IndexController
|
||||||
|
* @dataProvider dateRangeProvider
|
||||||
|
*
|
||||||
|
* @param string $range
|
||||||
|
*/
|
||||||
|
public function testIndexWithDate(string $range): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Now in testIndexWithDate(%s)', $range));
|
||||||
|
// mock stuff
|
||||||
|
$budget = factory(Budget::class)->make();
|
||||||
|
$budgetLimit = factory(BudgetLimit::class)->make();
|
||||||
|
$budgetInfo = [
|
||||||
|
$budget->id => [
|
||||||
|
'spent' => '0',
|
||||||
|
'budgeted' => '0',
|
||||||
|
'currentRep' => false,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
// set budget limit to current month:
|
||||||
|
$budgetLimit->start_date = Carbon::now()->startOfMonth();
|
||||||
|
$budgetLimit->end_date = Carbon::now()->endOfMonth();
|
||||||
|
|
||||||
|
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
||||||
|
|
||||||
|
$repository->shouldReceive('cleanupBudgets');
|
||||||
|
$repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget]));
|
||||||
|
$repository->shouldReceive('getInactiveBudgets')->andReturn(new Collection);
|
||||||
|
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
|
||||||
|
$repository->shouldReceive('spentInPeriod')->andReturn('-1');
|
||||||
|
$repository->shouldReceive('getBudgetLimits')->andReturn(new Collection([$budgetLimit]));
|
||||||
|
$repository->shouldReceive('collectBudgetInformation')->andReturn($budgetInfo);
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$this->changeDateRange($this->user(), $range);
|
||||||
|
$response = $this->get(route('budgets.index', ['2017-01-01']));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
// has bread crumb
|
||||||
|
$response->assertSee('<ol class="breadcrumb">');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\IndexController
|
||||||
|
* @dataProvider dateRangeProvider
|
||||||
|
*
|
||||||
|
* @param string $range
|
||||||
|
*/
|
||||||
|
public function testIndexWithInvalidDate(string $range): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Now in testIndexWithInvalidDate(%s)', $range));
|
||||||
|
// mock stuff
|
||||||
|
$budget = factory(Budget::class)->make();
|
||||||
|
$budgetLimit = factory(BudgetLimit::class)->make();
|
||||||
|
|
||||||
|
// set budget limit to current month:
|
||||||
|
$budgetLimit->start_date = Carbon::now()->startOfMonth();
|
||||||
|
$budgetLimit->end_date = Carbon::now()->endOfMonth();
|
||||||
|
$budgetInfo = [
|
||||||
|
$budget->id => [
|
||||||
|
'spent' => '0',
|
||||||
|
'budgeted' => '0',
|
||||||
|
'currentRep' => false,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
||||||
|
|
||||||
|
$repository->shouldReceive('cleanupBudgets');
|
||||||
|
$repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget]));
|
||||||
|
$repository->shouldReceive('getInactiveBudgets')->andReturn(new Collection);
|
||||||
|
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
|
||||||
|
$repository->shouldReceive('spentInPeriod')->andReturn('-1');
|
||||||
|
$repository->shouldReceive('getBudgetLimits')->andReturn(new Collection([$budgetLimit]));
|
||||||
|
$repository->shouldReceive('collectBudgetInformation')->andReturn($budgetInfo);
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$this->changeDateRange($this->user(), $range);
|
||||||
|
$response = $this->get(route('budgets.index', ['Hello-there']));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
// has bread crumb
|
||||||
|
$response->assertSee('<ol class="breadcrumb">');
|
||||||
|
}
|
||||||
|
}
|
265
tests/Feature/Controllers/Budget/ShowControllerTest.php
Normal file
265
tests/Feature/Controllers/Budget/ShowControllerTest.php
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ShowControllerTest.php
|
||||||
|
* Copyright (c) 2018 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 Tests\Feature\Controllers\Budget;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||||
|
use FireflyIII\Models\BudgetLimit;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Log;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Class ShowControllerTest
|
||||||
|
*/
|
||||||
|
class ShowControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
Log::debug(sprintf('Now in %s.', \get_class($this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\ShowController
|
||||||
|
* @dataProvider dateRangeProvider
|
||||||
|
*
|
||||||
|
* @param string $range
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function testNoBudget(string $range): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Now in testNoBudget(%s)', $range));
|
||||||
|
|
||||||
|
// mock stuff
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$collector = $this->mock(JournalCollectorInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->andReturn(null);
|
||||||
|
|
||||||
|
$collector->shouldReceive('setAllAssetAccounts')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setRange')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('getJournals')->andReturn(new Collection);
|
||||||
|
$collector->shouldReceive('setLimit')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setPage')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setTypes')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('withoutBudget')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('withOpposingAccount')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('getPaginatedJournals')->andReturn(new LengthAwarePaginator([], 0, 10));
|
||||||
|
|
||||||
|
$date = new Carbon();
|
||||||
|
$this->session(['start' => $date, 'end' => clone $date]);
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$this->changeDateRange($this->user(), $range);
|
||||||
|
$response = $this->get(route('budgets.no-budget'));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
// has bread crumb
|
||||||
|
$response->assertSee('<ol class="breadcrumb">');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\ShowController
|
||||||
|
* @dataProvider dateRangeProvider
|
||||||
|
*
|
||||||
|
* @param string $range
|
||||||
|
*/
|
||||||
|
public function testNoBudgetAll(string $range): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Now in testNoBudgetAll(%s)', $range));
|
||||||
|
// mock stuff
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$collector = $this->mock(JournalCollectorInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->andReturn(null);
|
||||||
|
|
||||||
|
$collector->shouldReceive('setAllAssetAccounts')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setRange')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setLimit')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setTypes')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setPage')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('withOpposingAccount')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('withoutBudget')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setTypes')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('getJournals')->andReturn(new Collection);
|
||||||
|
$collector->shouldReceive('getPaginatedJournals')->andReturn(new LengthAwarePaginator([], 0, 10));
|
||||||
|
|
||||||
|
$date = new Carbon();
|
||||||
|
$this->session(['start' => $date, 'end' => clone $date]);
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$this->changeDateRange($this->user(), $range);
|
||||||
|
$response = $this->get(route('budgets.no-budget', ['all']));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
// has bread crumb
|
||||||
|
$response->assertSee('<ol class="breadcrumb">');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\ShowController
|
||||||
|
* @dataProvider dateRangeProvider
|
||||||
|
*
|
||||||
|
* @param string $range
|
||||||
|
*/
|
||||||
|
public function testNoBudgetDate(string $range): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Now in testNoBudgetDate(%s)', $range));
|
||||||
|
// mock stuff
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$collector = $this->mock(JournalCollectorInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->andReturn(null);
|
||||||
|
|
||||||
|
$collector->shouldReceive('setAllAssetAccounts')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setRange')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('getJournals')->andReturn(new Collection);
|
||||||
|
$collector->shouldReceive('setLimit')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setPage')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('withOpposingAccount')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setTypes')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('withoutBudget')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('getPaginatedJournals')->andReturn(new LengthAwarePaginator([], 0, 10));
|
||||||
|
|
||||||
|
$date = new Carbon();
|
||||||
|
$this->session(['start' => $date, 'end' => clone $date]);
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$this->changeDateRange($this->user(), $range);
|
||||||
|
$response = $this->get(route('budgets.no-budget', ['2016-01-01']));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
// has bread crumb
|
||||||
|
$response->assertSee('<ol class="breadcrumb">');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\ShowController
|
||||||
|
* @dataProvider dateRangeProvider
|
||||||
|
*
|
||||||
|
* @param string $range
|
||||||
|
*/
|
||||||
|
public function testShow(string $range): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Now in testShow(%s)', $range));
|
||||||
|
// mock stuff
|
||||||
|
|
||||||
|
$budgetLimit = factory(BudgetLimit::class)->make();
|
||||||
|
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->andReturn(new TransactionJournal);
|
||||||
|
|
||||||
|
$collector = $this->mock(JournalCollectorInterface::class);
|
||||||
|
$collector->shouldReceive('setAllAssetAccounts')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setRange')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setLimit')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setPage')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setBudget')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('getPaginatedJournals')->andReturn(new LengthAwarePaginator([], 0, 10));
|
||||||
|
$collector->shouldReceive('withBudgetInformation')->andReturnSelf();
|
||||||
|
|
||||||
|
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
||||||
|
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
||||||
|
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$repository->shouldReceive('getBudgetLimits')->andReturn(new Collection([$budgetLimit]));
|
||||||
|
$repository->shouldReceive('spentInPeriod')->andReturn('-1');
|
||||||
|
|
||||||
|
$date = new Carbon();
|
||||||
|
$date->subDay();
|
||||||
|
$this->session(['first' => $date]);
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$this->changeDateRange($this->user(), $range);
|
||||||
|
$response = $this->get(route('budgets.show', [1]));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
$response->assertSee('<ol class="breadcrumb">');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\ShowController
|
||||||
|
* @expectedExceptionMessage This budget limit is not part of
|
||||||
|
*/
|
||||||
|
public function testShowByBadBudgetLimit(): void
|
||||||
|
{
|
||||||
|
Log::debug('Now in testShowByBadBudgetLimit()');
|
||||||
|
// mock stuff
|
||||||
|
$repository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$response = $this->get(route('budgets.show.limit', [1, 8]));
|
||||||
|
$response->assertStatus(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \FireflyIII\Http\Controllers\Budget\ShowController
|
||||||
|
* @dataProvider dateRangeProvider
|
||||||
|
*
|
||||||
|
* @param string $range
|
||||||
|
*/
|
||||||
|
public function testShowByBudgetLimit(string $range): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Now in testShowByBudgetLimit(%s)', $range));
|
||||||
|
// mock stuff
|
||||||
|
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
||||||
|
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
||||||
|
|
||||||
|
// mock account repository
|
||||||
|
$accountRepository = $this->mock(AccountRepositoryInterface::class);
|
||||||
|
$accountRepository->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
||||||
|
|
||||||
|
// mock budget repository
|
||||||
|
$budgetRepository = $this->mock(BudgetRepositoryInterface::class);
|
||||||
|
$budgetRepository->shouldReceive('spentInPeriod')->andReturn('1');
|
||||||
|
$budgetRepository->shouldReceive('getBudgetLimits')->andReturn(new Collection);
|
||||||
|
|
||||||
|
// mock journal collector:
|
||||||
|
$collector = $this->mock(JournalCollectorInterface::class);
|
||||||
|
$collector->shouldReceive('setAllAssetAccounts')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setRange')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setLimit')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setPage')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('setBudget')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('withBudgetInformation')->andReturnSelf();
|
||||||
|
$collector->shouldReceive('getPaginatedJournals')->andReturn(new LengthAwarePaginator([], 0, 10));
|
||||||
|
|
||||||
|
$this->be($this->user());
|
||||||
|
$this->changeDateRange($this->user(), $range);
|
||||||
|
$response = $this->get(route('budgets.show.limit', [1, 1]));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
// has bread crumb
|
||||||
|
$response->assertSee('<ol class="breadcrumb">');
|
||||||
|
}
|
||||||
|
}
|
@ -1,756 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* BudgetControllerTest.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 Tests\Feature\Controllers;
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
|
||||||
use FireflyIII\Models\Budget;
|
|
||||||
use FireflyIII\Models\BudgetLimit;
|
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
|
||||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Log;
|
|
||||||
use Tests\TestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class BudgetControllerTest
|
|
||||||
*
|
|
||||||
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
|
|
||||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
|
||||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
|
||||||
*/
|
|
||||||
class BudgetControllerTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function setUp()
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
Log::debug(sprintf('Now in %s.', \get_class($this)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::amount
|
|
||||||
*/
|
|
||||||
public function testAmount(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testAmount()');
|
|
||||||
// mock stuff
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
$repository->shouldReceive('updateLimitAmount')->andReturn(new BudgetLimit);
|
|
||||||
$repository->shouldReceive('spentInPeriod')->andReturn('0');
|
|
||||||
$repository->shouldReceive('budgetedPerDay')->andReturn('10');
|
|
||||||
|
|
||||||
|
|
||||||
$data = ['amount' => 200, 'start' => '2017-01-01', 'end' => '2017-01-31'];
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->post(route('budgets.amount', [1]), $data);
|
|
||||||
$response->assertStatus(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::amount
|
|
||||||
*/
|
|
||||||
public function testAmountLargeDiff(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testAmount()');
|
|
||||||
// mock stuff
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
$repository->shouldReceive('updateLimitAmount')->andReturn(new BudgetLimit);
|
|
||||||
$repository->shouldReceive('spentInPeriod')->andReturn('0');
|
|
||||||
$repository->shouldReceive('budgetedPerDay')->andReturn('10');
|
|
||||||
|
|
||||||
|
|
||||||
$data = ['amount' => 20000, 'start' => '2017-01-01', 'end' => '2017-01-31'];
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->post(route('budgets.amount', [1]), $data);
|
|
||||||
$response->assertStatus(200);
|
|
||||||
$response->assertSee('Normally you budget about \u20ac10.00 per day.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::amount
|
|
||||||
*/
|
|
||||||
public function testAmountZero(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testAmountZero()');
|
|
||||||
// mock stuff
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
$repository->shouldReceive('updateLimitAmount')->andReturn(new BudgetLimit);
|
|
||||||
$repository->shouldReceive('spentInPeriod')->andReturn('0');
|
|
||||||
$repository->shouldReceive('budgetedPerDay')->andReturn('10');
|
|
||||||
|
|
||||||
$data = ['amount' => 0, 'start' => '2017-01-01', 'end' => '2017-01-31'];
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->post(route('budgets.amount', [1]), $data);
|
|
||||||
$response->assertStatus(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::amount
|
|
||||||
*/
|
|
||||||
public function testAmountOutOfRange(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testAmountOutOfRange()');
|
|
||||||
// mock stuff
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
$repository->shouldReceive('updateLimitAmount')->andReturn(new BudgetLimit);
|
|
||||||
$repository->shouldReceive('spentInPeriod')->andReturn('0');
|
|
||||||
$repository->shouldReceive('budgetedPerDay')->andReturn('10');
|
|
||||||
|
|
||||||
$today = new Carbon;
|
|
||||||
$start = $today->startOfMonth()->format('Y-m-d');
|
|
||||||
$end = $today->endOfMonth()->format('Y-m-d');
|
|
||||||
$data = ['amount' => 200, 'start' => $start, 'end' => $end];
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->post(route('budgets.amount', [1]), $data);
|
|
||||||
$response->assertStatus(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::create
|
|
||||||
*/
|
|
||||||
public function testCreate(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testCreate()');
|
|
||||||
// mock stuff
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->get(route('budgets.create'));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
// has bread crumb
|
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::delete
|
|
||||||
*/
|
|
||||||
public function testDelete(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testDelete()');
|
|
||||||
// mock stuff
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->get(route('budgets.delete', [1]));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
// has bread crumb
|
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::destroy
|
|
||||||
*/
|
|
||||||
public function testDestroy(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testDestroy()');
|
|
||||||
// mock stuff
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
|
|
||||||
$repository->shouldReceive('destroy')->andReturn(true);
|
|
||||||
|
|
||||||
$this->session(['budgets.delete.uri' => 'http://localhost']);
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->post(route('budgets.destroy', [1]));
|
|
||||||
$response->assertStatus(302);
|
|
||||||
$response->assertSessionHas('success');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::edit
|
|
||||||
*/
|
|
||||||
public function testEdit(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testEdit()');
|
|
||||||
// mock stuff
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->get(route('budgets.edit', [1]));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
// has bread crumb
|
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::index
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::__construct
|
|
||||||
* @dataProvider dateRangeProvider
|
|
||||||
*
|
|
||||||
* @param string $range
|
|
||||||
*/
|
|
||||||
public function testIndex(string $range): void
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('Now in testIndex(%s)', $range));
|
|
||||||
// mock stuff
|
|
||||||
$budget = factory(Budget::class)->make();
|
|
||||||
$budgetLimit = factory(BudgetLimit::class)->make();
|
|
||||||
|
|
||||||
// set budget limit to current month:
|
|
||||||
$budgetLimit->start_date = Carbon::now()->startOfMonth();
|
|
||||||
$budgetLimit->end_date = Carbon::now()->endOfMonth();
|
|
||||||
$budgetInfo = [
|
|
||||||
$budget->id => [
|
|
||||||
'spent' => '0',
|
|
||||||
'budgeted' => '0',
|
|
||||||
'currentRep' => false,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
|
||||||
|
|
||||||
$repository->shouldReceive('cleanupBudgets');
|
|
||||||
$repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget]));
|
|
||||||
$repository->shouldReceive('getInactiveBudgets')->andReturn(new Collection);
|
|
||||||
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
|
|
||||||
$repository->shouldReceive('spentInPeriod')->andReturn('-1');
|
|
||||||
$repository->shouldReceive('collectBudgetInformation')->andReturn($budgetInfo);
|
|
||||||
$repository->shouldReceive('getBudgetLimits')->andReturn(new Collection([$budgetLimit]));
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$this->changeDateRange($this->user(), $range);
|
|
||||||
$response = $this->get(route('budgets.index'));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
// has bread crumb
|
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::index
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::__construct
|
|
||||||
* @dataProvider dateRangeProvider
|
|
||||||
*
|
|
||||||
* @param string $range
|
|
||||||
*/
|
|
||||||
public function testIndexWithDate(string $range): void
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('Now in testIndexWithDate(%s)', $range));
|
|
||||||
// mock stuff
|
|
||||||
$budget = factory(Budget::class)->make();
|
|
||||||
$budgetLimit = factory(BudgetLimit::class)->make();
|
|
||||||
$budgetInfo = [
|
|
||||||
$budget->id => [
|
|
||||||
'spent' => '0',
|
|
||||||
'budgeted' => '0',
|
|
||||||
'currentRep' => false,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
// set budget limit to current month:
|
|
||||||
$budgetLimit->start_date = Carbon::now()->startOfMonth();
|
|
||||||
$budgetLimit->end_date = Carbon::now()->endOfMonth();
|
|
||||||
|
|
||||||
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
|
||||||
|
|
||||||
$repository->shouldReceive('cleanupBudgets');
|
|
||||||
$repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget]));
|
|
||||||
$repository->shouldReceive('getInactiveBudgets')->andReturn(new Collection);
|
|
||||||
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
|
|
||||||
$repository->shouldReceive('spentInPeriod')->andReturn('-1');
|
|
||||||
$repository->shouldReceive('getBudgetLimits')->andReturn(new Collection([$budgetLimit]));
|
|
||||||
$repository->shouldReceive('collectBudgetInformation')->andReturn($budgetInfo);
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$this->changeDateRange($this->user(), $range);
|
|
||||||
$response = $this->get(route('budgets.index', ['2017-01-01']));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
// has bread crumb
|
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::index
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::__construct
|
|
||||||
* @dataProvider dateRangeProvider
|
|
||||||
*
|
|
||||||
* @param string $range
|
|
||||||
*/
|
|
||||||
public function testIndexOutOfRange(string $range): void
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('Now in testIndexOutOfRange(%s)', $range));
|
|
||||||
// mock stuff
|
|
||||||
$budget = factory(Budget::class)->make();
|
|
||||||
$budgetLimit = factory(BudgetLimit::class)->make();
|
|
||||||
$budgetInfo = [
|
|
||||||
$budget->id => [
|
|
||||||
'spent' => '0',
|
|
||||||
'budgeted' => '0',
|
|
||||||
'currentRep' => false,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
// set budget limit to current month:
|
|
||||||
$budgetLimit->start_date = Carbon::now()->startOfMonth();
|
|
||||||
$budgetLimit->end_date = Carbon::now()->endOfMonth();
|
|
||||||
|
|
||||||
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
|
||||||
|
|
||||||
$repository->shouldReceive('cleanupBudgets');
|
|
||||||
$repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget]));
|
|
||||||
$repository->shouldReceive('getInactiveBudgets')->andReturn(new Collection);
|
|
||||||
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
|
|
||||||
$repository->shouldReceive('spentInPeriod')->andReturn('-1');
|
|
||||||
$repository->shouldReceive('getBudgetLimits')->andReturn(new Collection([$budgetLimit]));
|
|
||||||
$repository->shouldReceive('collectBudgetInformation')->andReturn($budgetInfo);
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$today = new Carbon;
|
|
||||||
$today->startOfMonth();
|
|
||||||
$this->changeDateRange($this->user(), $range);
|
|
||||||
$response = $this->get(route('budgets.index', [$today->format('Y-m-d')]));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
// has bread crumb
|
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::index
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::__construct
|
|
||||||
* @dataProvider dateRangeProvider
|
|
||||||
*
|
|
||||||
* @param string $range
|
|
||||||
*/
|
|
||||||
public function testIndexWithInvalidDate(string $range): void
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('Now in testIndexWithInvalidDate(%s)', $range));
|
|
||||||
// mock stuff
|
|
||||||
$budget = factory(Budget::class)->make();
|
|
||||||
$budgetLimit = factory(BudgetLimit::class)->make();
|
|
||||||
|
|
||||||
// set budget limit to current month:
|
|
||||||
$budgetLimit->start_date = Carbon::now()->startOfMonth();
|
|
||||||
$budgetLimit->end_date = Carbon::now()->endOfMonth();
|
|
||||||
$budgetInfo = [
|
|
||||||
$budget->id => [
|
|
||||||
'spent' => '0',
|
|
||||||
'budgeted' => '0',
|
|
||||||
'currentRep' => false,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
|
||||||
|
|
||||||
$repository->shouldReceive('cleanupBudgets');
|
|
||||||
$repository->shouldReceive('getActiveBudgets')->andReturn(new Collection([$budget]));
|
|
||||||
$repository->shouldReceive('getInactiveBudgets')->andReturn(new Collection);
|
|
||||||
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
|
|
||||||
$repository->shouldReceive('spentInPeriod')->andReturn('-1');
|
|
||||||
$repository->shouldReceive('getBudgetLimits')->andReturn(new Collection([$budgetLimit]));
|
|
||||||
$repository->shouldReceive('collectBudgetInformation')->andReturn($budgetInfo);
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$this->changeDateRange($this->user(), $range);
|
|
||||||
$response = $this->get(route('budgets.index', ['Hello-there']));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
// has bread crumb
|
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::infoIncome
|
|
||||||
*/
|
|
||||||
public function testInfoIncome(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testInfoIncome()');
|
|
||||||
// mock stuff
|
|
||||||
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
|
|
||||||
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
|
|
||||||
$accountRepos->shouldReceive('setUser');
|
|
||||||
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->get(route('budgets.income.info', ['20170101', '20170131']));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::infoIncome
|
|
||||||
* @dataProvider dateRangeProvider
|
|
||||||
*
|
|
||||||
* @param string $range
|
|
||||||
*/
|
|
||||||
public function testInfoIncomeExpanded(string $range): void
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('Now in testInfoIncomeExpanded(%s)', $range));
|
|
||||||
// mock stuff
|
|
||||||
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$repository->shouldReceive('getAvailableBudget')->andReturn('100.123');
|
|
||||||
$accountRepos->shouldReceive('setUser');
|
|
||||||
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$this->changeDateRange($this->user(), $range);
|
|
||||||
$response = $this->get(route('budgets.income.info', ['20170301', '20170430']));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::noBudget
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::getPeriodOverview
|
|
||||||
* @dataProvider dateRangeProvider
|
|
||||||
*
|
|
||||||
* @param string $range
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function testNoBudget(string $range): void
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('Now in testNoBudget(%s)', $range));
|
|
||||||
|
|
||||||
// mock stuff
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$collector = $this->mock(JournalCollectorInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->andReturn(null);
|
|
||||||
|
|
||||||
$collector->shouldReceive('setAllAssetAccounts')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setRange')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('getJournals')->andReturn(new Collection);
|
|
||||||
$collector->shouldReceive('setLimit')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setPage')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setTypes')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('withoutBudget')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('withOpposingAccount')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('getPaginatedJournals')->andReturn(new LengthAwarePaginator([], 0, 10));
|
|
||||||
|
|
||||||
$date = new Carbon();
|
|
||||||
$this->session(['start' => $date, 'end' => clone $date]);
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$this->changeDateRange($this->user(), $range);
|
|
||||||
$response = $this->get(route('budgets.no-budget'));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
// has bread crumb
|
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::noBudget
|
|
||||||
* @dataProvider dateRangeProvider
|
|
||||||
*
|
|
||||||
* @param string $range
|
|
||||||
*/
|
|
||||||
public function testNoBudgetAll(string $range): void
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('Now in testNoBudgetAll(%s)', $range));
|
|
||||||
// mock stuff
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$collector = $this->mock(JournalCollectorInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->andReturn(null);
|
|
||||||
|
|
||||||
$collector->shouldReceive('setAllAssetAccounts')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setRange')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setLimit')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setTypes')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setPage')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('withOpposingAccount')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('withoutBudget')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setTypes')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('getJournals')->andReturn(new Collection);
|
|
||||||
$collector->shouldReceive('getPaginatedJournals')->andReturn(new LengthAwarePaginator([], 0, 10));
|
|
||||||
|
|
||||||
$date = new Carbon();
|
|
||||||
$this->session(['start' => $date, 'end' => clone $date]);
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$this->changeDateRange($this->user(), $range);
|
|
||||||
$response = $this->get(route('budgets.no-budget', ['all']));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
// has bread crumb
|
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::noBudget
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::getPeriodOverview
|
|
||||||
* @dataProvider dateRangeProvider
|
|
||||||
*
|
|
||||||
* @param string $range
|
|
||||||
*/
|
|
||||||
public function testNoBudgetDate(string $range): void
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('Now in testNoBudgetDate(%s)', $range));
|
|
||||||
// mock stuff
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$collector = $this->mock(JournalCollectorInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->andReturn(null);
|
|
||||||
|
|
||||||
$collector->shouldReceive('setAllAssetAccounts')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setRange')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('getJournals')->andReturn(new Collection);
|
|
||||||
$collector->shouldReceive('setLimit')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setPage')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('withOpposingAccount')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setTypes')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('withoutBudget')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('getPaginatedJournals')->andReturn(new LengthAwarePaginator([], 0, 10));
|
|
||||||
|
|
||||||
$date = new Carbon();
|
|
||||||
$this->session(['start' => $date, 'end' => clone $date]);
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$this->changeDateRange($this->user(), $range);
|
|
||||||
$response = $this->get(route('budgets.no-budget', ['2016-01-01']));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
// has bread crumb
|
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::postUpdateIncome
|
|
||||||
*/
|
|
||||||
public function testPostUpdateIncome(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testPostUpdateIncome()');
|
|
||||||
// mock stuff
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
$repository->shouldReceive('setAvailableBudget');
|
|
||||||
$repository->shouldReceive('cleanupBudgets');
|
|
||||||
|
|
||||||
$data = ['amount' => '200', 'start' => '2017-01-01', 'end' => '2017-01-31'];
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->post(route('budgets.income.post'), $data);
|
|
||||||
$response->assertStatus(302);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::show
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::getLimits
|
|
||||||
* @dataProvider dateRangeProvider
|
|
||||||
*
|
|
||||||
* @param string $range
|
|
||||||
*/
|
|
||||||
public function testShow(string $range): void
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('Now in testShow(%s)', $range));
|
|
||||||
// mock stuff
|
|
||||||
|
|
||||||
$budgetLimit = factory(BudgetLimit::class)->make();
|
|
||||||
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->andReturn(new TransactionJournal);
|
|
||||||
|
|
||||||
$collector = $this->mock(JournalCollectorInterface::class);
|
|
||||||
$collector->shouldReceive('setAllAssetAccounts')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setRange')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setLimit')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setPage')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setBudget')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('getPaginatedJournals')->andReturn(new LengthAwarePaginator([], 0, 10));
|
|
||||||
$collector->shouldReceive('withBudgetInformation')->andReturnSelf();
|
|
||||||
|
|
||||||
$accountRepos = $this->mock(AccountRepositoryInterface::class);
|
|
||||||
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
|
||||||
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$repository->shouldReceive('getBudgetLimits')->andReturn(new Collection([$budgetLimit]));
|
|
||||||
$repository->shouldReceive('spentInPeriod')->andReturn('-1');
|
|
||||||
|
|
||||||
$date = new Carbon();
|
|
||||||
$date->subDay();
|
|
||||||
$this->session(['first' => $date]);
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$this->changeDateRange($this->user(), $range);
|
|
||||||
$response = $this->get(route('budgets.show', [1]));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::showByBudgetLimit
|
|
||||||
* @expectedExceptionMessage This budget limit is not part of
|
|
||||||
*/
|
|
||||||
public function testShowByBadBudgetLimit(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testShowByBadBudgetLimit()');
|
|
||||||
// mock stuff
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->get(route('budgets.show.limit', [1, 8]));
|
|
||||||
$response->assertStatus(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::showByBudgetLimit()
|
|
||||||
* @dataProvider dateRangeProvider
|
|
||||||
*
|
|
||||||
* @param string $range
|
|
||||||
*/
|
|
||||||
public function testShowByBudgetLimit(string $range): void
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('Now in testShowByBudgetLimit(%s)', $range));
|
|
||||||
// mock stuff
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
|
|
||||||
// mock account repository
|
|
||||||
$accountRepository = $this->mock(AccountRepositoryInterface::class);
|
|
||||||
$accountRepository->shouldReceive('getAccountsByType')->andReturn(new Collection);
|
|
||||||
|
|
||||||
// mock budget repository
|
|
||||||
$budgetRepository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$budgetRepository->shouldReceive('spentInPeriod')->andReturn('1');
|
|
||||||
$budgetRepository->shouldReceive('getBudgetLimits')->andReturn(new Collection);
|
|
||||||
|
|
||||||
// mock journal collector:
|
|
||||||
$collector = $this->mock(JournalCollectorInterface::class);
|
|
||||||
$collector->shouldReceive('setAllAssetAccounts')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setRange')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setLimit')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setPage')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('setBudget')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('withBudgetInformation')->andReturnSelf();
|
|
||||||
$collector->shouldReceive('getPaginatedJournals')->andReturn(new LengthAwarePaginator([], 0, 10));
|
|
||||||
|
|
||||||
$this->be($this->user());
|
|
||||||
$this->changeDateRange($this->user(), $range);
|
|
||||||
$response = $this->get(route('budgets.show.limit', [1, 1]));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
// has bread crumb
|
|
||||||
$response->assertSee('<ol class="breadcrumb">');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::store
|
|
||||||
*/
|
|
||||||
public function testStore(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testStore()');
|
|
||||||
// mock stuff
|
|
||||||
$budget = factory(Budget::class)->make();
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
$repository->shouldReceive('findNull')->andReturn($budget);
|
|
||||||
$repository->shouldReceive('store')->andReturn($budget);
|
|
||||||
$repository->shouldReceive('cleanupBudgets');
|
|
||||||
|
|
||||||
$this->session(['budgets.create.uri' => 'http://localhost']);
|
|
||||||
|
|
||||||
$data = [
|
|
||||||
'name' => 'New Budget ' . random_int(1000, 9999),
|
|
||||||
];
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->post(route('budgets.store'), $data);
|
|
||||||
$response->assertStatus(302);
|
|
||||||
$response->assertSessionHas('success');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::update
|
|
||||||
*/
|
|
||||||
public function testUpdate(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testUpdate()');
|
|
||||||
// mock stuff
|
|
||||||
$budget = factory(Budget::class)->make();
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
$repository->shouldReceive('findNull')->andReturn($budget);
|
|
||||||
$repository->shouldReceive('update');
|
|
||||||
$repository->shouldReceive('cleanupBudgets');
|
|
||||||
|
|
||||||
$this->session(['budgets.edit.uri' => 'http://localhost']);
|
|
||||||
|
|
||||||
$data = [
|
|
||||||
'name' => 'Updated Budget ' . random_int(1000, 9999),
|
|
||||||
'active' => 1,
|
|
||||||
];
|
|
||||||
$this->be($this->user());
|
|
||||||
$response = $this->post(route('budgets.update', [1]), $data);
|
|
||||||
$response->assertStatus(302);
|
|
||||||
$response->assertSessionHas('success');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \FireflyIII\Http\Controllers\BudgetController::updateIncome
|
|
||||||
*/
|
|
||||||
public function testUpdateIncome(): void
|
|
||||||
{
|
|
||||||
Log::debug('Now in testUpdateIncome()');
|
|
||||||
// must be in list
|
|
||||||
$this->be($this->user());
|
|
||||||
|
|
||||||
// mock stuff
|
|
||||||
$repository = $this->mock(BudgetRepositoryInterface::class);
|
|
||||||
$journalRepos = $this->mock(JournalRepositoryInterface::class);
|
|
||||||
$journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
|
|
||||||
$repository->shouldReceive('getAvailableBudget')->andReturn('1');
|
|
||||||
$repository->shouldReceive('cleanupBudgets');
|
|
||||||
|
|
||||||
$response = $this->get(route('budgets.income', ['2017-01-01', '2017-01-31']));
|
|
||||||
$response->assertStatus(200);
|
|
||||||
}
|
|
||||||
}
|
|
@ -35,7 +35,7 @@ class FromAccountStartsTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function setUp()
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
Log::debug(sprintf('Now in %s.', \get_class($this)));
|
Log::debug(sprintf('Now in %s.', \get_class($this)));
|
||||||
@ -54,17 +54,23 @@ class FromAccountStartsTest extends TestCase
|
|||||||
$transaction = $journal->transactions()->where('amount', '<', 0)->first();
|
$transaction = $journal->transactions()->where('amount', '<', 0)->first();
|
||||||
$account = $transaction->account;
|
$account = $transaction->account;
|
||||||
$count = $journal->transactions()->count();
|
$count = $journal->transactions()->count();
|
||||||
|
$name = $account->name ?? '';
|
||||||
|
|
||||||
Log::debug(sprintf('Loop: %d, transaction count: %d, account is null: %d', $loops, $count, (int)null===$account));
|
Log::debug(sprintf('Loop: %d, transaction count: %d, account is null: %d, name = "%s"', $loops, $count, (int)null === $account, $name));
|
||||||
|
|
||||||
$loops++;
|
$loops++;
|
||||||
|
|
||||||
// do this until: account is not null, journal has two transactions, loops is below 30
|
// do this while the following is untrue:
|
||||||
} while (!(null !== $account && 2 === $count && $loops < 30));
|
// 1) account is not null,
|
||||||
|
// 2) journal has two transactions
|
||||||
|
// 3) loops is less than 30
|
||||||
|
// 4) $name is longer than 3
|
||||||
|
} while (!(null !== $account && 2 === $count && $loops < 30 && \strlen($name) > 3));
|
||||||
|
|
||||||
$trigger = FromAccountStarts::makeFromStrings(substr($account->name, 0, -3), false);
|
$trigger = FromAccountStarts::makeFromStrings(substr($account->name, 0, -3), false);
|
||||||
$result = $trigger->triggered($journal);
|
$result = $trigger->triggered($journal);
|
||||||
$this->assertTrue($result);
|
$this->assertTrue($result);
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,13 +86,18 @@ class FromAccountStartsTest extends TestCase
|
|||||||
$transaction = $journal->transactions()->where('amount', '<', 0)->first();
|
$transaction = $journal->transactions()->where('amount', '<', 0)->first();
|
||||||
$account = $transaction->account;
|
$account = $transaction->account;
|
||||||
$count = $journal->transactions()->count();
|
$count = $journal->transactions()->count();
|
||||||
|
$name = $account->name ?? '';
|
||||||
|
|
||||||
Log::debug(sprintf('Loop: %d, transaction count: %d, account is null: %d', $loops, $count, (int)null===$account));
|
Log::debug(sprintf('Loop: %d, transaction count: %d, account is null: %d, name = "%s"', $loops, $count, (int)null === $account, $name));
|
||||||
|
|
||||||
$loops++;
|
$loops++;
|
||||||
|
|
||||||
// do this until: account is not null, journal has two transactions, loops is below 30
|
// do this while the following is untrue:
|
||||||
} while (!(null !== $account && 2 === $count && $loops < 30));
|
// 1) account is not null,
|
||||||
|
// 2) journal has two transactions
|
||||||
|
// 3) loops is less than 30
|
||||||
|
// 4) $name is longer than 3
|
||||||
|
} while (!(null !== $account && 2 === $count && $loops < 30 && \strlen($name) > 3));
|
||||||
|
|
||||||
$trigger = FromAccountStarts::makeFromStrings('bla-bla-bla' . $account->name, false);
|
$trigger = FromAccountStarts::makeFromStrings('bla-bla-bla' . $account->name, false);
|
||||||
$result = $trigger->triggered($journal);
|
$result = $trigger->triggered($journal);
|
||||||
|
Loading…
Reference in New Issue
Block a user