mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-11-04 05:15:39 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			643 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			643 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace FireflyIII\Repositories\Account;
 | 
						|
 | 
						|
use Auth;
 | 
						|
use Carbon\Carbon;
 | 
						|
use Config;
 | 
						|
use DB;
 | 
						|
use FireflyIII\Models\Account;
 | 
						|
use FireflyIII\Models\AccountMeta;
 | 
						|
use FireflyIII\Models\AccountType;
 | 
						|
use FireflyIII\Models\PiggyBank;
 | 
						|
use FireflyIII\Models\Preference;
 | 
						|
use FireflyIII\Models\Transaction;
 | 
						|
use FireflyIII\Models\TransactionJournal;
 | 
						|
use FireflyIII\Models\TransactionType;
 | 
						|
use FireflyIII\Support\CacheProperties;
 | 
						|
use Illuminate\Database\Eloquent\Relations\HasMany;
 | 
						|
use Illuminate\Database\Query\Builder;
 | 
						|
use Illuminate\Pagination\LengthAwarePaginator;
 | 
						|
use Illuminate\Support\Collection;
 | 
						|
use Log;
 | 
						|
use Session;
 | 
						|
use Steam;
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * @SuppressWarnings(PHPMD.TooManyMethods)
 | 
						|
 *
 | 
						|
 * Class AccountRepository
 | 
						|
 *
 | 
						|
 * @package FireflyIII\Repositories\Account
 | 
						|
 */
 | 
						|
