diff --git a/app/Http/Controllers/Budget/AvailableBudgetController.php b/app/Http/Controllers/Budget/AvailableBudgetController.php new file mode 100644 index 0000000000..c6c3f60ddc --- /dev/null +++ b/app/Http/Controllers/Budget/AvailableBudgetController.php @@ -0,0 +1,209 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Http\Controllers\Budget; + + +use Carbon\Carbon; +use Carbon\Exceptions\InvalidDateException; +use FireflyIII\Http\Controllers\Controller; +use FireflyIII\Models\AvailableBudget; +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface; +use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; +use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; +use FireflyIII\Repositories\Budget\OperationsRepositoryInterface; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use Illuminate\Http\Request; +use Log; + +/** + * + * Class AvailableBudgetController + */ +class AvailableBudgetController extends Controller +{ + + /** @var AvailableBudgetRepositoryInterface */ + private $abRepository; + /** @var BudgetLimitRepositoryInterface */ + private $blRepository; + /** @var CurrencyRepositoryInterface */ + private $currencyRepos; + /** @var OperationsRepositoryInterface */ + private $opsRepository; + /** @var BudgetRepositoryInterface The budget repository */ + private $repository; + + /** + * AmountController constructor. + */ + public function __construct() + { + parent::__construct(); + + app('view')->share('hideBudgets', true); + + $this->middleware( + function ($request, $next) { + app('view')->share('title', (string)trans('firefly.budgets')); + app('view')->share('mainTitleIcon', 'fa-tasks'); + $this->repository = app(BudgetRepositoryInterface::class); + $this->opsRepository = app(OperationsRepositoryInterface::class); + $this->abRepository = app(AvailableBudgetRepositoryInterface::class); + $this->blRepository = app(BudgetLimitRepositoryInterface::class); + $this->currencyRepos = app(CurrencyRepositoryInterface::class); + + return $next($request); + } + ); + } + + /** + * Create will always assume the user's default currency, if it's not set. + * + * This method will check if there is no AB, and refuse to continue if it exists. + */ + public function create(Request $request, Carbon $start, Carbon $end, ?TransactionCurrency $currency = null) + { + $currency = $currency ?? app('amount')->getDefaultCurrency(); + $collection = $this->abRepository->get($start, $end); + $filtered = $collection->filter( + static function (AvailableBudget $budget) use ($currency) { + return $currency->id === $budget->transaction_currency_id; + } + ); + if ($filtered->count() > 0) { + /** @var AvailableBudget $first */ + $first = $filtered->first(); + + return redirect(route('available-budgets.edit', [$first->id])); + } + $page = (int)($request->get('page') ?? 1); + + return view('budgets.available-budgets.create', compact('start', 'end', 'page', 'currency')); + } + + /** + * createAlternative will show a list of enabled currencies so the user can pick one. + */ + public function createAlternative(Request $request, Carbon $start, Carbon $end) + { + $currencies = $this->currencyRepos->getEnabled(); + $availableBudgets = $this->abRepository->get($start, $end); + + // remove already budgeted currencies: + $currencies = $currencies->filter( + static function (TransactionCurrency $currency) use ($availableBudgets) { + /** @var AvailableBudget $budget */ + foreach ($availableBudgets as $budget) { + if ($budget->transaction_currency_id === $currency->id) { + return false; + } + } + return true; + } + ); + + + $page = (int)($request->get('page') ?? 1); + return view('budgets.available-budgets.create-alternative', compact('start', 'end', 'page', 'currencies')); + } + + /** + * @param AvailableBudget $availableBudget + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + */ + public function delete(AvailableBudget $availableBudget) + { + $this->abRepository->destroyAvailableBudget($availableBudget); + session()->flash('success', trans('firefly.deleted_ab')); + + return redirect(route('budgets.index')); + } + + /** + * @param AvailableBudget $availableBudget + */ + public function edit(AvailableBudget $availableBudget) + { + return view('budgets.available-budgets.edit', compact('availableBudget')); + } + + /** + * @param Request $request + */ + public function store(Request $request) + { + // make dates. + try { + $start = Carbon::createFromFormat('Y-m-d', $request->get('start')); + $end = Carbon::createFromFormat('Y-m-d', $request->get('end')); + } catch (InvalidDateException $e) { + $start = session()->get('start'); + $end = session()->get('end'); + Log::info($e->getMessage()); + } + // find currency + $currency = $this->currencyRepos->find((int)$request->get('currency_id')); + if (null === $currency) { + session()->flash('error', trans('firefly.invalid_currency')); + + return redirect(route('budgets.index')); + } + + // find existing AB + $existing = $this->abRepository->find($currency, $start, $end); + if (null === $existing) { + $this->abRepository->store( + [ + 'amount' => $request->get('amount'), + 'currency' => $currency, + 'start' => $start, + 'end' => $end, + ] + ); + } + if (null !== $existing) { + // update amount: + $this->abRepository->update($existing, ['amount' => $request->get('amount')]); + } + session()->flash('success', trans('firefly.set_ab')); + + return redirect(route('budgets.index')); + } + + /** + * @param Request $request + * @param AvailableBudget $availableBudget + */ + public function update(Request $request, AvailableBudget $availableBudget) + { + $this->abRepository->update($availableBudget, ['amount' => $request->get('amount')]); + session()->flash('success', trans('firefly.updated_ab')); + + return redirect(route('budgets.index')); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Budget/IndexController.php b/app/Http/Controllers/Budget/IndexController.php index c536e3109a..c41528a14f 100644 --- a/app/Http/Controllers/Budget/IndexController.php +++ b/app/Http/Controllers/Budget/IndexController.php @@ -26,13 +26,18 @@ namespace FireflyIII\Http\Controllers\Budget; use Carbon\Carbon; use FireflyIII\Http\Controllers\Controller; +use FireflyIII\Models\AvailableBudget; +use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface; +use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\OperationsRepositoryInterface; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\Http\Controllers\DateCalculation; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; +use Log; /** * @@ -42,12 +47,16 @@ class IndexController extends Controller { use DateCalculation; + /** @var AvailableBudgetRepositoryInterface */ + private $abRepository; + /** @var BudgetLimitRepositoryInterface */ + private $blRepository; + /** @var CurrencyRepositoryInterface */ + private $currencyRepository; /** @var OperationsRepositoryInterface */ private $opsRepository; /** @var BudgetRepositoryInterface The budget repository */ private $repository; - /** @var AvailableBudgetRepositoryInterface */ - private $abRepository; /** * IndexController constructor. @@ -64,9 +73,11 @@ class IndexController extends Controller function ($request, $next) { app('view')->share('title', (string)trans('firefly.budgets')); app('view')->share('mainTitleIcon', 'fa-tasks'); - $this->repository = app(BudgetRepositoryInterface::class); - $this->opsRepository = app(OperationsRepositoryInterface::class); - $this->abRepository = app(AvailableBudgetRepositoryInterface::class); + $this->repository = app(BudgetRepositoryInterface::class); + $this->opsRepository = app(OperationsRepositoryInterface::class); + $this->abRepository = app(AvailableBudgetRepositoryInterface::class); + $this->currencyRepository = app(CurrencyRepositoryInterface::class); + $this->blRepository = app(BudgetLimitRepositoryInterface::class); $this->repository->cleanupBudgets(); return $next($request); @@ -93,18 +104,47 @@ class IndexController extends Controller $page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page'); $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $defaultCurrency = app('amount')->getDefaultCurrency(); + $budgeted = '0'; + $spent = '0'; + // new period stuff: + $periodTitle = app('navigation')->periodShow($start, $range); - // make the next and previous period, and calculate the periods used for period navigation - $next = clone $end; - $next->addDay(); - $prev = clone $start; - $prev->subDay(); - $prev = app('navigation')->startOfPeriod($prev, $range); - $previousLoop = $this->getPreviousPeriods($start, $range); - $nextLoop = $this->getNextPeriods($start, $range); - $currentMonth = app('navigation')->periodShow($start, $range); - $nextText = app('navigation')->periodShow($next, $range); - $prevText = app('navigation')->periodShow($prev, $range); + // loop of previous periods: + $prevLoop = $this->getPreviousPeriods($start, $range); + $nextLoop = $this->getNextPeriods($start, $range); + + // get all available budgets. + $ab = $this->abRepository->get($start, $end); + $availableBudgets = []; + // for each, complement with spent amount: + /** @var AvailableBudget $entry */ + foreach ($ab as $entry) { + $array = $entry->toArray(); + $array['start_date'] = $entry->start_date; + $array['end_date'] = $entry->end_date; + + // spent in period: + $spentArr = $this->opsRepository->sumExpenses($entry->start_date, $entry->end_date, null, null, $entry->transactionCurrency); + $array['spent'] = $spentArr[$entry->transaction_currency_id]['sum'] ?? '0'; + + // budgeted in period: + $budgeted = $this->blRepository->budgeted($entry->start_date, $entry->end_date, $entry->transactionCurrency,); + $array['budgeted'] = $budgeted; + $availableBudgets[] = $array; + unset($spentArr); + } + + if (0 === count($availableBudgets)) { + // get budgeted for default currency: + $budgeted = $this->blRepository->budgeted($start, $end, $defaultCurrency,); + $spentArr = $this->opsRepository->sumExpenses($start, $end, null, null, $defaultCurrency); + $spent = $spentArr[$defaultCurrency->id]['sum'] ?? '0'; + unset($spentArr); + } + + // count the number of enabled currencies. This determines if we display a "+" button. + $currencies = $this->currencyRepository->getEnabled(); + $enableAddButton = $currencies->count() > count($availableBudgets); // number of days for consistent budgeting. $activeDaysPassed = $this->activeDaysPassed($start, $end); // see method description. @@ -118,14 +158,6 @@ class IndexController extends Controller // get all inactive budgets, and simply list them: $inactive = $this->repository->getInactiveBudgets(); - // collect budget info to fill bars and so on. - $budgetInformation = $this->opsRepository->collectBudgetInformation($collection, $start, $end); - - // to display available budget: - $available = $this->abRepository->getAvailableBudget($defaultCurrency, $start, $end); - $spent = array_sum(array_column($budgetInformation, 'spent')); - $budgeted = array_sum(array_column($budgetInformation, 'budgeted')); - // paginate budgets $paginator = new LengthAwarePaginator($budgets, $total, $pageSize, $page); @@ -133,11 +165,18 @@ class IndexController extends Controller return view( 'budgets.index', compact( - 'available', 'currentMonth', 'next', 'nextText', 'prev', 'paginator', - 'prevText', + 'availableBudgets', + //'available', + //'currentMonth', 'next', 'nextText', 'prev', + //'prevText', 'previousLoop', 'nextLoop', + 'budgeted', 'spent', + 'prevLoop', 'nextLoop', + 'paginator', + 'enableAddButton', + 'periodTitle', + 'defaultCurrency', 'page', 'activeDaysPassed', 'activeDaysLeft', - 'budgetInformation', - 'inactive', 'budgets', 'spent', 'budgeted', 'previousLoop', 'nextLoop', 'start', 'end' + 'inactive', 'budgets', 'start', 'end' ) ); } @@ -160,6 +199,7 @@ class IndexController extends Controller $budgetId = (int)$budgetId; $budget = $repository->findNull($budgetId); if (null !== $budget) { + Log::debug(sprintf('Set budget #%d ("%s") to position %d', $budget->id, $budget->name, $currentOrder)); $repository->setBudgetOrder($budget, $currentOrder); } $currentOrder++; diff --git a/app/Repositories/Budget/AvailableBudgetRepository.php b/app/Repositories/Budget/AvailableBudgetRepository.php index 9ed3832d74..c4d1c4a9d2 100644 --- a/app/Repositories/Budget/AvailableBudgetRepository.php +++ b/app/Repositories/Budget/AvailableBudgetRepository.php @@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\AvailableBudget; use FireflyIII\Models\TransactionCurrency; use FireflyIII\User; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; use Log; @@ -64,6 +65,48 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface } } + /** + * Find existing AB. + * + * @param TransactionCurrency $currency + * @param Carbon $start + * @param Carbon $end + * + * @return AvailableBudget|null + */ + public function find(TransactionCurrency $currency, Carbon $start, Carbon $end): ?AvailableBudget + { + return $this->user->availableBudgets() + ->where('transaction_currency_id', $currency->id) + ->where('start_date', $start->format('Y-m-d 00:00:00')) + ->where('end_date', $end->format('Y-m-d 00:00:00')) + ->first(); + + } + + /** + * Return a list of all available budgets (in all currencies) (for the selected period). + * + * @param Carbon|null $start + * @param Carbon|null $end + * + * @return Collection + */ + public function get(?Carbon $start = null, ?Carbon $end = null): Collection + { + $query = $this->user->availableBudgets()->with(['transactionCurrency']); + if (null !== $start && null !== $end) { + $query->where( + static function (Builder $q1) use ($start, $end) { + $q1->where('start_date', '=', $start->format('Y-m-d 00:00:00')); + $q1->where('end_date', '=', $end->format('Y-m-d 00:00:00')); + } + ); + } + + return $query->get(['available_budgets.*']); + } + /** * @param TransactionCurrency $currency * @param Carbon $start @@ -140,7 +183,6 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface return $query->get(); } - /** * @param TransactionCurrency $currency * @param Carbon $start @@ -176,6 +218,41 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface $this->user = $user; } + /** + * @param array $data + * + * @return AvailableBudget|null + */ + public function store(array $data): ?AvailableBudget + { + return AvailableBudget::create( + [ + 'user_id' => $this->user->id, + 'transaction_currency_id' => $data['currency']->id, + 'amount' => $data['amount'], + 'start_date' => $data['start'], + 'end_date' => $data['end'], + + ] + ); + } + + /** + * @param AvailableBudget $availableBudget + * @param array $data + * + * @return AvailableBudget + */ + public function update(AvailableBudget $availableBudget, array $data): AvailableBudget + { + if (isset($data['amount'])) { + $availableBudget->amount = $data['amount']; + } + $availableBudget->save(); + + return $availableBudget; + } + /** * @param AvailableBudget $availableBudget * @param array $data @@ -204,6 +281,4 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface return $availableBudget; } - - } \ No newline at end of file diff --git a/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php b/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php index dcdefd9818..66a76955a4 100644 --- a/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php +++ b/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php @@ -39,15 +39,52 @@ interface AvailableBudgetRepositoryInterface */ public function destroyAvailableBudget(AvailableBudget $availableBudget): void; + /** + * Return a list of all available budgets (in all currencies) (for the selected period). + * + * @param Carbon|null $start + * @param Carbon|null $end + * + * @return Collection + */ + public function get(?Carbon $start = null, ?Carbon $end = null): Collection; + /** * @param TransactionCurrency $currency * @param Carbon $start * @param Carbon $end * * @return string + * @deprecated */ public function getAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end): string; + /** + * @param array $data + * + * @return AvailableBudget|null + */ + public function store(array $data): ?AvailableBudget; + + /** + * @param AvailableBudget $availableBudget + * @param array $data + * + * @return AvailableBudget + */ + public function update(AvailableBudget $availableBudget, array $data): AvailableBudget; + + /** + * Find existing AB. + * + * @param TransactionCurrency $currency + * @param Carbon $start + * @param Carbon $end + * + * @return AvailableBudget|null + */ + public function find(TransactionCurrency $currency, Carbon $start, Carbon $end): ?AvailableBudget; + /** * @param Carbon $start * @param Carbon $end diff --git a/app/Repositories/Budget/BudgetLimitRepository.php b/app/Repositories/Budget/BudgetLimitRepository.php index 9ca5ace1ea..2de5bea6f3 100644 --- a/app/Repositories/Budget/BudgetLimitRepository.php +++ b/app/Repositories/Budget/BudgetLimitRepository.php @@ -55,6 +55,36 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface } } + /** + * Tells you which amount has been budgeted (for the given budgets) + * in the selected query. Returns a positive amount as a string. + * + * @param Carbon $start + * @param Carbon $end + * @param TransactionCurrency $currency + * @param Collection|null $budgets + * + * @return string + */ + public function budgeted(Carbon $start, Carbon $end, TransactionCurrency $currency, ?Collection $budgets = null): string + { + $query = BudgetLimit + ::where('start_date', $start->format('Y-m-d 00:00:00')) + ->where('end_date', $end->format('Y-m-d 00:00:00')) + ->where('transaction_currency_id', $currency->id); + if (null !== $budgets && $budgets->count() > 0) { + $query->whereIn('budget_id', $budgets->pluck('id')->toArray()); + } + $set = $query->get(['budget_limits.*']); + $result = '0'; + /** @var BudgetLimit $budgetLimit */ + foreach ($set as $budgetLimit) { + $result = bcadd($budgetLimit->amount, $result); + } + + return $result; + } + /** * Destroy a budget limit. * @@ -142,7 +172,6 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface return $set; } - /** * @param TransactionCurrency $currency * @param Carbon $start @@ -159,7 +188,6 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface ); } - /** * @param Budget $budget * @param Carbon $start diff --git a/app/Repositories/Budget/BudgetLimitRepositoryInterface.php b/app/Repositories/Budget/BudgetLimitRepositoryInterface.php index 7e4d249e68..e92bf4a736 100644 --- a/app/Repositories/Budget/BudgetLimitRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetLimitRepositoryInterface.php @@ -82,6 +82,19 @@ interface BudgetLimitRepositoryInterface */ public function storeBudgetLimit(array $data): BudgetLimit; + /** + * Tells you which amount has been budgeted (for the given budgets) + * in the selected query. Returns a positive amount as a string. + * + * @param Carbon $start + * @param Carbon $end + * @param TransactionCurrency $currency + * @param Collection|null $budgets + * + * @return string + */ + public function budgeted(Carbon $start, Carbon $end, TransactionCurrency $currency, ?Collection $budgets = null): string; + /** * @param BudgetLimit $budgetLimit * @param array $data diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index 167ff56fd0..f4e8abeb2e 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -28,6 +28,7 @@ use FireflyIII\Models\Budget; use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleTrigger; +use FireflyIII\Models\TransactionCurrency; use FireflyIII\Services\Internal\Destroy\BudgetDestroyService; use FireflyIII\User; use Illuminate\Support\Collection; @@ -192,7 +193,7 @@ class BudgetRepository implements BudgetRepositoryInterface { /** @var Collection $set */ $set = $this->user->budgets()->where('active', 1) - ->orderBy('order', 'DESC') + ->orderBy('order', 'ASC') ->orderBy('name', 'ASC') ->get(); diff --git a/app/Repositories/Budget/OperationsRepository.php b/app/Repositories/Budget/OperationsRepository.php index 7400220087..57b4afa01a 100644 --- a/app/Repositories/Budget/OperationsRepository.php +++ b/app/Repositories/Budget/OperationsRepository.php @@ -29,6 +29,7 @@ use FireflyIII\Models\AccountType; use FireflyIII\Models\Budget; use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\User; use Illuminate\Support\Collection; @@ -61,7 +62,6 @@ class OperationsRepository implements OperationsRepositoryInterface * @param Budget $budget * * @return string - * @deprecated */ public function budgetedPerDay(Budget $budget): string { @@ -278,6 +278,53 @@ class OperationsRepository implements OperationsRepositoryInterface return $return; } + /** @noinspection MoreThanThreeArgumentsInspection */ + /** + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $budgets + * @param TransactionCurrency|null $currency + * + * @return array + */ + public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null, ?TransactionCurrency $currency = null + ): array { + + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL]); + + if (null !== $accounts && $accounts->count() > 0) { + $collector->setAccounts($accounts); + } + if (null === $budgets || (null !== $budgets && 0 === $budgets->count())) { + $budgets = $this->getBudgets(); + } + if (null !== $currency) { + $collector->setCurrency($currency); + } + $collector->setBudgets($budgets); + $collector->withBudgetInformation(); + $journals = $collector->getExtractedJournals(); + $array = []; + + foreach ($journals as $journal) { + $currencyId = (int)$journal['currency_id']; + $array[$currencyId] = $array[$currencyId] ?? [ + 'sum' => '0', + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; + $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($journal['amount'])); + } + + return $array; + } + /** * For now, simply refer to whichever repository holds this function. * TODO might be done better in the future. @@ -295,4 +342,15 @@ class OperationsRepository implements OperationsRepositoryInterface return $blRepository->getBudgetLimits($budget, $start, $end); } + + /** + * @return Collection + */ + private function getBudgets(): Collection + { + /** @var BudgetRepositoryInterface $repos */ + $repos = app(BudgetRepositoryInterface::class); + + return $repos->getActiveBudgets(); + } } \ No newline at end of file diff --git a/app/Repositories/Budget/OperationsRepositoryInterface.php b/app/Repositories/Budget/OperationsRepositoryInterface.php index ad40bdc3af..e66d5c8809 100644 --- a/app/Repositories/Budget/OperationsRepositoryInterface.php +++ b/app/Repositories/Budget/OperationsRepositoryInterface.php @@ -25,6 +25,7 @@ namespace FireflyIII\Repositories\Budget; use Carbon\Carbon; use FireflyIII\Models\Budget; +use FireflyIII\Models\TransactionCurrency; use FireflyIII\User; use Illuminate\Support\Collection; @@ -40,10 +41,11 @@ interface OperationsRepositoryInterface * @param Budget $budget * * @return string - * @deprecated */ public function budgetedPerDay(Budget $budget): string; + + /** * This method collects various info on budgets, used on the budget page and on the index. * @@ -96,4 +98,17 @@ interface OperationsRepositoryInterface */ public function spentInPeriodMc(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array; + /** @noinspection MoreThanThreeArgumentsInspection */ + /** + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $budgets + * @param TransactionCurrency|null $currency + * + * @return array + */ + public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null, ?TransactionCurrency $currency = null + ): array; + } \ No newline at end of file diff --git a/app/Repositories/Category/OperationsRepository.php b/app/Repositories/Category/OperationsRepository.php index fc44bb7eeb..76f05b27e9 100644 --- a/app/Repositories/Category/OperationsRepository.php +++ b/app/Repositories/Category/OperationsRepository.php @@ -228,6 +228,7 @@ class OperationsRepository implements OperationsRepositoryInterface $categories = $this->getCategories(); } $collector->setCategories($categories); + $collector->withCategoryInformation(); $journals = $collector->getExtractedJournals(); $array = []; diff --git a/app/Repositories/Currency/CurrencyRepository.php b/app/Repositories/Currency/CurrencyRepository.php index 3c52510fe6..9ef3de89d9 100644 --- a/app/Repositories/Currency/CurrencyRepository.php +++ b/app/Repositories/Currency/CurrencyRepository.php @@ -392,6 +392,16 @@ class CurrencyRepository implements CurrencyRepositoryInterface return TransactionCurrency::orderBy('code', 'ASC')->get(); } + + /** + * @return Collection + */ + public function getEnabled(): Collection + { + return TransactionCurrency::where('enabled',true)->orderBy('code', 'ASC')->get(); + } + + /** * @param array $ids * diff --git a/app/Repositories/Currency/CurrencyRepositoryInterface.php b/app/Repositories/Currency/CurrencyRepositoryInterface.php index 4d3d929467..5b0832832b 100644 --- a/app/Repositories/Currency/CurrencyRepositoryInterface.php +++ b/app/Repositories/Currency/CurrencyRepositoryInterface.php @@ -34,12 +34,6 @@ use Illuminate\Support\Collection; */ interface CurrencyRepositoryInterface { - /** - * @param string $search - * @return Collection - */ - public function searchCurrency(string $search): Collection; - /** * @param TransactionCurrency $currency * @@ -200,6 +194,11 @@ interface CurrencyRepositoryInterface */ public function getCurrencyByPreference(Preference $preference): TransactionCurrency; + /** + * @return Collection + */ + public function getEnabled(): Collection; + /** * Get currency exchange rate. * @@ -220,6 +219,13 @@ interface CurrencyRepositoryInterface */ public function getExchangeRates(TransactionCurrency $currency): Collection; + /** + * @param string $search + * + * @return Collection + */ + public function searchCurrency(string $search): Collection; + /** * @param User $user */ diff --git a/app/Support/Http/Controllers/DateCalculation.php b/app/Support/Http/Controllers/DateCalculation.php index fb2c5938fd..4f44ec8f42 100644 --- a/app/Support/Http/Controllers/DateCalculation.php +++ b/app/Support/Http/Controllers/DateCalculation.php @@ -122,9 +122,17 @@ trait DateCalculation $count = 0; while ($count < 12) { - $format = $current->format('Y-m-d'); - $loop[$format] = app('navigation')->periodShow($current, $range); - $current = app('navigation')->endOfPeriod($current, $range); + $current = app('navigation')->endOfPeriod($current, $range); + $currentStart = app('navigation')->startOfPeriod($current, $range); + + $loop[] = [ + 'label' => $current->format('Y-m-d'), + 'title' => app('navigation')->periodShow($current, $range), + 'start' => clone $currentStart, + 'end' => clone $current, + ]; + + ++$count; $current->addDay(); } @@ -150,9 +158,14 @@ trait DateCalculation $count = 0; while ($count < 12) { $current->subDay(); - $current = app('navigation')->startOfPeriod($current, $range); - $format = $current->format('Y-m-d'); - $loop[$format] = app('navigation')->periodShow($current, $range); + $current = app('navigation')->startOfPeriod($current, $range); + $currentEnd = app('navigation')->endOfPeriod($current, $range); + $loop[] = [ + 'label' => $current->format('Y-m-d'), + 'title' => app('navigation')->periodShow($current, $range), + 'start' => clone $current, + 'end' => clone $currentEnd, + ]; ++$count; } diff --git a/app/Support/Twig/AmountFormat.php b/app/Support/Twig/AmountFormat.php index 2e75a264fd..9385b681d7 100644 --- a/app/Support/Twig/AmountFormat.php +++ b/app/Support/Twig/AmountFormat.php @@ -143,7 +143,7 @@ class AmountFormat extends Twig_Extension { return new Twig_SimpleFilter( 'formatAmountPlain', - function (string $string): string { + static function (string $string): string { $currency = app('amount')->getDefaultCurrency(); return app('amount')->formatAnything($currency, $string, false); diff --git a/public/v1/js/ff/budgets/index.js b/public/v1/js/ff/budgets/index.js index 34642d15d0..2e68214085 100644 --- a/public/v1/js/ff/budgets/index.js +++ b/public/v1/js/ff/budgets/index.js @@ -18,31 +18,33 @@ * along with Firefly III. If not, see . */ -/** global: infoIncomeUri, page, token, spent, budgeted, available, currencySymbol, budgetIndexUri, updateIncomeUri, periodStart, periodEnd, budgetAmountUri, accounting */ /** * */ $(function () { "use strict"; - $('.updateIncome').on('click', updateIncome); + //$('.updateIncome').on('click', updateIncome); /* On start, fill the "spent"-bar using the content from the page. */ - drawSpentBar(); - drawBudgetedBar(); + //drawSpentBar(); + //drawBudgetedBar(); + + $('.update_ab').on('click', updateAvailableBudget) + $('.create_ab_alt').on('click', createAltAvailableBudget) /* When the input changes, update the percentages for the budgeted bar: */ - $('input[type="number"]').on('change', updateBudgetedAmounts); + //$('input[type="number"]').on('change', updateBudgetedAmounts); - // $('.selectPeriod').change(function (e) { - var sel = $(e.target).val(); - if (sel !== "x") { - var newUri = budgetIndexUri.replace("REPLACE", sel); + var selected = $(e.currentTarget); + if (selected.find(":selected").val() !== "x") { + var newUri = budgetIndexUri.replace("START", selected.find(":selected").data('start')).replace('END', selected.find(":selected").data('end')); + console.log(newUri); window.location.assign(newUri + "?page=" + page); } }); @@ -91,7 +93,6 @@ var fixHelper = function (e, tr) { function sortStop(event, ui) { "use strict"; - //var current = $(ui.item); var list = $('.sortable-table tbody tr'); var submit = []; @@ -109,132 +110,157 @@ function sortStop(event, ui) { }; $.post('budgets/reorder', arr); } - - -function drawSpentBar() { - "use strict"; - if ($('.spentBar').length > 0) { - var overspent = spent > budgeted; - var pct; - - if (overspent) { - // draw overspent bar - pct = (budgeted / spent) * 100; - $('.spentBar .progress-bar-warning').css('width', pct + '%'); - $('.spentBar .progress-bar-danger').css('width', (100 - pct) + '%'); - } else { - // draw normal bar: - pct = (spent / budgeted) * 100; - $('.spentBar .progress-bar-info').css('width', pct + '%'); - } - } -} - -function drawBudgetedBar() { - "use strict"; - - if ($('.budgetedBar').length > 0) { - var budgetedMuch = budgeted > available; - - // recalculate percentage: - - var pct; - if (budgetedMuch) { - // budgeted too much. - pct = (available / budgeted) * 100; - $('.budgetedBar .progress-bar-warning').css('width', pct + '%'); - $('.budgetedBar .progress-bar-danger').css('width', (100 - pct) + '%'); - $('.budgetedBar .progress-bar-info').css('width', 0); - } else { - pct = (budgeted / available) * 100; - $('.budgetedBar .progress-bar-warning').css('width', 0); - $('.budgetedBar .progress-bar-danger').css('width', 0); - $('.budgetedBar .progress-bar-info').css('width', pct + '%'); - } - - $('#budgetedAmount').html(currencySymbol + ' ' + budgeted.toFixed(2)); - } -} - -/** - * - * @param e - */ -function updateBudgetedAmounts(e) { - "use strict"; - var target = $(e.target); - var id = target.data('id'); - var leftCell = $('td[class$="left"][data-id="' + id + '"]'); - var link = $('a[data-id="' + id + '"][class="budget-link"]'); - var value = target.val(); - var original = target.data('original'); - - // disable input - target.prop('disabled', true); - - // replace link (for now) - link.attr('href', '#'); - - // replace "left" with spinner. - leftCell.empty().html(''); - - // send a post to Firefly to update the amount: - var newUri = budgetAmountUri.replace("REPLACE", id); - - $.post(newUri, {amount: value, start: periodStart, end: periodEnd, _token: token}).done(function (data) { - - // difference between new value and original value - var difference = value - original; - - // update budgeted value - budgeted = budgeted + difference; - - // fill in "left" value: - - - if (data.left_per_day !== null) { - leftCell.html(data.left + ' (' + data.left_per_day + ')'); - } else { - leftCell.html(data.left); - } - - // update "budgeted" input: - target.val(data.amount); - - // enable thing again - target.prop('disabled', false); - - // set new original value: - target.data('original', data.amount); - - // run drawBudgetedBar() again: - drawBudgetedBar(); - - // update the link if relevant: - link.attr('href', 'budgets/show/' + id); - if (data.limit > 0) { - link.attr('href', 'budgets/show/' + id + '/' + data.limit); - } - - // update the warning if relevant: - if (data.large_diff === true) { - $('span[class$="budget_warning"][data-id="' + id + '"]').html(data.warn_text).show(); - console.log('Show warning for budget'); - } else { - $('span[class$="budget_warning"][data-id="' + id + '"]').empty().hide(); - } - }); -} - -/** - * - * @returns {boolean} - */ -function updateIncome() { - "use strict"; - $('#defaultModal').empty().load(updateIncomeUri, function () { - $('#defaultModal').modal('show'); - }); - +function createAltAvailableBudget(e) { + var button = $(e.currentTarget); + $('#defaultModal').empty().load(createAltAvailableBudgetUri, function () { + $('#defaultModal').modal('show'); + }); return false; } +function updateAvailableBudget(e) { + var button = $(e.currentTarget); + var abId = parseInt(button.data('id')); + if (0 === abId) { + $('#defaultModal').empty().load(createAvailableBudgetUri, function () { + $('#defaultModal').modal('show'); + }); + } + if (abId > 0) { + // edit URL. + $('#defaultModal').empty().load(editAvailableBudgetUri.replace('REPLACEME', abId), function () { + $('#defaultModal').modal('show'); + }); + } + return false; +} + + +// +// +// function drawSpentBar() { +// "use strict"; +// if ($('.spentBar').length > 0) { +// var overspent = spent > budgeted; +// var pct; +// +// if (overspent) { +// // draw overspent bar +// pct = (budgeted / spent) * 100; +// $('.spentBar .progress-bar-warning').css('width', pct + '%'); +// $('.spentBar .progress-bar-danger').css('width', (100 - pct) + '%'); +// } else { +// // draw normal bar: +// pct = (spent / budgeted) * 100; +// $('.spentBar .progress-bar-info').css('width', pct + '%'); +// } +// } +// } +// +// function drawBudgetedBar() { +// "use strict"; +// +// if ($('.budgetedBar').length > 0) { +// var budgetedMuch = budgeted > available; +// +// // recalculate percentage: +// +// var pct; +// if (budgetedMuch) { +// // budgeted too much. +// pct = (available / budgeted) * 100; +// $('.budgetedBar .progress-bar-warning').css('width', pct + '%'); +// $('.budgetedBar .progress-bar-danger').css('width', (100 - pct) + '%'); +// $('.budgetedBar .progress-bar-info').css('width', 0); +// } else { +// pct = (budgeted / available) * 100; +// $('.budgetedBar .progress-bar-warning').css('width', 0); +// $('.budgetedBar .progress-bar-danger').css('width', 0); +// $('.budgetedBar .progress-bar-info').css('width', pct + '%'); +// } +// +// $('#budgetedAmount').html(currencySymbol + ' ' + budgeted.toFixed(2)); +// } +// } + +// /** +// * +// * @param e +// */ +// function updateBudgetedAmounts(e) { +// "use strict"; +// var target = $(e.target); +// var id = target.data('id'); +// var leftCell = $('td[class$="left"][data-id="' + id + '"]'); +// var link = $('a[data-id="' + id + '"][class="budget-link"]'); +// var value = target.val(); +// var original = target.data('original'); +// +// // disable input +// target.prop('disabled', true); +// +// // replace link (for now) +// link.attr('href', '#'); +// +// // replace "left" with spinner. +// leftCell.empty().html(''); +// +// // send a post to Firefly to update the amount: +// var newUri = budgetAmountUri.replace("REPLACE", id); +// +// $.post(newUri, {amount: value, start: periodStart, end: periodEnd, _token: token}).done(function (data) { +// +// // difference between new value and original value +// var difference = value - original; +// +// // update budgeted value +// budgeted = budgeted + difference; +// +// // fill in "left" value: +// +// +// if (data.left_per_day !== null) { +// leftCell.html(data.left + ' (' + data.left_per_day + ')'); +// } else { +// leftCell.html(data.left); +// } +// +// // update "budgeted" input: +// target.val(data.amount); +// +// // enable thing again +// target.prop('disabled', false); +// +// // set new original value: +// target.data('original', data.amount); +// +// // run drawBudgetedBar() again: +// drawBudgetedBar(); +// +// // update the link if relevant: +// link.attr('href', 'budgets/show/' + id); +// if (data.limit > 0) { +// link.attr('href', 'budgets/show/' + id + '/' + data.limit); +// } +// +// // update the warning if relevant: +// if (data.large_diff === true) { +// $('span[class$="budget_warning"][data-id="' + id + '"]').html(data.warn_text).show(); +// console.log('Show warning for budget'); +// } else { +// $('span[class$="budget_warning"][data-id="' + id + '"]').empty().hide(); +// } +// }); +// } + +// /** +// * +// * @returns {boolean} +// */ +// function updateIncome() { +// "use strict"; +// $('#defaultModal').empty().load(updateIncomeUri, function () { +// $('#defaultModal').modal('show'); +// }); +// +// return false; +// } diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index 91ed837e70..54d67146d3 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -670,14 +670,25 @@ return [ 'options' => 'Options', // budgets: + 'total_available_budget' => 'Total available budget (between :start and :end)', + 'total_available_budget_in_currency' => 'Total available budget in :currency', + 'see_below' => 'see below', 'create_new_budget' => 'Create a new budget', 'store_new_budget' => 'Store new budget', 'stored_new_budget' => 'Stored new budget ":name"', 'available_between' => 'Available between :start and :end', 'transactionsWithoutBudget' => 'Expenses without budget', 'transactions_no_budget' => 'Expenses without budget between :start and :end', - 'spent_between' => 'Spent between :start and :end', + 'spent_between' => 'Already spent between :start and :end', + 'set_available_amount' => 'Set available amount', + 'update_available_amount' => 'Update available amount', + 'ab_basic_modal_explain' => 'Use this form to indicate how much you expect to be able to budget (in total, in :currency) in the indicated period.', 'createBudget' => 'New budget', + 'invalid_currency' => 'This is an invalid currency', + 'set_ab' => 'The available budget amount has been set', + 'updated_ab' => 'The available budget amount has been updated', + 'deleted_ab' => 'The available budget amount has been deleted', + 'alt_currency_ab_create' => 'Set the available budget in another currency', 'inactiveBudgets' => 'Inactive budgets', 'without_budget_between' => 'Transactions without a budget between :start and :end', 'delete_budget' => 'Delete budget ":name"', diff --git a/resources/views/v1/budgets/available-budgets/create-alternative.twig b/resources/views/v1/budgets/available-budgets/create-alternative.twig new file mode 100644 index 0000000000..a2273da364 --- /dev/null +++ b/resources/views/v1/budgets/available-budgets/create-alternative.twig @@ -0,0 +1,38 @@ + + diff --git a/resources/views/v1/budgets/available-budgets/create.twig b/resources/views/v1/budgets/available-budgets/create.twig new file mode 100644 index 0000000000..525099a349 --- /dev/null +++ b/resources/views/v1/budgets/available-budgets/create.twig @@ -0,0 +1,37 @@ + + diff --git a/resources/views/v1/budgets/available-budgets/edit.twig b/resources/views/v1/budgets/available-budgets/edit.twig new file mode 100644 index 0000000000..b25add6acc --- /dev/null +++ b/resources/views/v1/budgets/available-budgets/edit.twig @@ -0,0 +1,33 @@ + + diff --git a/resources/views/v1/budgets/index.twig b/resources/views/v1/budgets/index.twig index 678fd394f4..e7b4287f6f 100644 --- a/resources/views/v1/budgets/index.twig +++ b/resources/views/v1/budgets/index.twig @@ -5,92 +5,7 @@ {% endblock %} {% block content %} -
-
-
-
-

{{ start.formatLocalized(monthAndDayFormat) }} — {{ end.formatLocalized(monthAndDayFormat) }}

-
-
-
-
- {{ 'budgeted'|_ }}: {{ budgeted|formatAmountPlain }} -
-
- {{ trans('firefly.available_between',{start: start.formatLocalized(monthAndDayFormat), end: end.formatLocalized(monthAndDayFormat) }) }} - : - {{ available|formatAmountPlain }} - - -
-
- -
-
-
-
-
-
-
-
-
-
-
- {{ trans('firefly.spent_between', {start: start.formatLocalized(monthAndDayFormat), end: end.formatLocalized(monthAndDayFormat)}) }} - : {{ spent|formatAmount }} -
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
- - {% if paginator.count > 0 and inactive.count > 0 %} -
-
-

{{ 'createBudget'|_ }}

-
- -
- {% endif %} -
-
- {% if paginator.count == 0 and inactive.count == 0 and page == 1 %} - {% include 'partials.empty' with {objectType: 'default', type: 'budgets',route: route('budgets.create')} %} - {# make FF ignore demo for now. #} - {% set shownDemo = true %} - {% endif %} - - {# date thing #} +
@@ -102,23 +17,29 @@
@@ -127,6 +48,209 @@
+ + {% if availableBudgets|length == 0 %} +
+
+
+
+

+ {{ trans('firefly.total_available_budget_in_currency', {currency: defaultCurrency.name}) }} +
+ {{ trans('firefly.between_dates_breadcrumb', {start: start.formatLocalized(monthAndDayFormat), end: end.formatLocalized(monthAndDayFormat)}) }} +

+
+
+
+ {# info about the amount budgeted #} +
+ {{ 'budgeted'|_ }} ({{ 'see_below'|_ }}): + + {{ formatAmountBySymbol(budgeted, defaultCurrency.symbol, defaultCurrency.decimal_places) }} + + +
+ {# info about the amount spent #} +
+ {{ trans('firefly.available_between', {start: start.formatLocalized(monthAndDayFormat), end: end.formatLocalized(monthAndDayFormat) }) }} + : + {{ formatAmountBySymbol(0, defaultCurrency.symbol, defaultCurrency.decimal_places, true) }} + + +
+
+ {# info text to show how much is spent (in currency). #} +
+
+ {{ trans('firefly.spent_between', {start: start.formatLocalized(monthAndDayFormat), end: end.formatLocalized(monthAndDayFormat)}) }} + : {{ formatAmountBySymbol(spent, defaultCurrency.symbol, defaultCurrency.decimal_places) }} +
+
+
+
+ {% if enableAddButton %} + + {% endif %} +
+
+ {% endif %} + + {% set boxSize = 12 %} + {% if availableBudgets|length > 1 %} + {% set boxSize = 6 %} + {% endif %} + {% if availableBudgets|length > 0 %} +
+ {% for budget in availableBudgets %} +
+
+
+

+ {{ trans('firefly.total_available_budget_in_currency', {currency: budget.transaction_currency.name}) }} +
+ {{ trans('firefly.between_dates_breadcrumb', {start: budget.start_date.formatLocalized(monthAndDayFormat), end: budget.end_date.formatLocalized(monthAndDayFormat)}) }} +

+
+
+
+ {# info about the amount budgeted #} +
+ {{ 'budgeted'|_ }}: + + {{ formatAmountBySymbol(budget.budgeted, budget.transaction_currency.symbol, budget.transaction_currency.decimal_places, false) }} + + +
+ {# info about the amount spent #} +
+ {{ trans('firefly.available_between', {start: budget.start_date.formatLocalized(monthAndDayFormat), end: budget.end_date.formatLocalized(monthAndDayFormat) }) }} + : + {{ formatAmountBySymbol(budget.amount, budget.transaction_currency.symbol, budget.transaction_currency.decimal_places, true) }} + + + +
+
+ {# progresss bar to visualise available vs budgeted. #} +
+
+
+
+
+
+
+
+
+ {# info text to show how much is spent (in currency). #} +
+
+ {{ trans('firefly.spent_between', {start: budget.start_date.formatLocalized(monthAndDayFormat), end: budget.start_date.formatLocalized(monthAndDayFormat)}) }} + : {{ formatAmountBySymbol(budget.spent, budget.transaction_currency.symbol, budget.transaction_currency.decimal_places) }} +
+
+ + {# bar to visualise spending in budget .#} +
+
+
+
+
+
+
+
+
+
+
+
+ {% endfor %} + {% if enableAddButton %} + + {% endif %} +
+ {% endif %} + {# +
+
+ {{ 'budgeted'|_ }}: {{ "-1"|formatAmountPlain }}{{ budgeted|formatAmountPlain }} +
+
+ {{ trans('firefly.available_between',{start: start.formatLocalized(monthAndDayFormat), end: end.formatLocalized(monthAndDayFormat) }) }} + : + {{ "-1"|formatAmountPlain }}{{ available|formatAmountPlain }} + + +
+
+ +
+
+
+
+
+
+
+
+
+
+
+ {{ trans('firefly.spent_between', {start: start.formatLocalized(monthAndDayFormat), end: end.formatLocalized(monthAndDayFormat)}) }} + : {{ "-1"|formatAmount }}{{ spent|formatAmount }} +
+
+
+
+
+
+
+
+
+
+
+ + + +#} + {% if paginator.count == 0 and inactive.count == 0 and page == 1 %} + {% include 'partials.empty' with {objectType: 'default', type: 'budgets',route: route('budgets.create')} %} + {# make FF ignore demo for now. #} + {% set shownDemo = true %} + {% endif %} + +
@@ -162,6 +286,7 @@
+ {% if budgetInformation[budget.id]['currentLimit'] %} - {{ budgetInformation[budget.id]['spent']|formatAmount }} - ({{ (budgetInformation[budget.id]['spent'] / activeDaysPassed)|formatAmount }}) + {{ "-1"|formatAmount }} + {#{{ budgetInformation[budget.id]['spent']|formatAmount }}#} + ({{ "-1"|formatAmount }}) + {#({{ (budgetInformation[budget.id]['spent'] / activeDaysPassed)|formatAmount }})#} - {{ (repAmount + budgetInformation[budget.id]['spent'])|formatAmount }} + {{ "-1"|formatAmount }} + {#{{ (repAmount + budgetInformation[budget.id]['spent'])|formatAmount }}#} {% if repAmount + budgetInformation[budget.id]['spent'] > 0 %} - ({{ ((repAmount + budgetInformation[budget.id]['spent']) / activeDaysLeft)|formatAmount }}) + ({{ "-1"|formatAmount }}) + {#({{ ((repAmount + budgetInformation[budget.id]['spent']) / activeDaysLeft)|formatAmount }})#} {% endif %} @@ -213,8 +342,35 @@
- {% if inactive|length > 0 %} -
+ +
+ + {% if paginator.count > 0 and inactive.count > 0 %} +
+
+
+

{{ 'createBudget'|_ }}

+
+ +
+
+ {% endif %} + {% if inactive|length > 0 %}
@@ -231,8 +387,9 @@
-
- {% endif %} + {% endif %} +
+ {% endblock %} {% block styles %} @@ -243,14 +400,17 @@ diff --git a/routes/web.php b/routes/web.php index 25cb662a45..87f31f664f 100644 --- a/routes/web.php +++ b/routes/web.php @@ -220,11 +220,41 @@ Route::group( Route::get('{start_date?}/{end_date?}', ['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::post('income', ['uses' => 'Budget\AmountController@postUpdateIncome', 'as' => 'income.post']); - Route::post('amount/{budget}', ['uses' => 'Budget\AmountController@amount', 'as' => 'amount']); + //Route::get('income/{start_date}/{end_date}', ['uses' => 'Budget\AmountController@updateIncome', 'as' => 'income']); + //Route::post('income', ['uses' => 'Budget\AmountController@postUpdateIncome', 'as' => 'income.post']); + //Route::post('amount/{budget}', ['uses' => 'Budget\AmountController@amount', 'as' => 'amount']); +} +); +/** + * Available Budget Controller + */ +Route::group( + ['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers', 'prefix' => 'available-budgets', 'as' => 'available-budgets.'], function () { + // delete + //Route::get('delete/{budget}', ['uses' => 'Budget\DeleteController@delete', 'as' => 'delete']); + //Route::post('destroy/{budget}', ['uses' => 'Budget\DeleteController@destroy', 'as' => 'destroy']); + + // create + Route::get('create/{start_date}/{end_date}/{currency?}', ['uses' => 'Budget\AvailableBudgetController@create', 'as' => 'create']); + Route::get('create-alternative/{start_date}/{end_date}', ['uses' => 'Budget\AvailableBudgetController@createAlternative', 'as' => 'create-alternative']); + Route::post('store', ['uses' => 'Budget\AvailableBudgetController@store', 'as' => 'store']); + //Route::post('store', ['uses' => 'Budget\CreateController@store', 'as' => 'store']); + + // edit + Route::get('edit/{availableBudget}', ['uses' => 'Budget\AvailableBudgetController@edit', 'as' => 'edit']); + Route::post('update/{availableBudget}', ['uses' => 'Budget\AvailableBudgetController@update', 'as' => 'update']); + + Route::get('delete/{availableBudget}', ['uses' => 'Budget\AvailableBudgetController@delete', 'as' => 'delete']); + //Route::get('edit/{budget}', ['uses' => 'Budget\EditController@edit', 'as' => 'edit']); + //Route::post('update/{budget}', ['uses' => 'Budget\EditController@update', 'as' => 'update']); + + // 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/all', ['uses' => 'Budget\ShowController@noBudgetAll', 'as' => 'no-budget-all']); + //Route::get('list/no-budget/{start_date?}/{end_date?}', ['uses' => 'Budget\ShowController@noBudget', 'as' => 'no-budget']); } );