/**
  * @param TransactionJournal $journal
  *
  * @return bool
  */
 public function act(TransactionJournal $journal) : bool
 {
     Log::debug(sprintf('RuleAction PrependDescription prepended "%s" to "%s".', $this->action->action_value, $journal->description));
     $journal->description = $this->action->action_value . $journal->description;
     $journal->save();
     return true;
 }
 /**
  * @param TransactionJournal $journal
  *
  * @return bool
  */
 public function act(TransactionJournal $journal) : bool
 {
     $name = $this->action->action_value;
     $category = Category::firstOrCreateEncrypted(['name' => $name, 'user_id' => $journal->user->id]);
     $journal->categories()->sync([$category->id]);
     Log::debug(sprintf('RuleAction SetCategory set the category of journal #%d to budget #%d ("%s").', $journal->id, $category->id, $category->name));
     return true;
 }
 /**
  * @param TransactionJournal $journal
  *
  * @return bool
  */
 public function act(TransactionJournal $journal) : bool
 {
     $oldDescription = $journal->description;
     $journal->description = $this->action->action_value;
     $journal->save();
     Log::debug(sprintf('RuleAction SetDescription changed the description of journal #%d from "%s" to "%s".', $journal->id, $oldDescription, $this->action->action_value));
     return true;
 }
 /**
  * @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;
 }
Exemple #5
0
 /**
  *
  * @param TransactionJournal $journal
  * @param bool               $coloured
  *
  * @return string
  */
 public function formatJournal(TransactionJournal $journal, $coloured = true)
 {
     $cache = new CacheProperties();
     $cache->addProperty($journal->id);
     $cache->addProperty('formatJournal');
     if ($cache->has()) {
         return $cache->get();
         // @codeCoverageIgnore
     }
     if (is_null($journal->symbol)) {
         $symbol = $journal->transactionCurrency->symbol;
     } else {
         $symbol = $journal->symbol;
     }
     if ($journal->isTransfer() && $coloured) {
         $txt = '<span class="text-info">' . $this->formatWithSymbol($symbol, $journal->amount_positive, false) . '</span>';
         $cache->store($txt);
         return $txt;
     }
     if ($journal->isTransfer() && !$coloured) {
         $txt = $this->formatWithSymbol($symbol, $journal->amount_positive, false);
         $cache->store($txt);
         return $txt;
     }
     $txt = $this->formatWithSymbol($symbol, $journal->amount, $coloured);
     $cache->store($txt);
     return $txt;
 }
 /**
  * Connect a new transaction journal to any related piggy banks.
  *
  * @param  TransactionJournalStored $event
  *
  * @return bool
  */
 public function handle(TransactionJournalStored $event) : bool
 {
     /** @var TransactionJournal $journal */
     $journal = $event->journal;
     $piggyBankId = $event->piggyBankId;
     /** @var PiggyBank $piggyBank */
     $piggyBank = auth()->user()->piggyBanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
     if (is_null($piggyBank)) {
         return true;
     }
     // update piggy bank rep for date of transaction journal.
     $repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
     if (is_null($repetition)) {
         return true;
     }
     $amount = TransactionJournal::amountPositive($journal);
     // if piggy account matches source account, the amount is positive
     $sources = TransactionJournal::sourceAccountList($journal)->pluck('id')->toArray();
     if (in_array($piggyBank->account_id, $sources)) {
         $amount = bcmul($amount, '-1');
     }
     $repetition->currentamount = bcadd($repetition->currentamount, $amount);
     $repetition->save();
     PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]);
     return true;
 }
 /**
  * @param TransactionJournal $journal
  *
  * @return bool
  */
 public function act(TransactionJournal $journal) : bool
 {
     // if tag does not exist, no need to continue:
     $name = $this->action->action_value;
     /** @var Tag $tag */
     $tag = $journal->user->tags()->get()->filter(function (Tag $tag) use($name) {
         return $tag->tag == $name;
     })->first();
     if (!is_null($tag)) {
         Log::debug(sprintf('RuleAction RemoveTag removed tag #%d ("%s") from journal #%d.', $tag->id, $tag->tag, $journal->id));
         $journal->tags()->detach([$tag->id]);
         return true;
     }
     Log::debug(sprintf('RuleAction RemoveTag tried to remove tag "%s" from journal #%d but no such tag exists.', $name, $journal->id));
     return true;
 }
 /**
  * Handle the event.
  *
  * @param  TransactionJournalUpdated $event
  * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
  *
  * @return bool
  */
 public function handle(TransactionJournalUpdated $event) : bool
 {
     $journal = $event->journal;
     if (!$journal->isTransfer()) {
         return true;
     }
     // get the event connected to this journal:
     /** @var PiggyBankEvent $event */
     $event = PiggyBankEvent::where('transaction_journal_id', $journal->id)->first();
     if (is_null($event)) {
         return false;
     }
     $piggyBank = $event->piggyBank()->first();
     $repetition = null;
     if (!is_null($piggyBank)) {
         /** @var PiggyBankRepetition $repetition */
         $repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
     }
     if (is_null($repetition)) {
         return false;
     }
     $amount = TransactionJournal::amount($journal);
     $diff = bcsub($amount, $event->amount);
     // update current repetition
     $repetition->currentamount = bcadd($repetition->currentamount, $diff);
     $repetition->save();
     $event->amount = $amount;
     $event->save();
     return true;
 }
 /**
  * @covers FireflyIII\Repositories\Journal\JournalRepository::delete
  * @covers FireflyIII\Providers\EventServiceProvider::boot
  * @covers FireflyIII\Providers\EventServiceProvider::registerDeleteEvents
  */
 public function testDelete()
 {
     $journal = FactoryMuffin::create('FireflyIII\\Models\\TransactionJournal');
     $transaction = $journal->transactions[0];
     $this->object->delete($journal);
     $this->assertEquals(0, TransactionJournal::where('id', $journal->id)->whereNull('deleted_at')->count());
     $this->assertEquals(0, Transaction::where('id', $transaction->id)->whereNull('deleted_at')->count());
 }
 /**
  * @param $value
  * @param $route
  *
  * @return mixed
  */
 public static function routeBinder($value, $route) : TransactionJournal
 {
     if (auth()->check()) {
         $object = TransactionJournal::where('transaction_journals.id', $value)->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')->where('completed', 0)->where('user_id', auth()->user()->id)->first(['transaction_journals.*']);
         if ($object) {
             return $object;
         }
     }
     throw new NotFoundHttpException();
 }
