diff --git a/app/Helpers/Collector/JournalCollector.php b/app/Helpers/Collector/JournalCollector.php index 467197d8ca..3383f129fd 100644 --- a/app/Helpers/Collector/JournalCollector.php +++ b/app/Helpers/Collector/JournalCollector.php @@ -7,6 +7,7 @@ namespace FireflyIII\Helpers\Collector; use Carbon\Carbon; use Crypt; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\Category; use FireflyIII\Models\Transaction; use FireflyIII\User; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; @@ -51,6 +52,8 @@ class JournalCollector 'account_types.type as account_type', ]; + /** @var bool */ + private $joinedCategory = false; /** @var int */ private $limit; /** @var int */ @@ -220,6 +223,46 @@ class JournalCollector return $this; } + /** + * @param Category $category + * + * @return JournalCollector + */ + public function setCategory(Category $category): JournalCollector + { + if (!$this->joinedCategory) { + // join some extra tables: + $this->joinedCategory = true; + $this->query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'); + $this->query->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id'); + } + + $this->query->where( + function (EloquentBuilder $q) use ($category) { + $q->where('category_transaction.category_id', $category->id); + $q->orWhere('category_transaction_journal.category_id', $category->id); + } + ); + + return $this; + } + + /** + * @param Collection $accounts + * + * @return JournalCollector + */ + public function setDestinationAccounts(Collection $accounts): JournalCollector + { + if ($accounts->count() > 0) { + $accountIds = $accounts->pluck('id')->toArray(); + $this->query->whereIn('transactions.account_id', $accountIds); + $this->query->where('transactions.amount', '>', 0); + } + + return $this; + } + /** * @param int $limit * @@ -287,22 +330,6 @@ class JournalCollector return $this; } - /** - * @param Collection $accounts - * - * @return JournalCollector - */ - public function setDestinationAccounts(Collection $accounts): JournalCollector - { - if ($accounts->count() > 0) { - $accountIds = $accounts->pluck('id')->toArray(); - $this->query->whereIn('transactions.account_id', $accountIds); - $this->query->where('transactions.amount', '>', 0); - } - - return $this; - } - /** * @param Collection $accounts * diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php index f80d3a16bc..c1cfbdf1a5 100644 --- a/app/Http/Controllers/CategoryController.php +++ b/app/Http/Controllers/CategoryController.php @@ -14,13 +14,13 @@ declare(strict_types = 1); namespace FireflyIII\Http\Controllers; use Carbon\Carbon; +use FireflyIII\Helpers\Collector\JournalCollector; use FireflyIII\Http\Requests\CategoryFormRequest; use FireflyIII\Models\AccountType; use FireflyIII\Models\Category; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI; use FireflyIII\Support\CacheProperties; -use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; use Input; use Navigation; @@ -180,16 +180,17 @@ class CategoryController extends Controller $start = session('start', Navigation::startOfPeriod(new Carbon, $range)); /** @var Carbon $end */ $end = session('end', Navigation::endOfPeriod(new Carbon, $range)); + $accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); $hideCategory = true; // used in list. $page = intval(Input::get('page')); - $pageSize = Preferences::get('transactionPageSize', 50)->data; - $offset = ($page - 1) * $pageSize; - $set = $repository->journalsInPeriod(new Collection([$category]), new Collection, [], $start, $end); // category - $count = $set->count(); - $subSet = $set->splice($offset, $pageSize); + $pageSize = intval(Preferences::get('transactionPageSize', 50)->data); $subTitle = $category->name; $subTitleIcon = 'fa-bar-chart'; - $journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page); + + // use journal collector + $collector = new JournalCollector(auth()->user()); + $collector->setPage($page)->setLimit($pageSize)->setAccounts($accounts)->setRange($start, $end)->setCategory($category); + $journals = $collector->getPaginatedJournals(); $journals->setPath('categories/show/' . $category->id); // oldest transaction in category: @@ -218,7 +219,7 @@ class CategoryController extends Controller $categoryCollection = new Collection([$category]); - $accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); + while ($end >= $start) { $end = Navigation::startOfPeriod($end, $range); $currentEnd = Navigation::endOfPeriod($end, $range); @@ -233,7 +234,7 @@ class CategoryController extends Controller } $cache->store($entries); - return view('categories.show', compact('category', 'journals', 'entries', 'hideCategory', 'subTitle')); + return view('categories.show', compact('category', 'journals', 'entries', 'hideCategory', 'subTitle', 'subTitleIcon')); } /** @@ -244,7 +245,7 @@ class CategoryController extends Controller * * @return View */ - public function showWithDate(CRI $repository, Category $category, string $date) + public function showWithDate(AccountRepositoryInterface $repository, Category $category, string $date) { $carbon = new Carbon($date); $range = Preferences::get('viewRange', '1M')->data; @@ -253,14 +254,16 @@ class CategoryController extends Controller $subTitle = $category->name; $hideCategory = true; // used in list. $page = intval(Input::get('page')); - $pageSize = Preferences::get('transactionPageSize', 50)->data; - $offset = ($page - 1) * $pageSize; - $set = $repository->journalsInPeriod(new Collection([$category]), new Collection, [], $start, $end); // category - $count = $set->count(); - $subSet = $set->splice($offset, $pageSize); - $journals = new LengthAwarePaginator($subSet, $count, $pageSize, $page); + $pageSize = intval(Preferences::get('transactionPageSize', 50)->data); + $accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); + + // new collector: + $collector = new JournalCollector(auth()->user()); + $collector->setPage($page)->setLimit($pageSize)->setAccounts($accounts)->setRange($start, $end)->setCategory($category); + $journals = $collector->getPaginatedJournals(); $journals->setPath('categories/show/' . $category->id . '/' . $date); + return view('categories.show_with_date', compact('category', 'journals', 'hideCategory', 'subTitle', 'carbon')); } diff --git a/app/Http/Controllers/Popup/ReportController.php b/app/Http/Controllers/Popup/ReportController.php index 0b4df645ba..e023cb8284 100644 --- a/app/Http/Controllers/Popup/ReportController.php +++ b/app/Http/Controllers/Popup/ReportController.php @@ -17,6 +17,7 @@ namespace FireflyIII\Http\Controllers\Popup; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Collection\BalanceLine; +use FireflyIII\Helpers\Collector\JournalCollector; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; @@ -174,10 +175,14 @@ class ReportController extends Controller $repository = app(CategoryRepositoryInterface::class); $category = $repository->find(intval($attributes['categoryId'])); $types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER]; - $journals = $repository->journalsInPeriod( - new Collection([$category]), $attributes['accounts'], $types, $attributes['startDate'], $attributes['endDate'] - ); - $view = view('popup.report.category-entry', compact('journals', 'category'))->render(); + // get journal collector instead: + $collector = new JournalCollector(auth()->user()); + $collector->setAccounts($attributes['accounts'])->setTypes($types) + ->setRange($attributes['startDate'], $attributes['endDate']) + ->setCategory($category); + $journals = $collector->getJournals(); // 7193 + + $view = view('popup.report.category-entry', compact('journals', 'category'))->render(); return $view; } diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php index cc0ec6b192..4ee0a03061 100644 --- a/app/Repositories/Category/CategoryRepository.php +++ b/app/Repositories/Category/CategoryRepository.php @@ -174,115 +174,6 @@ class CategoryRepository implements CategoryRepositoryInterface return $set; } - /** - * @param Category $category - * @param int $page - * @param int $pageSize - * - * @return LengthAwarePaginator - */ - public function getJournals(Category $category, int $page, int $pageSize): LengthAwarePaginator - { - $complete = new Collection; - // first collect actual transaction journals (fairly easy) - $query = $this->user->transactionJournals()->expanded()->sortCorrectly(); - $query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'); - $query->where('category_transaction_journal.category_id', $category->id); - $first = $query->get(TransactionJournal::queryFields()); - - // then collection transactions (harder) - $query = $this->user->transactionJournals()->distinct() - ->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id') - ->where('category_transaction.category_id', $category->id); - $second = $query->get(['transaction_journals.*']); - - $complete = $complete->merge($first); - $complete = $complete->merge($second); - - // sort: - /** @var Collection $complete */ - $complete = $complete->sortByDesc( - function ($model) { - $date = new Carbon($model->date); - - return intval($date->format('U')); - } - ); - // create paginator - $offset = ($page - 1) * $pageSize; - $subSet = $complete->slice($offset, $pageSize)->all(); - $paginator = new LengthAwarePaginator($subSet, $complete->count(), $pageSize, $page); - - return $paginator; - } - - /** - * Get all transactions in a category in a range. - * - * @param Collection $categories - * @param Collection $accounts - * @param array $types - * @param Carbon $start - * @param Carbon $end - * - * @return Collection - */ - public function journalsInPeriod(Collection $categories, Collection $accounts, array $types, Carbon $start, Carbon $end): Collection - { - $complete = new Collection; - // first collect actual transaction journals (fairly easy) - $query = $this->user->transactionJournals()->expanded()->sortCorrectly(); - - if ($end >= $start) { - $query->before($end)->after($start); - } - - if (count($types) > 0) { - $query->transactionTypes($types); - } - - if ($accounts->count() > 0) { - $accountIds = $accounts->pluck('id')->toArray(); - $query->leftJoin('transactions as t', 't.transaction_journal_id', '=', 'transaction_journals.id'); - $query->whereIn('t.account_id', $accountIds); - } - if ($categories->count() > 0) { - $categoryIds = $categories->pluck('id')->toArray(); - $query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'); - $query->whereIn('category_transaction_journal.category_id', $categoryIds); - } - - // that should do it: - $first = $query->get(TransactionJournal::queryFields()); - - - // then collection transactions (harder) - $query = $this->user->transactionJournals()->distinct() - ->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id') - ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'); - if (count($types) > 0) { - $query->whereIn('transaction_types.type', $types); - } - if ($accounts->count() > 0) { - $accountIds = $accounts->pluck('id')->toArray(); - $query->whereIn('transactions.account_id', $accountIds); - } - if ($categories->count() > 0) { - $categoryIds = $categories->pluck('id')->toArray(); - $query->whereIn('category_transaction.category_id', $categoryIds); - } - - - $second = $query->get(['transaction_journals.*', 'transaction_types.type as transaction_type_type']); - - $complete = $complete->merge($first); - $complete = $complete->merge($second); - - return $complete; - } - /** * @param Collection $accounts * @param array $types diff --git a/app/Repositories/Category/CategoryRepositoryInterface.php b/app/Repositories/Category/CategoryRepositoryInterface.php index d5aaff5bc2..b6079c0be8 100644 --- a/app/Repositories/Category/CategoryRepositoryInterface.php +++ b/app/Repositories/Category/CategoryRepositoryInterface.php @@ -84,26 +84,6 @@ interface CategoryRepositoryInterface */ public function getCategories(): Collection; - /** - * @param Category $category - * @param int $page - * @param int $pageSize - * - * @return LengthAwarePaginator - */ - public function getJournals(Category $category, int $page, int $pageSize): LengthAwarePaginator; - - /** - * @param Collection $categories - * @param Collection $accounts - * @param array $types - * @param Carbon $start - * @param Carbon $end - * - * @return Collection - */ - public function journalsInPeriod(Collection $categories, Collection $accounts, array $types, Carbon $start, Carbon $end): Collection; - /** * @param Collection $accounts * @param array $types diff --git a/resources/views/categories/show.twig b/resources/views/categories/show.twig index f80113b6cc..0800aaf7b9 100644 --- a/resources/views/categories/show.twig +++ b/resources/views/categories/show.twig @@ -35,7 +35,7 @@