From 373b9cdd9fedaa854a4dc258e9c9cd4f3c0b956a Mon Sep 17 00:00:00 2001 From: James Cole Date: Mon, 9 Jan 2017 17:57:29 +0100 Subject: [PATCH] A better tag overview as preparation for #525 --- app/Http/Controllers/TagController.php | 111 +++++++++++++++--- app/Repositories/Tag/TagRepository.php | 68 +++++++++++ .../Tag/TagRepositoryInterface.php | 33 ++++++ resources/views/tags/show.twig | 44 ++++++- routes/web.php | 4 +- 5 files changed, 236 insertions(+), 24 deletions(-) diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php index c000fd6fd5..f155623fdc 100644 --- a/app/Http/Controllers/TagController.php +++ b/app/Http/Controllers/TagController.php @@ -13,13 +13,17 @@ declare(strict_types = 1); namespace FireflyIII\Http\Controllers; +use Carbon\Carbon; +use Exception; use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Http\Requests\TagFormRequest; use FireflyIII\Models\Tag; use FireflyIII\Models\Transaction; use FireflyIII\Repositories\Tag\TagRepositoryInterface; +use FireflyIII\Support\CacheProperties; use Illuminate\Http\Request; use Illuminate\Support\Collection; +use Navigation; use Preferences; use Session; use URL; @@ -41,8 +45,12 @@ use View; class TagController extends Controller { + /** @var array */ public $tagOptions = []; + /** @var TagRepositoryInterface */ + protected $repository; + /** * */ @@ -53,15 +61,19 @@ class TagController extends Controller $this->middleware( function ($request, $next) { - View::share('title', 'Tags'); - View::share('mainTitleIcon', 'fa-tags'); + $this->repository = app(TagRepositoryInterface::class); $this->tagOptions = [ 'nothing' => trans('firefly.regular_tag'), 'balancingAct' => trans('firefly.balancing_act'), 'advancePayment' => trans('firefly.advance_payment'), ]; + + + View::share('title', strval(trans('firefly.tags'))); + View::share('mainTitleIcon', 'fa-tags'); View::share('tagOptions', $this->tagOptions); + return $next($request); } ); @@ -113,16 +125,15 @@ class TagController extends Controller } /** - * @param TagRepositoryInterface $repository - * @param Tag $tag + * @param Tag $tag * * @return \Illuminate\Http\RedirectResponse */ - public function destroy(TagRepositoryInterface $repository, Tag $tag) + public function destroy(Tag $tag) { $tagName = $tag->tag; - $repository->destroy($tag); + $this->repository->destroy($tag); Session::flash('success', strval(trans('firefly.deleted_tag', ['tag' => e($tagName)]))); Preferences::mark(); @@ -216,15 +227,34 @@ class TagController extends Controller * * @return View */ - public function show(Request $request, JournalCollectorInterface $collector, Tag $tag) + public function show(Request $request, JournalCollectorInterface $collector, Tag $tag, string $moment = '') { + $range = Preferences::get('viewRange', '1M')->data; + + if (strlen($moment) > 0) { + try { + $start = new Carbon($moment); + $end = Navigation::endOfPeriod($start, $range); + } catch (Exception $e) { + $start = Navigation::startOfPeriod($this->repository->firstUseDate($tag), $range); + $end = Navigation::startOfPeriod($this->repository->lastUseDate($tag), $range); + } + } + if (strlen($moment) === 0) { + $start = clone session('start', Carbon::now()->startOfMonth()); + $end = clone session('end', Carbon::now()->endOfMonth()); + } + $subTitle = $tag->tag; $subTitleIcon = 'fa-tag'; $page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page')); $pageSize = intval(Preferences::get('transactionPageSize', 50)->data); + $periods = $this->getPeriodOverview($tag); // use collector: - $collector->setAllAssetAccounts()->setLimit($pageSize)->setPage($page)->setTag($tag)->withBudgetInformation()->withCategoryInformation(); + $collector->setAllAssetAccounts() + ->setLimit($pageSize)->setPage($page)->setTag($tag) + ->withBudgetInformation()->withCategoryInformation()->setRange($start, $end); $journals = $collector->getPaginatedJournals(); $journals->setPath('tags/show/' . $tag->id); @@ -234,20 +264,18 @@ class TagController extends Controller } ); - return view('tags.show', compact('tag', 'subTitle', 'subTitleIcon', 'journals', 'sum')); + return view('tags.show', compact('tag', 'periods', 'subTitle', 'subTitleIcon', 'journals', 'sum', 'start', 'end')); } /** - * @param TagFormRequest $request - * - * @param TagRepositoryInterface $repository + * @param TagFormRequest $request * * @return \Illuminate\Http\RedirectResponse */ - public function store(TagFormRequest $request, TagRepositoryInterface $repository) + public function store(TagFormRequest $request) { $data = $request->collectTagData(); - $repository->store($data); + $this->repository->store($data); Session::flash('success', strval(trans('firefly.created_tag', ['tag' => e($data['tag'])]))); Preferences::mark(); @@ -265,16 +293,15 @@ class TagController extends Controller } /** - * @param TagFormRequest $request - * @param TagRepositoryInterface $repository - * @param Tag $tag + * @param TagFormRequest $request + * @param Tag $tag * * @return \Illuminate\Http\RedirectResponse */ - public function update(TagFormRequest $request, TagRepositoryInterface $repository, Tag $tag) + public function update(TagFormRequest $request, Tag $tag) { $data = $request->collectTagData(); - $repository->update($tag, $data); + $this->repository->update($tag, $data); Session::flash('success', strval(trans('firefly.updated_tag', ['tag' => e($data['tag'])]))); Preferences::mark(); @@ -289,4 +316,50 @@ class TagController extends Controller // redirect to previous URL. return redirect(session('tags.edit.url')); } + + /** + * @param Tag $tag + * + * @return Collection + */ + private function getPeriodOverview(Tag $tag): Collection + { + // get first and last tag date from tag: + $range = Preferences::get('viewRange', '1M')->data; + $start = Navigation::startOfPeriod($this->repository->firstUseDate($tag), $range); + $end = Navigation::startOfPeriod($this->repository->lastUseDate($tag), $range); + // properties for entries with their amounts. + $cache = new CacheProperties; + $cache->addProperty($start); + $cache->addProperty($end); + $cache->addProperty('tag.entries'); + $cache->addProperty($tag->id); + + if ($cache->has()) { + return $cache->get(); + } + + $collection = new Collection; + + // while end larger or equal to start + while ($end >= $start) { + $currentEnd = Navigation::endOfPeriod($end, $range); + + // get expenses and what-not in this period and this tag. + $arr = [ + 'date_string' => $end->format('Y-m-d'), + 'date_name' => Navigation::periodShow($end, $range), + 'date' => $end, + 'spent' => $this->repository->spentInperiod($tag, $end, $currentEnd), + 'earned' => $this->repository->earnedInperiod($tag, $end, $currentEnd), + ]; + $collection->push($arr); + + $end = Navigation::subtractPeriod($end, $range, 1); + } + $cache->store($collection); + + return $collection; + + } } diff --git a/app/Repositories/Tag/TagRepository.php b/app/Repositories/Tag/TagRepository.php index dd6e341328..8145be1151 100644 --- a/app/Repositories/Tag/TagRepository.php +++ b/app/Repositories/Tag/TagRepository.php @@ -14,6 +14,8 @@ declare(strict_types = 1); namespace FireflyIII\Repositories\Tag; +use Carbon\Carbon; +use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Models\Tag; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; @@ -121,6 +123,21 @@ class TagRepository implements TagRepositoryInterface return new Tag; } + /** + * @param Tag $tag + * + * @return Carbon + */ + public function firstUseDate(Tag $tag): Carbon + { + $journal = $tag->transactionJournals()->orderBy('date', 'ASC')->first(); + if (!is_null($journal)) { + return $journal->date; + } + + return new Carbon; + } + /** * @return Collection */ @@ -137,6 +154,21 @@ class TagRepository implements TagRepositoryInterface return $tags; } + /** + * @param Tag $tag + * + * @return Carbon + */ + public function lastUseDate(Tag $tag): Carbon + { + $journal = $tag->transactionJournals()->orderBy('date', 'DESC')->first(); + if (!is_null($journal)) { + return $journal->date; + } + + return new Carbon; + } + /** * @param array $data * @@ -353,4 +385,40 @@ class TagRepository implements TagRepositoryInterface return false; } + + /** + * @param Tag $tag + * @param Carbon $start + * @param Carbon $end + * + * @return string + */ + public function earnedInPeriod(Tag $tag, Carbon $start, Carbon $end): string + { + /** @var JournalCollectorInterface $collector */ + $collector = app(JournalCollectorInterface::class, [$this->user]); + $collector->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setAllAssetAccounts()->setTag($tag); + $set = $collector->getJournals(); + $sum = strval($set->sum('transaction_amount')); + + return $sum; + } + + /** + * @param Tag $tag + * @param Carbon $start + * @param Carbon $end + * + * @return string + */ + public function spentInPeriod(Tag $tag, Carbon $start, Carbon $end): string + { + /** @var JournalCollectorInterface $collector */ + $collector = app(JournalCollectorInterface::class, [$this->user]); + $collector->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setAllAssetAccounts()->setTag($tag); + $set = $collector->getJournals(); + $sum = strval($set->sum('transaction_amount')); + + return $sum; + } } diff --git a/app/Repositories/Tag/TagRepositoryInterface.php b/app/Repositories/Tag/TagRepositoryInterface.php index 3da24ab718..64bf47c44e 100644 --- a/app/Repositories/Tag/TagRepositoryInterface.php +++ b/app/Repositories/Tag/TagRepositoryInterface.php @@ -13,6 +13,7 @@ declare(strict_types = 1); namespace FireflyIII\Repositories\Tag; +use Carbon\Carbon; use FireflyIII\Models\Tag; use FireflyIII\Models\TransactionJournal; use Illuminate\Support\Collection; @@ -44,6 +45,15 @@ interface TagRepositoryInterface */ public function destroy(Tag $tag): bool; + /** + * @param Tag $tag + * @param Carbon $start + * @param Carbon $end + * + * @return string + */ + public function earnedInPeriod(Tag $tag, Carbon $start, Carbon $end): string; + /** * @param int $tagId * @@ -58,6 +68,13 @@ interface TagRepositoryInterface */ public function findByTag(string $tag): Tag; + /** + * @param Tag $tag + * + * @return Carbon + */ + public function firstUseDate(Tag $tag): Carbon; + /** * This method returns all the user's tags. * @@ -65,6 +82,22 @@ interface TagRepositoryInterface */ public function get(): Collection; + /** + * @param Tag $tag + * + * @return Carbon + */ + public function lastUseDate(Tag $tag): Carbon; + + /** + * @param Tag $tag + * @param Carbon $start + * @param Carbon $end + * + * @return string + */ + public function spentInPeriod(Tag $tag, Carbon $start, Carbon $end): string; + /** * This method stores a tag. * diff --git a/resources/views/tags/show.twig b/resources/views/tags/show.twig index e78b69f5b1..720934948e 100644 --- a/resources/views/tags/show.twig +++ b/resources/views/tags/show.twig @@ -76,7 +76,12 @@
- +
+