Exemple #11
0
 /**
  * @covers FireflyIII\Models\Tag::save
  */
 public function testSave()
 {
     $tag = FactoryMuffin::create('FireflyIII\\Models\\Tag');
     // connect some transaction journals to the tag:
     $journal = FactoryMuffin::create('FireflyIII\\Models\\TransactionJournal');
     $journal->tags()->save($tag);
     $tag->save();
     $journal = TransactionJournal::find($journal->id);
     $this->assertEquals(1, $journal->tag_count);
 }
 /**
  * @param $value
  *
  * @return mixed
  * @throws NotFoundHttpException
  */
 public static function routeBinder($value)
 {
     if (Auth::check()) {
         $validTypes = [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER];
         $object = TransactionJournal::where('transaction_journals.id', $value)->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')->whereIn('transaction_types.type', $validTypes)->where('user_id', Auth::user()->id)->first(['transaction_journals.*']);
         if ($object) {
             return $object;
         }
     }
     throw new NotFoundHttpException();
 }
 /**
  * @param TransactionJournal $journal
  *
  * @return bool
  */
 public function act(TransactionJournal $journal) : bool
 {
     /** @var BudgetRepositoryInterface $repository */
     $repository = app(BudgetRepositoryInterface::class, [$journal->user]);
     $search = $this->action->action_value;
     $budgets = $repository->getActiveBudgets();
     $budget = $budgets->filter(function (Budget $current) use($search) {
         return $current->name == $search;
     })->first();
     if (is_null($budget)) {
         Log::debug(sprintf('RuleAction SetBudget could not set budget of journal #%d to "%s" because no such budget exists.', $journal->id, $search));
         return true;
     }
     if ($journal->transactionType->type == TransactionType::TRANSFER) {
         Log::debug(sprintf('RuleAction SetBudget could not set budget of journal #%d to "%s" because journal is a transfer.', $journal->id, $search));
         return true;
     }
     Log::debug(sprintf('RuleAction SetBudget set the budget of journal #%d to budget #%d ("%s").', $journal->id, $budget->id, $budget->name));
     $journal->budgets()->sync([$budget->id]);
     return true;
 }
 /**
  * @param TransactionJournal $journal
  *
  * @return bool
  */
 public function triggered(TransactionJournal $journal) : bool
 {
     $amount = $journal->destination_amount ?? TransactionJournal::amountPositive($journal);
     $compare = $this->triggerValue;
     $result = bccomp($amount, $compare, 4);
     if ($result === 1) {
         Log::debug(sprintf('RuleTrigger AmountMore for journal #%d: %d is more than %d, so return true', $journal->id, $amount, $compare));
         return true;
     }
     Log::debug(sprintf('RuleTrigger AmountMore for journal #%d: %d is NOT more than %d, so return false', $journal->id, $amount, $compare));
     return false;
 }
 /**
  * @param $value
  * @param $route
  *
  * @return mixed
  */
 public static function routeBinder($value, $route) : Collection
 {
     if (auth()->check()) {
         $ids = explode(',', $value);
         /** @var \Illuminate\Support\Collection $object */
         $object = TransactionJournal::whereIn('transaction_journals.id', $ids)->expanded()->where('transaction_journals.user_id', auth()->user()->id)->get(TransactionJournal::queryFields());
         if ($object->count() > 0) {
             return $object;
         }
     }
     throw new NotFoundHttpException();
 }
 /**
  * @param Carbon $start
  * @param Carbon $end
  *
  * @return Builder
  */
 protected function queryJournalsWithTransactions(Carbon $start, Carbon $end)
 {
     $query = TransactionJournal::leftJoin('transactions as t_from', function (JoinClause $join) {
         $join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
     })->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id')->leftJoin('account_meta as acm_from', function (JoinClause $join) {
         $join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole');
     })->leftJoin('transactions as t_to', function (JoinClause $join) {
         $join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
     })->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id')->leftJoin('account_meta as acm_to', function (JoinClause $join) {
         $join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole');
     })->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id');
     $query->before($end)->after($start)->where('transaction_journals.user_id', Auth::user()->id);
     return $query;
 }
 /**
  * @param TransactionJournal $journal
  *
  * @return bool
  */
 public function triggered(TransactionJournal $journal) : bool
 {
     $name = '';
     /** @var Account $account */
     foreach (TransactionJournal::sourceAccountList($journal) as $account) {
         $name .= strtolower($account->name);
     }
     $search = strtolower($this->triggerValue);
     if ($name === $search) {
         Log::debug(sprintf('RuleTrigger FromAccountIs for journal #%d: "%s" is "%s", return true.', $journal->id, $name, $search));
         return true;
     }
     Log::debug(sprintf('RuleTrigger FromAccountIs for journal #%d: "%s" is NOT "%s", return false.', $journal->id, $name, $search));
     return false;
 }
 /**
  * @param TransactionJournal $journal
  *
  * @return bool
  */
 public function triggered(TransactionJournal $journal) : bool
 {
     $name = '';
     /** @var Account $account */
     foreach (TransactionJournal::sourceAccountList($journal) as $account) {
         $name .= strtolower($account->name);
     }
     $search = strtolower($this->triggerValue);
     $part = substr($name, 0, strlen($search));
     if ($part === $search) {
         Log::debug(sprintf('RuleTrigger FromAccountStarts for journal #%d: "%s" starts with "%s", return true.', $journal->id, $name, $search));
         return true;
     }
     Log::debug(sprintf('RuleTrigger FromAccountStarts for journal #%d: "%s" does not start with "%s", return false.', $journal->id, $name, $search));
     return false;
 }
 /**
  *
  */
 protected function registerDeleteEvents()
 {
     TransactionJournal::deleted(function (TransactionJournal $journal) {
         /** @var Transaction $transaction */
         foreach ($journal->transactions()->get() as $transaction) {
             $transaction->delete();
         }
     });
     Account::deleted(function (Account $account) {
         /** @var Transaction $transaction */
         foreach ($account->transactions()->get() as $transaction) {
             $journal = $transaction->transactionJournal()->first();
             $journal->delete();
         }
     });
 }
 /**
  * @param TransactionJournal $journal
  *
  * @return bool
  */
 public function triggered(TransactionJournal $journal) : bool
 {
     $fromAccountName = '';
     /** @var Account $account */
     foreach (TransactionJournal::sourceAccountList($journal) as $account) {
         $fromAccountName .= strtolower($account->name);
     }
     $search = strtolower($this->triggerValue);
     $strpos = strpos($fromAccountName, $search);
     if (!($strpos === false)) {
         Log::debug(sprintf('RuleTrigger FromAccountContains for journal #%d: "%s" contains "%s", return true.', $journal->id, $fromAccountName, $search));
         return true;
     }
     Log::debug(sprintf('RuleTrigger FromAccountContains for journal #%d: "%s" does not contain "%s", return false.', $journal->id, $fromAccountName, $search));
     return false;
 }
 /**
  * @param Bill       $bill
  * @param Collection $entries
  *
  * @return array
  */
 public function single(Bill $bill, Collection $entries) : array
 {
     $format = (string) trans('config.month');
     $data = ['count' => 3, 'labels' => [], 'datasets' => []];
     $minAmount = [];
     $maxAmount = [];
     $actualAmount = [];
     /** @var TransactionJournal $entry */
     foreach ($entries as $entry) {
         $data['labels'][] = $entry->date->formatLocalized($format);
         $minAmount[] = round($bill->amount_min, 2);
         $maxAmount[] = round($bill->amount_max, 2);
         // journalAmount has been collected in BillRepository::getJournals
         $actualAmount[] = round(TransactionJournal::amountPositive($entry), 2);
     }
     $data['datasets'][] = ['type' => 'bar', 'label' => trans('firefly.minAmount'), 'data' => $minAmount];
     $data['datasets'][] = ['type' => 'line', 'label' => trans('firefly.billEntry'), 'data' => $actualAmount];
     $data['datasets'][] = ['type' => 'bar', 'label' => trans('firefly.maxAmount'), 'data' => $maxAmount];
     $data['count'] = count($data['datasets']);
     return $data;
 }
