firefly-iii/app/Repositories/Journal/JournalRepository.php

306 lines
10 KiB
PHP
Raw Normal View History

2015-02-09 00:23:39 -06:00
<?php
namespace FireflyIII\Repositories\Journal;
2015-04-03 15:54:21 -05:00
use App;
2015-02-27 07:27:04 -06:00
use Auth;
2015-04-28 03:36:13 -05:00
use DB;
2015-02-24 15:53:38 -06:00
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
2015-04-28 03:36:13 -05:00
use FireflyIII\Models\Tag;
2015-02-24 15:53:38 -06:00
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
2015-02-25 14:19:06 -06:00
use Illuminate\Support\Collection;
2015-04-03 15:54:21 -05:00
use Log;
2015-02-24 15:53:38 -06:00
2015-02-11 00:35:10 -06:00
/**
* Class JournalRepository
*
* @package FireflyIII\Repositories\Journal
*/
class JournalRepository implements JournalRepositoryInterface
{
2015-02-09 00:23:39 -06:00
2015-04-03 15:54:21 -05:00
/**
* Get users first transaction journal
*
* @return TransactionJournal
*/
public function first()
{
return Auth::user()->transactionjournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']);
}
2015-04-11 12:59:41 -05:00
/**
* @param TransactionType $dbType
*
* @return Collection
*/
public function getJournalsOfType(TransactionType $dbType)
{
return Auth::user()->transactionjournals()->where('transaction_type_id', $dbType->id)->orderBy('id', 'DESC')->take(50)->get();
}
/**
* @param $type
*
* @return TransactionType
*/
public function getTransactionType($type)
{
return TransactionType::whereType($type)->first();
}
2015-04-28 03:36:13 -05:00
/**
2015-04-28 06:47:13 -05:00
*
* * Remember: a balancingAct takes at most one expense and one transfer.
* an advancePayment takes at most one expense, infinite deposits and NO transfers.
*
2015-04-28 03:36:13 -05:00
* @param TransactionJournal $journal
* @param array $array
*
* @return void
*/
public function saveTags(TransactionJournal $journal, array $array)
{
2015-04-28 10:10:52 -05:00
/** @var \FireflyIII\Repositories\Tag\TagRepositoryInterface $tagRepository */
$tagRepository = App::make('FireflyIII\Repositories\Tag\TagRepositoryInterface');
2015-04-28 03:36:13 -05:00
foreach ($array as $name) {
2015-04-28 14:01:54 -05:00
if (strlen(trim($name)) > 0) {
$tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]);
$tagRepository->connect($journal, $tag);
}
2015-04-28 03:36:13 -05:00
}
}
2015-02-24 15:53:38 -06:00
/**
* @param array $data
*
* @return TransactionJournal
*/
public function store(array $data)
{
// find transaction type.
$transactionType = TransactionType::where('type', ucfirst($data['what']))->first();
// store actual journal.
$journal = new TransactionJournal(
[
'user_id' => $data['user'],
'transaction_type_id' => $transactionType->id,
'transaction_currency_id' => $data['amount_currency_id'],
'description' => $data['description'],
'completed' => 0,
'date' => $data['date'],
]
);
$journal->save();
// store or get category
if (strlen($data['category']) > 0) {
$category = Category::firstOrCreateEncrypted(['name' => $data['category'], 'user_id' => $data['user']]);
2015-02-24 15:53:38 -06:00
$journal->categories()->save($category);
}
// store or get budget
if (intval($data['budget_id']) > 0) {
$budget = Budget::find($data['budget_id']);
$journal->budgets()->save($budget);
}
// store accounts (depends on type)
2015-03-29 05:32:00 -05:00
list($from, $to) = $this->storeAccounts($transactionType, $data);
2015-02-24 15:53:38 -06:00
// store accompanying transactions.
Transaction::create( // first transaction.
[
'account_id' => $from->id,
'transaction_journal_id' => $journal->id,
'amount' => $data['amount'] * -1
]
);
2015-04-03 15:54:21 -05:00
Transaction::create( // second transaction.
2015-02-24 15:53:38 -06:00
[
'account_id' => $to->id,
'transaction_journal_id' => $journal->id,
'amount' => $data['amount']
]
);
2015-02-27 07:27:04 -06:00
$journal->completed = 1;
$journal->save();
2015-02-24 15:53:38 -06:00
2015-04-28 07:08:58 -05:00
// store tags
if (isset($data['tags']) && is_array($data['tags'])) {
$this->saveTags($journal, $data['tags']);
}
2015-02-24 15:53:38 -06:00
return $journal;
}
2015-02-27 07:27:04 -06:00
/**
* @param TransactionJournal $journal
* @param array $data
*
* @return mixed
*/
public function update(TransactionJournal $journal, array $data)
{
// update actual journal.
$journal->transaction_currency_id = $data['amount_currency_id'];
$journal->description = $data['description'];
$journal->date = $data['date'];
// unlink all categories, recreate them:
$journal->categories()->detach();
if (strlen($data['category']) > 0) {
$category = Category::firstOrCreateEncrypted(['name' => $data['category'], 'user_id' => $data['user']]);
2015-02-27 07:27:04 -06:00
$journal->categories()->save($category);
}
// unlink all budgets and recreate them:
$journal->budgets()->detach();
if (intval($data['budget_id']) > 0) {
$budget = Budget::find($data['budget_id']);
$journal->budgets()->save($budget);
}
// store accounts (depends on type)
2015-03-29 05:32:00 -05:00
list($from, $to) = $this->storeAccounts($journal->transactionType, $data);
// update the from and to transaction.
/** @var Transaction $transaction */
foreach ($journal->transactions()->get() as $transaction) {
if (floatval($transaction->amount) < 0) {
// this is the from transaction, negative amount:
$transaction->amount = $data['amount'] * -1;
$transaction->account_id = $from->id;
$transaction->save();
}
if (floatval($transaction->amount) > 0) {
$transaction->amount = $data['amount'];
$transaction->account_id = $to->id;
$transaction->save();
}
}
$journal->save();
2015-04-28 03:36:13 -05:00
// update tags:
if (isset($data['tags']) && is_array($data['tags'])) {
$this->updateTags($journal, $data['tags']);
}
2015-03-29 05:32:00 -05:00
return $journal;
}
2015-04-28 03:36:13 -05:00
/**
* @param TransactionJournal $journal
* @param array $array
*
* @return void
*/
public function updateTags(TransactionJournal $journal, array $array)
{
2015-04-28 10:10:52 -05:00
// create tag repository
/** @var \FireflyIII\Repositories\Tag\TagRepositoryInterface $tagRepository */
$tagRepository = App::make('FireflyIII\Repositories\Tag\TagRepositoryInterface');
2015-04-28 03:36:13 -05:00
// find or create all tags:
$tags = [];
$ids = [];
foreach ($array as $name) {
2015-04-28 14:01:54 -05:00
if (strlen(trim($name)) > 0) {
$tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]);
$tags[] = $tag;
$ids[] = $tag->id;
}
2015-04-28 03:36:13 -05:00
}
// 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();
}
2015-05-02 15:30:59 -05:00
// if count is zero, delete them all:
if(count($ids) == 0) {
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->delete();
}
2015-04-28 03:36:13 -05:00
// connect each tag to journal (if not yet connected):
2015-04-28 06:47:13 -05:00
/** @var Tag $tag */
foreach ($tags as $tag) {
2015-04-28 10:10:52 -05:00
$tagRepository->connect($journal, $tag);
2015-04-28 03:36:13 -05:00
}
}
2015-03-29 05:32:00 -05:00
/**
* @param TransactionType $type
* @param array $data
*
* @return array
*/
protected function storeAccounts(TransactionType $type, array $data)
{
$from = null;
2015-04-03 15:54:21 -05:00
$to = null;
2015-03-29 05:32:00 -05:00
switch ($type->type) {
2015-02-27 07:27:04 -06:00
case 'Withdrawal':
$from = Account::find($data['account_id']);
if (strlen($data['expense_account']) > 0) {
$toType = AccountType::where('type', 'Expense account')->first();
2015-04-03 15:54:21 -05:00
$to = Account::firstOrCreateEncrypted(
2015-02-27 07:27:04 -06:00
['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => $data['expense_account'], 'active' => 1]
);
} else {
$toType = AccountType::where('type', 'Cash account')->first();
2015-04-03 15:54:21 -05:00
$to = Account::firstOrCreateEncrypted(
['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1]
);
2015-02-27 07:27:04 -06:00
}
break;
case 'Deposit':
$to = Account::find($data['account_id']);
if (strlen($data['revenue_account']) > 0) {
$fromType = AccountType::where('type', 'Revenue account')->first();
$from = Account::firstOrCreateEncrypted(
2015-02-27 07:27:04 -06:00
['user_id' => $data['user'], 'account_type_id' => $fromType->id, 'name' => $data['revenue_account'], 'active' => 1]
);
} else {
$toType = AccountType::where('type', 'Cash account')->first();
2015-04-03 15:54:21 -05:00
$from = Account::firstOrCreateEncrypted(
['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1]
);
2015-02-27 07:27:04 -06:00
}
break;
case 'Transfer':
$from = Account::find($data['account_from_id']);
$to = Account::find($data['account_to_id']);
break;
}
2015-04-03 15:54:21 -05:00
if (is_null($to->id)) {
Log::error('"to"-account is null, so we cannot continue!');
App::abort(500, '"to"-account is null, so we cannot continue!');
}
if (is_null($from->id)) {
Log::error('"from"-account is null, so we cannot continue!');
App::abort(500, '"from"-account is null, so we cannot continue!');
}
2015-02-27 07:27:04 -06:00
2015-03-29 05:32:00 -05:00
return [$from, $to];
2015-02-27 07:27:04 -06:00
}
}