{{ 'transactions'|_ }}

@@ -99,11 +104,42 @@
+
+ {% for period in periods %} + {% if period.spent != 0 or period.earned != 0 %} +
+ +
+ + {% if period.spent != 0 %} + + + + + {% endif %} + {% if period.earned != 0 %} + + + + + {% endif %} +
{{ 'spent'|_ }}{{ period.spent|formatAmount }}
{{ 'earned'|_ }}{{ period.earned|formatAmount }}
+
+
+ {% endif %} + + {% endfor %} +
+
+ {% endblock %} {% block scripts %} - {% endblock %} diff --git a/routes/web.php b/routes/web.php index 8b50c86560..71793df647 100755 --- a/routes/web.php +++ b/routes/web.php @@ -586,7 +586,9 @@ Route::group( Route::get('', ['uses' => 'TagController@index', 'as' => 'index']); Route::get('create', ['uses' => 'TagController@create', 'as' => 'create']); - Route::get('show/{tag}', ['uses' => 'TagController@show', 'as' => 'show']); + + Route::get('show/{tag}/{date?}', ['uses' => 'TagController@show', 'as' => 'show']); + Route::get('edit/{tag}', ['uses' => 'TagController@edit', 'as' => 'edit']); Route::get('delete/{tag}', ['uses' => 'TagController@delete', 'as' => 'delete']);