Exemple #22
0
 /**
  * @param TransactionJournal $journal
  *
  * @return Entry
  */
 public static function fromJournal(TransactionJournal $journal)
 {
     $entry = new self();
     $entry->description = $journal->description;
     $entry->date = $journal->date->format('Y-m-d');
     $entry->amount = TransactionJournal::amount($journal);
     $entry->budget = new EntryBudget($journal->budgets->first());
     $entry->category = new EntryCategory($journal->categories->first());
     $entry->bill = new EntryBill($journal->bill);
     $sources = TransactionJournal::sourceAccountList($journal);
     $destinations = TransactionJournal::destinationAccountList($journal);
     $entry->sourceAccount = new EntryAccount($sources->first());
     $entry->destinationAccount = new EntryAccount($destinations->first());
     foreach ($sources as $source) {
         $entry->sourceAccounts->push(new EntryAccount($source));
     }
     foreach ($destinations as $destination) {
         $entry->destinationAccounts->push(new EntryAccount($destination));
     }
     return $entry;
 }
Exemple #23
0
 /**
  * @param TransactionJournal $entry
  */
 public function addOrCreateIncome(TransactionJournal $entry)
 {
     // add each account individually:
     $sources = TransactionJournal::sourceTransactionList($entry);
     foreach ($sources as $transaction) {
         $amount = strval($transaction->amount);
         $account = $transaction->account;
         $amount = bcmul($amount, '-1');
         $object = new stdClass();
         $object->amount = $amount;
         $object->name = $account->name;
         $object->count = 1;
         $object->id = $account->id;
         // overrule some properties:
         if ($this->incomes->has($account->id)) {
             $object = $this->incomes->get($account->id);
             $object->amount = bcadd($object->amount, $amount);
             $object->count++;
         }
         $this->incomes->put($account->id, $object);
     }
 }
 /**
  *
  */
 protected function registerDeleteEvents()
 {
     Account::deleted(function (Account $account) {
         Log::debug('Now trigger account delete response #' . $account->id);
         /** @var Transaction $transaction */
         foreach ($account->transactions()->get() as $transaction) {
             Log::debug('Now at transaction #' . $transaction->id);
             $journal = $transaction->transactionJournal()->first();
             if (!is_null($journal)) {
                 Log::debug('Call for deletion of journal #' . $journal->id);
                 $journal->delete();
             }
         }
     });
     TransactionJournal::deleted(function (TransactionJournal $journal) {
         Log::debug('Now triggered journal delete response #' . $journal->id);
         /** @var Transaction $transaction */
         foreach ($journal->transactions()->get() as $transaction) {
             Log::debug('Will now delete transaction #' . $transaction->id);
             $transaction->delete();
         }
     });
 }
