/** * @covers FireflyIII\Models\Tag::firstOrCreateEncrypted */ public function testFirstOrCreateEncryptedNew() { $tag = FactoryMuffin::create('FireflyIII\\Models\\Tag'); $search = ['tagMode' => 'something', 'tag' => 'Something else', 'user_id' => $tag->user_id]; $result = Tag::firstOrCreateEncrypted($search); $this->assertNotEquals($tag->id, $result->id); }
/** * @param array $fields * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * * @return Tag|null */ public static function firstOrCreateEncrypted(array $fields) { // everything but the tag: if (isset($fields['tagMode'])) { unset($fields['tagMode']); } $query = Tag::orderBy('id'); foreach ($fields as $name => $value) { if ($name != 'tag') { $query->where($name, $value); } } $set = $query->get(['tags.*']); /** @var Tag $tag */ foreach ($set as $tag) { if ($tag->tag == $fields['tag']) { return $tag; } } // create it! $fields['tagMode'] = 'nothing'; $fields['description'] = isset($fields['description']) && !is_null($fields['description']) ? $fields['description'] : ''; $tag = Tag::create($fields); return $tag; }
/** * @return bool */ public function act() { // journal has this tag maybe? $tag = Tag::firstOrCreateEncrypted(['tag' => $this->action->action_value, 'user_id' => Auth::user()->id]); $count = $this->journal->tags()->where('id', $tag->id)->count(); if ($count == 0) { $this->journal->tags()->save($tag); } return true; }
/** * @return array */ public function rules() { $idRule = ''; $tagRule = 'required|min:1|uniqueObjectForUser:tags,tag'; if (Tag::find(Input::get('id'))) { $idRule = 'belongsToUser:tags'; $tagRule = 'required|min:1|uniqueObjectForUser:tags,tag,' . Input::get('id'); } return ['tag' => $tagRule, 'id' => $idRule, 'description' => 'min:1', 'date' => 'date', 'latitude' => 'numeric|min:-90|max:90', 'longitude' => 'numeric|min:-90|max:90', 'zoomLevel' => 'numeric|min:0|max:80', 'tagMode' => 'required|in:nothing,balancingAct,advancePayment']; }
/** * @return Collection */ public function convert() { $tags = new Collection(); $strings = explode(' ', $this->value); foreach ($strings as $string) { $tag = Tag::firstOrCreateEncrypted(['tag' => $string, 'tagMode' => 'nothing', 'user_id' => Auth::user()->id]); $tags->push($tag); } $tags = $tags->merge($this->data['tags']); return $tags; }
/** * @param TransactionJournal $journal * * @return bool */ public function act(TransactionJournal $journal) : bool { // journal has this tag maybe? $tag = Tag::firstOrCreateEncrypted(['tag' => $this->action->action_value, 'user_id' => $journal->user->id]); $count = $journal->tags()->where('tag_id', $tag->id)->count(); if ($count === 0) { $journal->tags()->save($tag); Log::debug(sprintf('RuleAction AddTag. Added tag #%d ("%s") to journal %d.', $tag->id, $tag->tag, $journal->id)); return true; } Log::debug(sprintf('RuleAction AddTag fired but tag %d ("%s") was already added to journal %d.', $tag->id, $tag->tag, $journal->id)); return true; }
/** * @return \Illuminate\Http\RedirectResponse */ public function flush() { // get all tags. // update all counts: $tags = Tag::get(); /** @var Tag $tag */ foreach ($tags as $tag) { foreach ($tag->transactionjournals()->get() as $journal) { $count = $journal->tags()->count(); $journal->tag_count = $count; $journal->save(); } } Session::clear(); return Redirect::route('index'); }
/** * @return \Illuminate\Http\RedirectResponse */ public function flush() { Preferences::mark(); // get all tags. // update all counts: $tags = Tag::get(); /** @var Tag $tag */ foreach ($tags as $tag) { foreach ($tag->transactionjournals()->get() as $journal) { $count = $journal->tags()->count(); $journal->tag_count = $count; $journal->save(); } } Session::clear(); Artisan::call('cache:clear'); return redirect(route('index')); }
/** * @param $tagName * * @return Tag|null * @internal param $tag */ protected function findTag($tagName) { // account $user = User::whereEmail('*****@*****.**')->first(); /** @var Tag $tag */ foreach (Tag::get() as $tag) { if ($tag->tag == $tagName && $user->id == $tag->user_id) { return $tag; break; } } return null; }
/** * @param TransactionJournal $journal * @param Tag $tag * * @return boolean */ protected function connectAdvancePayment(TransactionJournal $journal, Tag $tag) { /** @var TransactionType $transfer */ $transfer = TransactionType::whereType('Transfer')->first(); /** @var TransactionType $withdrawal */ $withdrawal = TransactionType::whereType('Withdrawal')->first(); /** @var TransactionType $deposit */ $deposit = TransactionType::whereType('Deposit')->first(); $withdrawals = $tag->transactionjournals()->where('transaction_type_id', $withdrawal->id)->count(); $deposits = $tag->transactionjournals()->where('transaction_type_id', $deposit->id)->count(); // advance payments cannot accept transfers: if ($journal->transaction_type_id == $transfer->id) { return false; } // the first transaction to be attached to this // tag is attached just like that: if ($withdrawals < 1 && $deposits < 1) { $journal->tags()->save($tag); $journal->save(); return true; } // if withdrawal and already has a withdrawal, return false: if ($journal->transaction_type_id == $withdrawal->id && $withdrawals == 1) { return false; } // if already has transaction journals, must match ALL asset account id's: if ($deposits > 0 || $withdrawals == 1) { return $this->matchAll($journal, $tag); } // this statement is unreachable. return false; // @codeCoverageIgnore }
/** * Assuming the journal has only one tag. Parameter amount is used as fallback. * * @param Tag $tag * @param string $amount * * @return string */ protected function amountByTag(Tag $tag, $amount) { if ($tag->tagMode == 'advancePayment') { if ($this->transactionType->type == 'Withdrawal') { $others = $tag->transactionJournals()->transactionTypes(['Deposit'])->get(); foreach ($others as $other) { $amount = bcsub($amount, $other->actual_amount); } return $amount; } if ($this->transactionType->type == 'Deposit') { return '0'; } } if ($tag->tagMode == 'balancingAct') { if ($this->transactionType->type == 'Withdrawal') { $transfer = $tag->transactionJournals()->transactionTypes(['Transfer'])->first(); if ($transfer) { $amount = bcsub($amount, $transfer->actual_amount); return $amount; } } } return $amount; }
/** * @param Tag $tag * * @return View */ public function edit(Tag $tag) { $subTitle = trans('firefly.edit_tag', ['tag' => $tag->tag]); $subTitleIcon = 'fa-tag'; /* * Default tag options (again) */ $tagOptions = $this->tagOptions; /* * Can this tag become another type? */ $allowAdvance = Tag::tagAllowAdvance($tag); $allowToBalancingAct = Tag::tagAllowBalancing($tag); // edit tag options: if ($allowAdvance === false) { unset($tagOptions['advancePayment']); } if ($allowToBalancingAct === false) { unset($tagOptions['balancingAct']); } // put previous url in session if not redirect from store (not "return_to_edit"). if (session('tags.edit.fromUpdate') !== true) { Session::put('tags.edit.url', URL::previous()); } Session::forget('tags.edit.fromUpdate'); Session::flash('gaEventCategory', 'tags'); Session::flash('gaEventAction', 'edit'); return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon', 'tagOptions')); }
/** * @param TransactionJournal $journal * @param array $array * * @return bool */ private function updateTags(TransactionJournal $journal, array $array) : bool { // create tag repository /** @var TagRepositoryInterface $tagRepository */ $tagRepository = app(TagRepositoryInterface::class); // find or create all tags: $tags = []; $ids = []; foreach ($array as $name) { if (strlen(trim($name)) > 0) { $tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]); $tags[] = $tag; $ids[] = $tag->id; } } // delete all tags connected to journal not in this array: if (count($ids) > 0) { DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->whereNotIn('tag_id', $ids)->delete(); } // if count is zero, delete them all: if (count($ids) == 0) { DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->delete(); } // connect each tag to journal (if not yet connected): /** @var Tag $tag */ foreach ($tags as $tag) { $tagRepository->connect($journal, $tag); } return true; }
/** * @param Tag $tag * @param $amount * * @return string */ protected function amountByTagAdvancePayment(Tag $tag, $amount) { if ($this->transactionType->type == 'Withdrawal') { $others = $tag->transactionJournals()->transactionTypes(['Deposit'])->get(); foreach ($others as $other) { $amount = bcsub($amount, $other->amount_positive); } return $amount; } if ($this->transactionType->type == 'Deposit') { return '0'; } return $amount; }
/** * Reports on tags without any transactions. */ private function reportTags() { $set = Tag::leftJoin('tag_transaction_journal', 'tags.id', '=', 'tag_transaction_journal.tag_id')->leftJoin('users', 'tags.user_id', '=', 'users.id')->distinct()->whereNull('tag_transaction_journal.tag_id')->whereNull('tags.deleted_at')->get(['tags.id', 'tags.tag', 'tags.user_id', 'users.email']); /** @var stdClass $entry */ foreach ($set as $entry) { $line = 'Notice: User #' . $entry->user_id . ' (' . $entry->email . ') has tag #' . $entry->id . ' ("' . $entry->tag . '") which has no transactions.'; $this->line($line); } }
/** * @param TransactionJournal $journal * @param Tag $tag * * @return bool */ protected function connectBalancingAct(TransactionJournal $journal, Tag $tag) : bool { /** @var TransactionType $withdrawal */ $withdrawal = TransactionType::whereType(TransactionType::WITHDRAWAL)->first(); $withdrawals = $tag->transactionJournals()->where('transaction_type_id', $withdrawal->id)->count(); /** @var TransactionType $transfer */ $transfer = TransactionType::whereType(TransactionType::TRANSFER)->first(); $transfers = $tag->transactionJournals()->where('transaction_type_id', $transfer->id)->count(); // only if this is the only withdrawal. if ($journal->transaction_type_id == $withdrawal->id && $withdrawals < 1) { $journal->tags()->save($tag); $journal->save(); return true; } // and only if this is the only transfer if ($journal->transaction_type_id == $transfer->id && $transfers < 1) { $journal->tags()->save($tag); $journal->save(); return true; } // ignore expense return false; }
/** * @covers FireflyIII\Repositories\Tag\TagRepository::destroy */ public function testDestroy() { $tag = FactoryMuffin::create('FireflyIII\\Models\\Tag'); $this->object->destroy($tag); $this->assertCount(0, Tag::where('id', $tag->id)->whereNull('deleted_at')->get()); }
/** * @param $tagName * * @return Tag|null * @internal param $tag */ protected function findTag($tagName) { /** @var Tag $tag */ foreach (Tag::get() as $tag) { if ($tag->tag == $tagName && $this->user->id == $tag->user_id) { return $tag; break; } } return null; }
} } throw new NotFoundHttpException(); }); Route::bind('category', function ($value) { if (Auth::check()) { $object = Category::where('id', $value)->where('user_id', Auth::user()->id)->first(); if ($object) { return $object; } } throw new NotFoundHttpException(); }); Route::bind('tag', function ($value) { if (Auth::check()) { $object = Tag::where('id', $value)->where('user_id', Auth::user()->id)->first(); if ($object) { return $object; } } throw new NotFoundHttpException(); }); /** * Auth\AuthController */ Route::get('/register', ['uses' => 'Auth\\AuthController@getRegister', 'as' => 'register']); Route::get('/cron/sendgrid', ['uses' => 'CronController@sendgrid']); Route::controllers(['auth' => 'Auth\\AuthController', 'password' => 'Auth\\PasswordController']); Route::group(['middleware' => ['auth', 'range']], function () { /** * Home Controller
/** * Returns an array of tags and their comparitive size with amounts bla bla. * * @param Carbon $start * @param Carbon $end * @param Collection $accounts * * @return array */ public function tagReport(Carbon $start, Carbon $end, Collection $accounts) : array { $ids = $accounts->pluck('id')->toArray(); $set = Tag::leftJoin('tag_transaction_journal', 'tags.id', '=', 'tag_transaction_journal.tag_id')->leftJoin('transaction_journals', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')->leftJoin('transactions AS source', function (JoinClause $join) { $join->on('source.transaction_journal_id', '=', 'transaction_journals.id')->where('source.amount', '<', '0'); })->leftJoin('transactions AS destination', function (JoinClause $join) { $join->on('destination.transaction_journal_id', '=', 'transaction_journals.id')->where('destination.amount', '>', '0'); })->where('transaction_journals.date', '>=', $start->format('Y-m-d'))->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->where(function (Builder $q) use($ids) { $q->whereIn('source.account_id', $ids)->whereIn('destination.account_id', $ids, 'xor'); })->get(['tags.id', 'tags.tag', 'transaction_journals.id as journal_id', 'destination.amount']); $collection = []; if ($set->count() === 0) { return $collection; } /** @var Tag $entry */ foreach ($set as $entry) { // less than zero? multiply to be above zero. $amount = $entry->amount; $id = intval($entry->id); $previousAmount = $collection[$id]['amount'] ?? '0'; $collection[$id] = ['id' => $id, 'tag' => $entry->tag, 'amount' => bcadd($previousAmount, $amount)]; } // cleanup collection (match "fonts") $max = strval(max(array_column($collection, 'amount'))); foreach ($collection as $id => $entry) { $size = bcdiv($entry['amount'], $max, 4); if (bccomp($size, '0.25') === -1) { $size = '0.5'; } $collection[$id]['fontsize'] = $size; } return $collection; }