middleware( function ($request, $next) { View::share('title', trans('firefly.transactions')); View::share('mainTitleIcon', 'fa-repeat'); return $next($request); } ); } /** * @param Request $request * @param JournalRepositoryInterface $repository * @param string $what * * @param string $moment * * @return View */ public function index(Request $request, JournalRepositoryInterface $repository, string $what, string $moment = '') { // default values: $subTitleIcon = config('firefly.transactionIconsByWhat.' . $what); $types = config('firefly.transactionTypesByWhat.' . $what); $page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page')); $pageSize = intval(Preferences::get('transactionPageSize', 50)->data); $count = 0; $loop = 0; $range = Preferences::get('viewRange', '1M')->data; $start = null; $end = null; $periods = new Collection; $path = '/transactions/' . $what; // prep for "all" view. if ($moment === 'all') { $subTitle = trans('firefly.all_' . $what); $first = $repository->first(); $start = $first->date ?? new Carbon; $end = new Carbon; $path = '/transactions/' . $what . '/all/'; } // prep for "specific date" view. if (strlen($moment) > 0 && $moment !== 'all') { $start = new Carbon($moment); $end = Navigation::endOfPeriod($start, $range); $path = '/transactions/' . $what . '/' . $moment; $subTitle = trans( 'firefly.title_' . $what . '_between', ['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)] ); $periods = $this->getPeriodOverview($what); } // prep for current period if (strlen($moment) === 0) { $start = clone session('start', Navigation::startOfPeriod(new Carbon, $range)); $end = clone session('end', Navigation::endOfPeriod(new Carbon, $range)); $periods = $this->getPeriodOverview($what); $subTitle = trans( 'firefly.title_' . $what . '_between', ['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)] ); } // grab journals, but be prepared to jump a period back to get the right ones: Log::info('Now at transaction loop start.'); while ($count === 0 && $loop < 3) { $loop++; Log::info('Count is zero, search for journals.'); /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); $collector->setAllAssetAccounts()->setRange($start, $end)->setTypes($types)->setLimit($pageSize)->setPage($page)->withOpposingAccount(); $collector->removeFilter(InternalTransferFilter::class); $journals = $collector->getPaginatedJournals(); $journals->setPath($path); $count = $journals->getCollection()->count(); if ($count === 0 && $loop < 3) { $start->subDay(); $start = Navigation::startOfPeriod($start, $range); $end = Navigation::endOfPeriod($start, $range); Log::info(sprintf('Count is still zero, go back in time to "%s" and "%s"!', $start->format('Y-m-d'), $end->format('Y-m-d'))); } } if ($moment !== 'all' && $loop > 1) { $subTitle = trans( 'firefly.title_' . $what . '_between', ['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)] ); } return view('transactions.index', compact('subTitle', 'what', 'subTitleIcon', 'journals', 'periods', 'start', 'end', 'moment')); } /** * @param Request $request * @param JournalRepositoryInterface $repository * * @return \Illuminate\Http\JsonResponse */ public function reorder(Request $request, JournalRepositoryInterface $repository) { $ids = $request->get('items'); $date = new Carbon($request->get('date')); if (count($ids) > 0) { $order = 0; $ids = array_unique($ids); foreach ($ids as $id) { $journal = $repository->find(intval($id)); if ($journal && $journal->date->isSameDay($date)) { $repository->setOrder($journal, $order); $order++; } } } Preferences::mark(); return Response::json([true]); } /** * @param TransactionJournal $journal * @param JournalTaskerInterface $tasker * * @return View */ public function show(TransactionJournal $journal, JournalTaskerInterface $tasker) { if ($this->isOpeningBalance($journal)) { return $this->redirectToAccount($journal); } $events = $tasker->getPiggyBankEvents($journal); $transactions = $tasker->getTransactionsOverview($journal); $what = strtolower($journal->transaction_type_type ?? $journal->transactionType->type); $subTitle = trans('firefly.' . $what) . ' "' . e($journal->description) . '"'; return view('transactions.show', compact('journal', 'events', 'subTitle', 'what', 'transactions')); } /** * @param string $what * * @return Collection * @throws FireflyException */ private function getPeriodOverview(string $what): Collection { $repository = app(JournalRepositoryInterface::class); $first = $repository->first(); $start = $first->date ?? new Carbon; $range = Preferences::get('viewRange', '1M')->data; $start = Navigation::startOfPeriod($start, $range); $end = Navigation::endOfX(new Carbon, $range); $entries = new Collection; $types = config('firefly.transactionTypesByWhat.' . $what); // properties for cache $cache = new CacheProperties; $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($what); $cache->addProperty('transaction-list-entries'); if ($cache->has()) { return $cache->get(); // @codeCoverageIgnore } Log::debug(sprintf('Going to get period expenses and incomes between %s and %s.', $start->format('Y-m-d'), $end->format('Y-m-d'))); while ($end >= $start) { Log::debug('Loop start!'); $end = Navigation::startOfPeriod($end, $range); $currentEnd = Navigation::endOfPeriod($end, $range); // count journals without budget in this period: /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); $collector->setAllAssetAccounts()->setRange($end, $currentEnd)->withOpposingAccount()->setTypes($types); $collector->removeFilter(InternalTransferFilter::class); $set = $collector->getJournals(); $sum = $set->sum('transaction_amount'); $journals = $set->count(); $dateStr = $end->format('Y-m-d'); $dateName = Navigation::periodShow($end, $range); $array = [ 'string' => $dateStr, 'name' => $dateName, 'count' => $journals, 'spent' => 0, 'earned' => 0, 'transferred' => 0, 'date' => clone $end, ]; Log::debug(sprintf('What is %s', $what)); switch ($what) { case 'withdrawal': $array['spent'] = $sum; break; case 'deposit': $array['earned'] = $sum; break; case 'transfers': case 'transfer': $array['transferred'] = Steam::positive($sum); break; } $entries->push($array); $end = Navigation::subtractPeriod($end, $range, 1); } Log::debug('End of loop'); $cache->store($entries); return $entries; } }