Exemple #25
0
 /**
  *
  * @param \FireflyIII\Models\TransactionJournal $journal
  * @param bool                                  $coloured
  *
  * @return string
  */
 public function formatJournal(TransactionJournal $journal, bool $coloured = true) : string
 {
     $locale = setlocale(LC_MONETARY, 0);
     $float = round(TransactionJournal::amount($journal), 2);
     $formatter = new NumberFormatter($locale, NumberFormatter::CURRENCY);
     $currencyCode = $journal->transaction_currency_code ?? $journal->transactionCurrency->code;
     $result = $formatter->formatCurrency($float, $currencyCode);
     if ($coloured === true && $float === 0.0) {
         return '<span style="color:#999">' . $result . '</span>';
         // always grey.
     }
     if (!$coloured) {
         return $result;
     }
     if (!$journal->isTransfer()) {
         if ($float > 0) {
             return '<span class="text-success">' . $result . '</span>';
         }
         return '<span class="text-danger">' . $result . '</span>';
     } else {
         return '<span class="text-info">' . $result . '</span>';
     }
 }
 /**
  * @param TransactionJournal $entry
  */
 public function addOrCreateExpense(TransactionJournal $entry)
 {
     // add each account individually:
     $destinations = TransactionJournal::destinationTransactionList($entry);
     foreach ($destinations as $transaction) {
         $amount = strval($transaction->amount);
         $account = $transaction->account;
         if (bccomp('0', $amount) === -1) {
             $amount = bcmul($amount, '-1');
         }
         $object = new stdClass();
         $object->amount = $amount;
         $object->name = $account->name;
         $object->count = 1;
         $object->id = $account->id;
         // overrule some properties:
         if ($this->expenses->has($account->id)) {
             $object = $this->expenses->get($account->id);
             $object->amount = bcadd($object->amount, $amount);
             $object->count++;
         }
         $this->expenses->put($account->id, $object);
     }
 }
 /**
  * @param TransactionJournal $journal
  *
  * @return bool
  */
 public function triggered(TransactionJournal $journal) : bool
 {
     $toAccountName = '';
     /** @var Account $account */
     foreach (TransactionJournal::destinationAccountList($journal) as $account) {
         $toAccountName .= strtolower($account->name);
     }
     $toAccountNameLength = strlen($toAccountName);
     $search = strtolower($this->triggerValue);
     $searchLength = strlen($search);
     // if the string to search for is longer than the account name,
     // shorten the search string.
     if ($searchLength > $toAccountNameLength) {
         $search = substr($search, $toAccountNameLength * -1);
         $searchLength = strlen($search);
     }
     $part = substr($toAccountName, $searchLength * -1);
     if ($part === $search) {
         Log::debug(sprintf('RuleTrigger ToAccountEnds for journal #%d: "%s" ends with "%s", return true.', $journal->id, $toAccountName, $search));
         return true;
     }
     Log::debug(sprintf('RuleTrigger ToAccountEnds for journal #%d: "%s" does not end with "%s", return false.', $journal->id, $toAccountName, $search));
     return false;
 }