class AccountRepository implements AccountRepositoryInterface
 | 
						|
{
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param array $types
 | 
						|
     *
 | 
						|
     * @return int
 | 
						|
     */
 | 
						|
    public function countAccounts(array $types)
 | 
						|
    {
 | 
						|
        return Auth::user()->accounts()->accountTypeIn($types)->count();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Account $account
 | 
						|
     * @param Account $moveTo
 | 
						|
     *
 | 
						|
     * @return boolean
 | 
						|
     */
 | 
						|
    public function destroy(Account $account, Account $moveTo = null)
 | 
						|
    {
 | 
						|
        if (!is_null($moveTo)) {
 | 
						|
            // update all transactions:
 | 
						|
            DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]);
 | 
						|
        }
 | 
						|
 | 
						|
        $account->delete();
 | 
						|
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param array $types
 | 
						|
     *
 | 
						|
     * @return Collection
 | 
						|
     */
 | 
						|
    public function getAccounts(array $types)
 | 
						|
    {
 | 
						|
        /** @var Collection $result */
 | 
						|
        $result = Auth::user()->accounts()->with(
 | 
						|
            ['accountmeta' => function (HasMany $query) {
 | 
						|
                $query->where('name', 'accountRole');
 | 
						|
            }]
 | 
						|
        )->accountTypeIn($types)->get(['accounts.*']);
 | 
						|
 | 
						|
        $result = $result->sortBy(
 | 
						|
            function (Account $account) {
 | 
						|
                return strtolower($account->name);
 | 
						|
            }
 | 
						|
        );
 | 
						|
 | 
						|
        return $result;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return Collection
 | 
						|
     */
 | 
						|
    public function getCreditCards()
 | 
						|
    {
 | 
						|
        return Auth::user()->accounts()
 | 
						|
                   ->hasMetaValue('accountRole', 'ccAsset')
 | 
						|
                   ->hasMetaValue('ccType', 'monthlyFull')
 | 
						|
                   ->get(
 | 
						|
                       [
 | 
						|
                           'accounts.*',
 | 
						|
                           'ccType.data as ccType',
 | 
						|
                           'accountRole.data as accountRole'
 | 
						|
                       ]
 | 
						|
                   );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param TransactionJournal $journal
 | 
						|
     * @param Account            $account
 | 
						|
     *
 | 
						|
     * @return Transaction
 | 
						|
     */
 | 
						|
    public function getFirstTransaction(TransactionJournal $journal, Account $account)
 | 
						|
    {
 | 
						|
 | 
						|
        return $journal->transactions()->where('account_id', $account->id)->first();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Preference $preference
 | 
						|
     *
 | 
						|
     * @return Collection
 | 
						|
     */
 | 
						|
    public function getFrontpageAccounts(Preference $preference)
 | 
						|
    {
 | 
						|
        $cache = new CacheProperties();
 | 
						|
        $cache->addProperty($preference->data);
 | 
						|
        $cache->addProperty('frontPageaccounts');
 | 
						|
        if ($cache->has()) {
 | 
						|
            return $cache->get(); // @codeCoverageIgnore
 | 
						|
        }
 | 
						|
        $query = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account']);
 | 
						|
 | 
						|
        if (count($preference->data) > 0) {
 | 
						|
            $query->whereIn('id', $preference->data);
 | 
						|
        }
 | 
						|
 | 
						|
        $result = $query->get(['accounts.*']);
 | 
						|
 | 
						|
        $cache->store($result);
 | 
						|
 | 
						|
        return $result;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * This method is used on the front page where (in turn) its viewed journals-tiny.php which (in turn)
 | 
						|
     * is almost the only place where formatJournal is used. Aka, we can use some custom querying to get some specific.
 | 
						|
     * fields using left joins.
 | 
						|
     *
 | 
						|
     * @param Account $account
 | 
						|
     * @param Carbon  $start
 | 
						|
     * @param Carbon  $end
 | 
						|
     *
 | 
						|
     * @return mixed
 | 
						|
     */
 | 
						|
    public function getFrontpageTransactions(Account $account, Carbon $start, Carbon $end)
 | 
						|
    {
 | 
						|
        $cache = new CacheProperties();
 | 
						|
        $cache->addProperty($account->id);
 | 
						|
        $cache->addProperty($start);
 | 
						|
        $cache->addProperty($end);
 | 
						|
        if ($cache->has()) {
 | 
						|
            return $cache->get(); // @codeCoverageIgnore
 | 
						|
        }
 | 
						|
 | 
						|
        $set = Auth::user()
 | 
						|
                   ->transactionjournals()
 | 
						|
                   ->with(['transactions'])
 | 
						|
                   ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
 | 
						|
                   ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')->where('accounts.id', $account->id)
 | 
						|
                   ->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transaction_journals.transaction_currency_id')
 | 
						|
                   ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
 | 
						|
                   ->before($end)
 | 
						|
                   ->after($start)
 | 
						|
                   ->orderBy('transaction_journals.date', 'DESC')
 | 
						|
                   ->orderBy('transaction_journals.id', 'DESC')
 | 
						|
                   ->take(10)
 | 
						|
                   ->get(['transaction_journals.*', 'transaction_currencies.symbol', 'transaction_types.type']);
 | 
						|
        $cache->store($set);
 | 
						|
 | 
						|
        return $set;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Account $account
 | 
						|
     * @param int     $page
 | 
						|
     *
 | 
						|
     * @return LengthAwarePaginator
 | 
						|
     */
 | 
						|
    public function getJournals(Account $account, $page)
 | 
						|
    {
 | 
						|
        $offset = ($page - 1) * 50;
 | 
						|
        $query  = Auth::user()
 | 
						|
                      ->transactionJournals()
 | 
						|
                      ->withRelevantData()
 | 
						|
                      ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
 | 
						|
                      ->where('transactions.account_id', $account->id)
 | 
						|
                      ->orderBy('transaction_journals.date', 'DESC')
 | 
						|
                      ->orderBy('transaction_journals.order', 'ASC')
 | 
						|
                      ->orderBy('transaction_journals.id', 'DESC');
 | 
						|
 | 
						|
        $count     = $query->count();
 | 
						|
        $set       = $query->take(50)->offset($offset)->get(['transaction_journals.*']);
 | 
						|
        $paginator = new LengthAwarePaginator($set, $count, 50, $page);
 | 
						|
 | 
						|
        return $paginator;
 | 
						|
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the accounts of a user that have piggy banks connected to them.
 | 
						|
     *
 | 
						|
     * @return Collection
 | 
						|
     */
 | 
						|
    public function getPiggyBankAccounts()
 | 
						|
    {
 | 
						|
        $ids        = [];
 | 
						|
        $start      = clone Session::get('start', new Carbon);
 | 
						|
        $end        = clone Session::get('end', new Carbon);
 | 
						|
        $accountIds = DB::table('piggy_banks')->distinct()->get(['piggy_banks.account_id']);
 | 
						|
        $accounts   = new Collection;
 | 
						|
 | 
						|
        /** @var PiggyBank $id */
 | 
						|
        foreach ($accountIds as $id) {
 | 
						|
            $ids[] = intval($id->account_id);
 | 
						|
        }
 | 
						|
 | 
						|
        $cache = new CacheProperties;
 | 
						|
        $cache->addProperty($ids);
 | 
						|
        $cache->addProperty('piggyAccounts');
 | 
						|
        if ($cache->has()) {
 | 
						|
            return $cache->get(); // @codeCoverageIgnore
 | 
						|
        }
 | 
						|
 | 
						|
        $ids = array_unique($ids);
 | 
						|
        if (count($ids) > 0) {
 | 
						|
            $accounts = Auth::user()->accounts()->whereIn('id', $ids)->get();
 | 
						|
        }
 | 
						|
 | 
						|
        $accounts->each(
 | 
						|
            function (Account $account) use ($start, $end) {
 | 
						|
                $account->startBalance = Steam::balance($account, $start, true);
 | 
						|
                $account->endBalance   = Steam::balance($account, $end, true);
 | 
						|
                $account->piggyBalance = 0;
 | 
						|
                /** @var PiggyBank $piggyBank */
 | 
						|
                foreach ($account->piggyBanks as $piggyBank) {
 | 
						|
                    $account->piggyBalance += $piggyBank->currentRelevantRep()->currentamount;
 | 
						|
                }
 | 
						|
                // sum of piggy bank amounts on this account:
 | 
						|
                // diff between endBalance and piggyBalance.
 | 
						|
                // then, percentage.
 | 
						|
                $difference          = $account->endBalance - $account->piggyBalance;
 | 
						|
                $account->difference = $difference;
 | 
						|
                $account->percentage = $difference != 0 && $account->endBalance != 0 ? round((($difference / $account->endBalance) * 100)) : 100;
 | 
						|
 | 
						|
            }
 | 
						|
        );
 | 
						|
 | 
						|
        $cache->store($accounts);
 | 
						|
 | 
						|
        return $accounts;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get savings accounts and the balance difference in the period.
 | 
						|
     *
 | 
						|
     * @return Collection
 | 
						|
     */
 | 
						|
    public function getSavingsAccounts()
 | 
						|
    {
 | 
						|
        $accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')
 | 
						|
                        ->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
 | 
						|
                        ->where('account_meta.name', 'accountRole')
 | 
						|
                        ->where('account_meta.data', '"savingAsset"')
 | 
						|
                        ->get(['accounts.*']);
 | 
						|
        $start    = clone Session::get('start', new Carbon);
 | 
						|
        $end      = clone Session::get('end', new Carbon);
 | 
						|
 | 
						|
        $accounts->each(
 | 
						|
            function (Account $account) use ($start, $end) {
 | 
						|
                $account->startBalance = Steam::balance($account, $start);
 | 
						|
                $account->endBalance   = Steam::balance($account, $end);
 | 
						|
 | 
						|
                // diff (negative when lost, positive when gained)
 | 
						|
                $diff = $account->endBalance - $account->startBalance;
 | 
						|
 | 
						|
                if ($diff < 0 && $account->startBalance > 0) {
 | 
						|
                    // percentage lost compared to start.
 | 
						|
                    $pct = (($diff * -1) / $account->startBalance) * 100;
 | 
						|
                } else {
 | 
						|
                    if ($diff >= 0 && $account->startBalance > 0) {
 | 
						|
                        $pct = ($diff / $account->startBalance) * 100;
 | 
						|
                    } else {
 | 
						|
                        $pct = 100;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                $pct                 = $pct > 100 ? 100 : $pct;
 | 
						|
                $account->difference = $diff;
 | 
						|
                $account->percentage = round($pct);
 | 
						|
 | 
						|
            }
 | 
						|
        );
 | 
						|
 | 
						|
        return $accounts;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get all transfers TO this account in this range.
 | 
						|
     *
 | 
						|
     * @param Account $account
 | 
						|
     * @param Carbon  $start
 | 
						|
     * @param Carbon  $end
 | 
						|
     *
 | 
						|
     * @return Collection
 | 
						|
     */
 | 
						|
    public function getTransfersInRange(Account $account, Carbon $start, Carbon $end)
 | 
						|
    {
 | 
						|
        $set      = TransactionJournal::whereIn(
 | 
						|
            'id', function (Builder $q) use ($account, $start, $end) {
 | 
						|
            $q->select('transaction_journals.id')
 | 
						|
              ->from('transactions')
 | 
						|
              ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
 | 
						|
              ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
 | 
						|
              ->where('transactions.account_id', $account->id)
 | 
						|
              ->where('transaction_journals.user_id', Auth::user()->id)
 | 
						|
              ->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
 | 
						|
              ->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
 | 
						|
              ->where('transaction_types.type', 'Transfer');
 | 
						|
 | 
						|
        }
 | 
						|
        )->get();
 | 
						|
        $filtered = $set->filter(
 | 
						|
            function (TransactionJournal $journal) use ($account) {
 | 
						|
                if ($journal->destination_account->id == $account->id) {
 | 
						|
                    return $journal;
 | 
						|
                }
 | 
						|
 | 
						|
                return null;
 | 
						|
            }
 | 
						|
        );
 | 
						|
 | 
						|
        return $filtered;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Account $account
 | 
						|
     * @param Carbon  $date
 | 
						|
     *
 | 
						|
     * @return float
 | 
						|
     */
 | 
						|
    public function leftOnAccount(Account $account, Carbon $date)
 | 
						|
    {
 | 
						|
 | 
						|
        $balance = Steam::balance($account, $date, true);
 | 
						|
        /** @var PiggyBank $p */
 | 
						|
        foreach ($account->piggybanks()->get() as $p) {
 | 
						|
            $balance -= $p->currentRelevantRep()->currentamount;
 | 
						|
        }
 | 
						|
 | 
						|
        return $balance;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Account $account
 | 
						|
     *
 | 
						|
     * @return TransactionJournal|null
 | 
						|
     */
 | 
						|
    public function openingBalanceTransaction(Account $account)
 | 
						|
    {
 | 
						|
        return TransactionJournal
 | 
						|
            ::orderBy('transaction_journals.date', 'ASC')
 | 
						|
            ->accountIs($account)
 | 
						|
            ->orderBy('created_at', 'ASC')
 | 
						|
            ->first(['transaction_journals.*']);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param array $data
 | 
						|
     *
 | 
						|
     * @return Account
 | 
						|
     */
 | 
						|
    public function store(array $data)
 | 
						|
    {
 | 
						|
        $newAccount = $this->storeAccount($data);
 | 
						|
        if (!is_null($newAccount)) {
 | 
						|
            $this->storeMetadata($newAccount, $data);
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        // continue with the opposing account:
 | 
						|
        if ($data['openingBalance'] != 0) {
 | 
						|
            $type         = $data['openingBalance'] < 0 ? 'expense' : 'revenue';
 | 
						|
            $opposingData = [
 | 
						|
                'user'           => $data['user'],
 | 
						|
                'accountType'    => $type,
 | 
						|
                'virtualBalance' => 0,
 | 
						|
                'name'           => $data['name'] . ' initial balance',
 | 
						|
                'active'         => false,
 | 
						|
                'iban'           => '',
 | 
						|
            ];
 | 
						|
            $opposing     = $this->storeAccount($opposingData);
 | 
						|
            if (!is_null($opposing) && !is_null($newAccount)) {
 | 
						|
                $this->storeInitialBalance($newAccount, $opposing, $data);
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
 | 
						|
        return $newAccount;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    public function sumOfEverything()
 | 
						|
    {
 | 
						|
        return Auth::user()->transactions()->sum('amount');
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Account $account
 | 
						|
     * @param array   $data
 | 
						|
     *
 | 
						|
     * @return Account
 | 
						|
     */
 | 
						|
    public function update(Account $account, array $data)
 | 
						|
    {
 | 
						|
        // update the account:
 | 
						|
        $account->name            = $data['name'];
 | 
						|
        $account->active          = $data['active'] == '1' ? true : false;
 | 
						|
        $account->virtual_balance = $data['virtualBalance'];
 | 
						|
        $account->iban            = $data['iban'];
 | 
						|
        $account->save();
 | 
						|
 | 
						|
        $this->updateMetadata($account, $data);
 | 
						|
        $openingBalance = $this->openingBalanceTransaction($account);
 | 
						|
 | 
						|
        // if has openingbalance?
 | 
						|
        if ($data['openingBalance'] != 0) {
 | 
						|
            // if opening balance, do an update:
 | 
						|
            if ($openingBalance) {
 | 
						|
                // update existing opening balance.
 | 
						|
                $this->updateInitialBalance($account, $openingBalance, $data);
 | 
						|
            } else {
 | 
						|
                // create new opening balance.
 | 
						|
                $type         = $data['openingBalance'] < 0 ? 'expense' : 'revenue';
 | 
						|
                $opposingData = [
 | 
						|
                    'user'           => $data['user'],
 | 
						|
                    'accountType'    => $type,
 | 
						|
                    'name'           => $data['name'] . ' initial balance',
 | 
						|
                    'active'         => false,
 | 
						|
                    'iban'           => '',
 | 
						|
                    'virtualBalance' => 0,
 | 
						|
                ];
 | 
						|
                $opposing     = $this->storeAccount($opposingData);
 | 
						|
                if (!is_null($opposing)) {
 | 
						|
                    $this->storeInitialBalance($account, $opposing, $data);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
        } else {
 | 
						|
            if ($openingBalance) { // opening balance is zero, should we delete it?
 | 
						|
                $openingBalance->delete(); // delete existing opening balance.
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return $account;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param array $data
 | 
						|
     *
 | 
						|
     * @return Account
 | 
						|
     */
 | 
						|
    protected function storeAccount(array $data)
 | 
						|
    {
 | 
						|
        $type        = Config::get('firefly.accountTypeByIdentifier.' . $data['accountType']);
 | 
						|
        $accountType = AccountType::whereType($type)->first();
 | 
						|
        $newAccount  = new Account(
 | 
						|
            [
 | 
						|
                'user_id'         => $data['user'],
 | 
						|
                'account_type_id' => $accountType->id,
 | 
						|
                'name'            => $data['name'],
 | 
						|
                'virtual_balance' => $data['virtualBalance'],
 | 
						|
                'active'          => $data['active'] === true ? true : false,
 | 
						|
                'iban'            => $data['iban'],
 | 
						|
            ]
 | 
						|
        );
 | 
						|
 | 
						|
        if (!$newAccount->isValid()) {
 | 
						|
            // does the account already exist?
 | 
						|
            $searchData      = [
 | 
						|
                'user_id'         => $data['user'],
 | 
						|
                'account_type_id' => $accountType->id,
 | 
						|
                'virtual_balance' => $data['virtualBalance'],
 | 
						|
                'name'            => $data['name'],
 | 
						|
                'iban'            => $data['iban'],
 | 
						|
            ];
 | 
						|
            $existingAccount = Account::firstOrNullEncrypted($searchData);
 | 
						|
            if (!$existingAccount) {
 | 
						|
                Log::error('Account create error: ' . $newAccount->getErrors()->toJson());
 | 
						|
                abort(500);
 | 
						|
                // @codeCoverageIgnoreStart
 | 
						|
            }
 | 
						|
            // @codeCoverageIgnoreEnd
 | 
						|
            $newAccount = $existingAccount;
 | 
						|
 | 
						|
        }
 | 
						|
        $newAccount->save();
 | 
						|
 | 
						|
        return $newAccount;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Account $account
 | 
						|
     * @param array   $data
 | 
						|
     */
 | 
						|
    protected function storeMetadata(Account $account, array $data)
 | 
						|
    {
 | 
						|
        $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType'];
 | 
						|
        foreach ($validFields as $field) {
 | 
						|
            if (isset($data[$field])) {
 | 
						|
                $metaData = new AccountMeta(
 | 
						|
                    [
 | 
						|
                        'account_id' => $account->id,
 | 
						|
                        'name'       => $field,
 | 
						|
                        'data'       => $data[$field]
 | 
						|
                    ]
 | 
						|
                );
 | 
						|
                $metaData->save();
 | 
						|
            }
 | 
						|
 | 
						|
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Account $account
 | 
						|
     * @param Account $opposing
 | 
						|
     * @param array   $data
 | 
						|
     *
 | 
						|
     * @return TransactionJournal
 | 
						|
     */
 | 
						|
    protected function storeInitialBalance(Account $account, Account $opposing, array $data)
 | 
						|
    {
 | 
						|
        $transactionType = TransactionType::whereType('Opening balance')->first();
 | 
						|
        $journal         = TransactionJournal::create(
 | 
						|
            [
 | 
						|
                'user_id'                 => $data['user'],
 | 
						|
                'transaction_type_id'     => $transactionType->id,
 | 
						|
                'bill_id'                 => null,
 | 
						|
                'transaction_currency_id' => $data['openingBalanceCurrency'],
 | 
						|
                'description'             => 'Initial balance for "' . $account->name . '"',
 | 
						|
                'completed'               => true,
 | 
						|
                'date'                    => $data['openingBalanceDate'],
 | 
						|
                'encrypted'               => true
 | 
						|
            ]
 | 
						|
        );
 | 
						|
 | 
						|
        if ($data['openingBalance'] < 0) {
 | 
						|
            $firstAccount  = $opposing;
 | 
						|
            $secondAccount = $account;
 | 
						|
            $firstAmount   = $data['openingBalance'] * -1;
 | 
						|
            $secondAmount  = $data['openingBalance'];
 | 
						|
        } else {
 | 
						|
            $firstAccount  = $account;
 | 
						|
            $secondAccount = $opposing;
 | 
						|
            $firstAmount   = $data['openingBalance'];
 | 
						|
            $secondAmount  = $data['openingBalance'] * -1;
 | 
						|
        }
 | 
						|
 | 
						|
        $one = new Transaction(['account_id' => $firstAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $firstAmount]);
 | 
						|
        $one->save();// first transaction: from
 | 
						|
 | 
						|
        $two = new Transaction(['account_id' => $secondAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $secondAmount]);
 | 
						|
        $two->save(); // second transaction: to
 | 
						|
 | 
						|
        return $journal;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Account $account
 | 
						|
     * @param array   $data
 | 
						|
     *
 | 
						|
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
 | 
						|
     */
 | 
						|
    protected function updateMetadata(Account $account, array $data)
 | 
						|
    {
 | 
						|
        $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType'];
 | 
						|
 | 
						|
        foreach ($validFields as $field) {
 | 
						|
            $entry = $account->accountMeta()->where('name', $field)->first();
 | 
						|
 | 
						|
            // update if new data is present:
 | 
						|
            if ($entry && isset($data[$field])) {
 | 
						|
                $entry->data = $data[$field];
 | 
						|
                $entry->save();
 | 
						|
            }
 | 
						|
            // no entry but data present?
 | 
						|
            if (!$entry && isset($data[$field])) {
 | 
						|
                $metaData = new AccountMeta(
 | 
						|
                    [
 | 
						|
                        'account_id' => $account->id,
 | 
						|
                        'name'       => $field,
 | 
						|
                        'data'       => $data[$field]
 | 
						|
                    ]
 | 
						|
                );
 | 
						|
                $metaData->save();
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param Account            $account
 | 
						|
     * @param TransactionJournal $journal
 | 
						|
     * @param array              $data
 | 
						|
     *
 | 
						|
     * @return TransactionJournal
 | 
						|
     */
 | 
						|
    protected function updateInitialBalance(Account $account, TransactionJournal $journal, array $data)
 | 
						|
    {
 | 
						|
        $journal->date = $data['openingBalanceDate'];
 | 
						|
 | 
						|
        /** @var Transaction $transaction */
 | 
						|
        foreach ($journal->transactions()->get() as $transaction) {
 | 
						|
            if ($account->id == $transaction->account_id) {
 | 
						|
                $transaction->amount = $data['openingBalance'];
 | 
						|
                $transaction->save();
 | 
						|
            }
 | 
						|
            if ($account->id != $transaction->account_id) {
 | 
						|
                $transaction->amount = $data['openingBalance'] * -1;
 | 
						|
                $transaction->save();
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return $journal;
 | 
						|
    }
 | 
						|
}
 |