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