Exemple #28
0
 /**
  * @param array $words
  *
  * @return Collection
  */
 public function searchTransactions(array $words) : Collection
 {
     // decrypted transaction journals:
     $decrypted = auth()->user()->transactionJournals()->expanded()->where('transaction_journals.encrypted', 0)->where(function (EloquentBuilder $q) use($words) {
         foreach ($words as $word) {
             $q->orWhere('transaction_journals.description', 'LIKE', '%' . e($word) . '%');
         }
     })->get(TransactionJournal::queryFields());
     // encrypted
     $all = auth()->user()->transactionJournals()->expanded()->where('transaction_journals.encrypted', 1)->get(TransactionJournal::queryFields());
     $set = $all->filter(function (TransactionJournal $journal) use($words) {
         foreach ($words as $word) {
             $haystack = strtolower($journal->description);
             $word = strtolower($word);
             if (!(strpos($haystack, $word) === false)) {
                 return $journal;
             }
         }
         return null;
     });
     $filtered = $set->merge($decrypted);
     $filtered = $filtered->sortBy(function (TransactionJournal $journal) {
         return intval($journal->date->format('U'));
     });
     $filtered = $filtered->reverse();
     return $filtered;
 }
 /**
  * @param Bill               $bill
  * @param TransactionJournal $journal
  *
  * @return boolean|null
  */
 public function scan(Bill $bill, TransactionJournal $journal)
 {
     $matches = explode(',', $bill->match);
     $description = strtolower($journal->description) . ' ' . strtolower($journal->destination_account->name);
     $wordMatch = $this->doWordMatch($matches, $description);
     $amountMatch = $this->doAmountMatch($journal->amount_positive, $bill->amount_min, $bill->amount_max);
     Log::debug('Journal #' . $journal->id . ' has description "' . $description . '"');
     /*
      * If both, update!
      */
     if ($wordMatch && $amountMatch) {
         $journal->bill()->associate($bill);
         $journal->save();
         return true;
     } else {
         Log::debug('Wordmatch: ' . ($wordMatch ? 'true' : 'false') . ' AmountMatch: ' . ($amountMatch ? 'true' : 'false'));
     }
     if ($bill->id == $journal->bill_id) {
         // if no match, but bill used to match, remove it:
         $journal->bill_id = null;
         $journal->save();
         return true;
     }
     return false;
 }
 /**
  * @param Carbon $date
  *
  * @return TransactionJournal
  */
 protected function createSavings(Carbon $date)
 {
     $date = new Carbon($date->format('Y-m') . '-24');
     // paid on 24th.
     $toAccount = $this->findAccount('Savings');
     $fromAccount = $this->findAccount('MyBank Checking Account');
     $category = Category::firstOrCreateEncrypted(['name' => 'Money management', 'user_id' => $this->user->id]);
     // create journal:
     $journal = TransactionJournal::create(['user_id' => $this->user->id, 'transaction_type_id' => 3, 'transaction_currency_id' => 1, 'description' => 'Save money', 'completed' => 1, 'date' => $date]);
     Transaction::create(['account_id' => $fromAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => -150]);
     Transaction::create(['account_id' => $toAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => 150]);
     $journal->categories()->save($category);
     return $journal;
 }