diff --git a/app/Helpers/Collection/BalanceLine.php b/app/Helpers/Collection/BalanceLine.php index a5e48efae1..ff0d17fc3b 100644 --- a/app/Helpers/Collection/BalanceLine.php +++ b/app/Helpers/Collection/BalanceLine.php @@ -26,9 +26,6 @@ class BalanceLine /** @var BudgetModel */ protected $budget; - /** @var LimitRepetition */ - protected $repetition; - protected $role = self::ROLE_DEFAULTROLE; /** @@ -110,7 +107,7 @@ class BalanceLine */ public function leftOfRepetition() { - $start = $this->getRepetition() ? $this->getRepetition()->amount : 0; + $start = isset($this->budget->amount) ? $this->budget->amount : 0; /** @var BalanceEntry $balanceEntry */ foreach ($this->getBalanceEntries() as $balanceEntry) { $start += $balanceEntry->getSpent(); @@ -119,22 +116,6 @@ class BalanceLine return $start; } - /** - * @return LimitRepetition - */ - public function getRepetition() - { - return $this->repetition; - } - - /** - * @param LimitRepetition $repetition - */ - public function setRepetition($repetition) - { - $this->repetition = $repetition; - } - /** * @return Collection */ diff --git a/app/Helpers/Report/ReportHelper.php b/app/Helpers/Report/ReportHelper.php index 63981f4b35..46dbebb137 100644 --- a/app/Helpers/Report/ReportHelper.php +++ b/app/Helpers/Report/ReportHelper.php @@ -20,6 +20,8 @@ use FireflyIII\Models\Account; use FireflyIII\Models\Bill; use FireflyIII\Models\Budget as BudgetModel; use FireflyIII\Models\LimitRepetition; +use FireflyIII\Models\Tag; +use FireflyIII\Models\TransactionJournal; use Illuminate\Support\Collection; /** @@ -62,13 +64,8 @@ class ReportHelper implements ReportHelperInterface /** @var \FireflyIII\Repositories\Category\CategoryRepositoryInterface $repository */ $repository = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); - /** @var \FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface $singleRepository */ - $singleRepository = app('FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface'); - - $set = $repository->listCategories(); + $set = $repository->spentForAccountsPerMonth($accounts, $start, $end); foreach ($set as $category) { - $spent = $singleRepository->balanceInPeriod($category, $start, $end, $accounts); - $category->spent = $spent; $object->addCategory($category); } @@ -332,13 +329,18 @@ class ReportHelper implements ReportHelperInterface */ public function getBalanceReport(Carbon $start, Carbon $end, Collection $accounts) { - $repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + /** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + + /** @var \FireflyIII\Repositories\Tag\TagRepositoryInterface $tagRepository */ $tagRepository = app('FireflyIII\Repositories\Tag\TagRepositoryInterface'); - $balance = new Balance; + + $balance = new Balance; // build a balance header: - $header = new BalanceHeader; - $budgets = $repository->getBudgets(); + $header = new BalanceHeader; + $budgets = $repository->getBudgetsAndLimitsInRange($start, $end); + $spentData = $repository->spentPerBudgetPerAccount($budgets, $accounts, $start, $end); foreach ($accounts as $account) { $header->addAccount($account); } @@ -348,18 +350,22 @@ class ReportHelper implements ReportHelperInterface $line = new BalanceLine; $line->setBudget($budget); - // get budget amount for current period: - $rep = $repository->getCurrentRepetition($budget, $start, $end); - // could be null? - $line->setRepetition($rep); - // loop accounts: foreach ($accounts as $account) { $balanceEntry = new BalanceEntry; $balanceEntry->setAccount($account); // get spent: - $spent = $this->query->spentInBudget($account, $budget, $start, $end); // I think shared is irrelevant. + $entry = $spentData->filter( + function (TransactionJournal $model) use ($budget, $account) { + return $model->account_id == $account->id && $model->budget_id == $budget->id; + } + ); + $spent = 0; + if (!is_null($entry->first())) { + $spent = $entry->first()->spent; + } + //$spent = $this->query->spentInBudget($account, $budget, $start, $end); // I think shared is irrelevant. $balanceEntry->setSpent($spent); $line->addBalanceEntry($balanceEntry); @@ -374,13 +380,31 @@ class ReportHelper implements ReportHelperInterface $empty = new BalanceLine; $tags = new BalanceLine; $diffLine = new BalanceLine; + $tagsLeft = $tagRepository->allCoveredByBalancingActs($accounts, $start, $end); $tags->setRole(BalanceLine::ROLE_TAGROLE); $diffLine->setRole(BalanceLine::ROLE_DIFFROLE); foreach ($accounts as $account) { - $spent = $this->query->spentNoBudget($account, $start, $end); - $left = $tagRepository->coveredByBalancingActs($account, $start, $end); + //$spent = $this->query->spentNoBudget($account, $start, $end); + $entry = $spentData->filter( + function (TransactionJournal $model) use ($budget, $account) { + return $model->account_id == $account->id && is_null($model->budget_id); + } + ); + $spent = 0; + if (!is_null($entry->first())) { + $spent = $entry->first()->spent; + } + $leftEntry = $tagsLeft->filter( + function (Tag $tag) use ($account) { + return $tag->account_id == $account->id; + } + ); + $left = 0; + if (!is_null($leftEntry->first())) { + $left = $leftEntry->first()->sum; + } bcscale(2); $diff = bcadd($spent, $left); diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php index d43661064d..33b7f87022 100644 --- a/app/Http/Controllers/ReportController.php +++ b/app/Http/Controllers/ReportController.php @@ -125,21 +125,18 @@ class ReportController extends Controller $expenseTopLength = 8; // get report stuff! - $accountReport = $this->helper->getAccountReport($start, $end, $accounts); // done - $incomes = $this->helper->getIncomeReport($start, $end, $accounts); // done - $expenses = $this->helper->getExpenseReport($start, $end, $accounts); // done - $budgets = $this->helper->getBudgetReport($start, $end, $accounts); - $categories = $this->helper->getCategoryReport($start, $end, $accounts); - $balance = $this->helper->getBalanceReport($start, $end, $accounts); - $bills = $this->helper->getBillReport($start, $end, $accounts); + $accountReport = $this->helper->getAccountReport($start, $end, $accounts); // done (+2) + $incomes = $this->helper->getIncomeReport($start, $end, $accounts); // done (+3) + $expenses = $this->helper->getExpenseReport($start, $end, $accounts); // done (+1) + $budgets = $this->helper->getBudgetReport($start, $end, $accounts); // done (+5) + $categories = $this->helper->getCategoryReport($start, $end, $accounts); // done (+1) (20) + $balance = $this->helper->getBalanceReport($start, $end, $accounts); // +566 + // $bills = $this->helper->getBillReport($start, $end, $accounts); + + $bills = []; // and some id's, joined: - $accountIds = []; - /** @var Account $account */ - foreach ($accounts as $account) { - $accountIds[] = $account->id; - } - $accountIds = join(',', $accountIds); + $accountIds = join(',', $accounts->pluck('id')->toArray()); // continue! return view( diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index 3d4f9fc2bf..fa0db398ba 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -817,4 +817,56 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn return $return; } + + /** + * Returns a list of expenses (in the field "spent", grouped per budget per account. + * + * @param Collection $budgets + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function spentPerBudgetPerAccount(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end) + { + + $accountIds = $accounts->pluck('id')->toArray(); + $budgetIds = $budgets->pluck('id')->toArray(); + $set = Auth::user()->transactionjournals() + ->leftJoin( + 'transactions AS t_from', function (JoinClause $join) { + $join->on('transaction_journals.id', '=', 't_from.transaction_journal_id')->where('t_from.amount', '<', 0); + } + ) + ->leftJoin( + 'transactions AS t_to', function (JoinClause $join) { + $join->on('transaction_journals.id', '=', 't_to.transaction_journal_id')->where('t_to.amount', '>', 0); + } + ) + ->leftJoin('budget_transaction_journal', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id') + ->whereIn('t_from.account_id', $accountIds) + ->whereNotIn('t_to.account_id', $accountIds) + ->where( + function (Builder $q) use ($budgetIds) { + $q->whereIn('budget_transaction_journal.budget_id', $budgetIds); + $q->orWhereNull('budget_transaction_journal.budget_id'); + } + ) + ->after($start) + ->before($end) + ->groupBy('t_from.account_id') + ->groupBy('budget_transaction_journal.budget_id') + ->transactionTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE]) + ->get( + [ + 't_from.account_id', + 'budget_transaction_journal.budget_id', + DB::Raw('SUM(`t_from`.`amount`) AS `spent`') + ] + ); + + return $set; + + } } diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php index a06b661749..3ba1b8c1d8 100644 --- a/app/Repositories/Budget/BudgetRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -15,6 +15,10 @@ use Illuminate\Support\Collection; */ interface BudgetRepositoryInterface { + + + + /** * @return void */ @@ -51,6 +55,19 @@ interface BudgetRepositoryInterface */ public function getExpensesPerMonth(Budget $budget, Carbon $start, Carbon $end); + + /** + * Returns a list of expenses (in the field "spent", grouped per budget per account. + * + * @param Collection $budgets + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function spentPerBudgetPerAccount(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end); + /** * Returns an array with the following key:value pairs: * @@ -84,6 +101,8 @@ interface BudgetRepositoryInterface */ public function spentPerDayForAccounts(Budget $budget, Collection $accounts, Carbon $start, Carbon $end); + + /** * Returns an array with the following key:value pairs: * diff --git a/app/Repositories/Tag/TagRepository.php b/app/Repositories/Tag/TagRepository.php index 446aa85755..59832ff3e4 100644 --- a/app/Repositories/Tag/TagRepository.php +++ b/app/Repositories/Tag/TagRepository.php @@ -5,11 +5,13 @@ namespace FireflyIII\Repositories\Tag; use Auth; use Carbon\Carbon; +use DB; use FireflyIII\Models\Account; use FireflyIII\Models\Tag; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\Support\CacheProperties; +use Illuminate\Database\Query\JoinClause; use Illuminate\Support\Collection; /** @@ -94,6 +96,49 @@ class TagRepository implements TagRepositoryInterface return $amount; } + + /** + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function allCoveredByBalancingActs(Collection $accounts, Carbon $start, Carbon $end) + { + $ids = $accounts->pluck('id')->toArray(); + $set = Auth::user()->tags() + ->leftJoin('tag_transaction_journal', 'tag_transaction_journal.tag_id', '=', 'tags.id') + ->leftJoin('transaction_journals', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id') + ->leftJoin( + 'transactions AS t_from', function (JoinClause $join) { + $join->on('transaction_journals.id', '=', 't_from.transaction_journal_id')->where('t_from.amount', '<', 0); + } + ) + ->leftJoin( + 'transactions AS t_to', function (JoinClause $join) { + $join->on('transaction_journals.id', '=', 't_to.transaction_journal_id')->where('t_to.amount', '>', 0); + } + ) + ->where('tags.tagMode', 'balancingAct') + ->where('transaction_types.type', TransactionType::TRANSFER) + ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) + ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) + ->whereNull('transaction_journals.deleted_at') + ->whereIn('t_from.account_id', $ids) + ->whereIn('t_to.account_id', $ids) + ->groupBy('t_to.account_id') + ->get( + [ + 't_to.account_id', + DB::Raw('SUM(`t_to`.`amount`) as `sum`') + ] + ); + + return $set; + } + /** * @param Tag $tag * diff --git a/app/Repositories/Tag/TagRepositoryInterface.php b/app/Repositories/Tag/TagRepositoryInterface.php index 75c6a4df96..35f5c0f83c 100644 --- a/app/Repositories/Tag/TagRepositoryInterface.php +++ b/app/Repositories/Tag/TagRepositoryInterface.php @@ -16,7 +16,14 @@ use Illuminate\Support\Collection; */ interface TagRepositoryInterface { - + /** + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function allCoveredByBalancingActs(Collection $accounts, Carbon $start, Carbon $end); /** * @param TransactionJournal $journal