diff --git a/app/lib/Firefly/Storage/Account/EloquentAccountRepository.php b/app/lib/Firefly/Storage/Account/EloquentAccountRepository.php index a5f0b4a4a7..2f4b4acfc7 100644 --- a/app/lib/Firefly/Storage/Account/EloquentAccountRepository.php +++ b/app/lib/Firefly/Storage/Account/EloquentAccountRepository.php @@ -25,6 +25,56 @@ class EloquentAccountRepository implements AccountRepositoryInterface $this->_user = \Auth::user(); } + /** + * @return mixed + */ + public function count() + { + return $this->_user->accounts()->count(); + + } + + /** + * @param \Account $account + * + * @return bool|mixed + */ + public function destroy(\Account $account) + { + // find all transaction journals related to this account: + $journals = \TransactionJournal::withRelevantData()->accountIs($account)->get(['transaction_journals.*']); + $accountIDs = []; + + /** @var \TransactionJournal $journal */ + foreach ($journals as $journal) { + // remember the account id's of the transactions involved: + foreach ($journal->transactions as $t) { + $accountIDs[] = $t->account_id; + } + $journal->delete(); + + } + $accountIDs = array_unique($accountIDs); + if (count($accountIDs) > 0) { + // find the "initial balance" type accounts in this list. Should be just 1. + $query = $this->_user->accounts()->accountTypeIn(['Initial balance account']) + ->whereIn('accounts.id', $accountIDs); + if ($query->count() == 1) { + $iba = $query->first(['accounts.*']); + $iba->delete(); + } + } + $account->delete(); + + /** + * + * TODO + * Also delete: initial balance, initial balance account, and transactions + */ + + return true; + } + /** * @param $id * @@ -45,10 +95,12 @@ class EloquentAccountRepository implements AccountRepositoryInterface */ public function findExpenseAccountByName($name) { + $cashType = $this->findAccountType('Cash account'); + $importType = $this->findAccountType('Import account'); // catch Import account: if ($name == 'Import account') { - $importType = $this->findAccountType('Import account'); - $import = $this->firstOrCreate( + + $import = $this->firstOrCreate( [ 'name' => 'Import account', 'user_id' => $this->_user->id, @@ -77,10 +129,11 @@ class EloquentAccountRepository implements AccountRepositoryInterface $account = $this->firstOrCreate($set); } + // find cash account as fall back: if (is_null($account)) { - $cashType = $this->findAccountType('Cash account'); - $account = $this->_user->accounts()->where('account_type_id', $cashType->id)->first(); + + $account = $this->_user->accounts()->where('account_type_id', $cashType->id)->first(); } // create cash account as ultimate fall back: @@ -94,7 +147,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface $account = $this->firstOrCreate($set); } - if ($account->active == 0) { + if ($account->active == 0 && $account->account_type_id != $cashType->id) { return null; } @@ -176,6 +229,320 @@ class EloquentAccountRepository implements AccountRepositoryInterface return $account; } + public function getByAccountType(\AccountType $type) + { + return $this->_user->accounts()->with('accounttype')->orderBy('name', 'ASC') + ->where('account_type_id', $type->id)->get(); + } + + /** + * @param $ids + * + * @return array|mixed + */ + public function getByIds(array $ids) + { + if (count($ids) > 0) { + return $this->_user->accounts()->with('accounttype')->whereIn('id', $ids)->orderBy('name', 'ASC')->get(); + } else { + return $this->getActiveDefault(); + } + } +// +// /** +// * @param $name +// * +// * @return \Account|mixed|null +// */ +// public function createOrFindBeneficiary($name) +// { +// if (is_null($name) || strlen($name) == 0) { +// return null; +// } +// $type = \AccountType::where('type', 'Expense account')->first(); +// return $this->createOrFind($name, $type); +// } +// +// /** +// * @param $name +// * @param \AccountType $type +// * +// * @return \Account|mixed +// */ +// public function createOrFind($name, \AccountType $type = null) +// { +// $account = $this->findByName($name, $type); +// if (!$account) { +// $data = [ +// 'name' => $name, +// 'account_type' => $type +// ]; +// +// return $this->store($data); +// } +// +// return $account; +// } +// +// /** +// * @param $name +// * @param \AccountType $type +// * +// * @return mixed +// */ +// public function findByName($name, \AccountType $type = null) +// { +// $type = is_null($type) ? \AccountType::where('type', 'Asset account')->first() : $type; +// +// return $this->_user->accounts()->where('account_type_id', $type->id) +// ->where('name', 'like', '%' . $name . '%') +// ->first(); +// } + + /** + * @return mixed + */ + public function getActiveDefault() + { + return $this->_user->accounts()->accountTypeIn(['Default account', 'Asset account'])->where( + 'accounts.active', 1 + ) + ->get(['accounts.*']); + } + + /** + * @return mixed + */ + public function getDefault() + { + return $this->_user->accounts()->accountTypeIn(['Default account', 'Asset account']) + ->orderBy('accounts.name', 'ASC')->get(['accounts.*']); + } + + /** + * Gets a list of accounts that have the mentioned type. Will automatically convert + * strings in this array to actual (model) account types. + * + * @param array $types + * + * @return Collection + */ + public function getOfTypes(array $types) + { + $accounts = $this->_user->accounts()->accountTypeIn($types)->get(['accounts.*']); + return $accounts; + } + + /** + * @param Job $job + * @param array $payload + * + * @return mixed + */ + public function importAccount(Job $job, array $payload) + { + /** @var \Firefly\Storage\Import\ImportRepositoryInterface $repository */ + $repository = \App::make('Firefly\Storage\Import\ImportRepositoryInterface'); + + /** @var \Importmap $importMap */ + $importMap = $repository->findImportmap($payload['mapID']); + $user = $importMap->user; + $this->overruleUser($user); + + /* + * maybe Account is already imported: + */ + $importEntry = $repository->findImportEntry($importMap, 'Account', intval($payload['data']['id'])); + + /* + * if so, delete job and return: + */ + if (!is_null($importEntry)) { + \Log::debug('Already imported ' . $payload['data']['name'] . ' of type ' . $payload['account_type']); + $importMap->jobsdone++; + $importMap->save(); + $job->delete(); // count fixed + return; + } + + /* + * find the payload's account type: + */ + $payload['account_type'] = isset($payload['account_type']) ? $payload['account_type'] : 'Expense account'; + $type = $this->findAccountType($payload['account_type']); + + /* + * Create data array for store() procedure. + */ + $data = [ + 'account_type' => $type, + 'name' => $payload['data']['name'], + ]; + if (isset($payload['data']['openingbalance'])) { + $data['openingbalance'] = floatval($payload['data']['openingbalance']); + $data['openingbalancedate'] = $payload['data']['openingbalancedate']; + } + if (isset($payload['data']['inactive'])) { + $data['active'] = intval($payload['data']['inactive']) == 0 ? 1 : 0; + } + + /* + * Try to store: + */ + $account = $this->store($data); + + /* + * Check for failure. + */ + if (count($account->errors()) > 0) { + \Log::error('Account creation error: ' . $account->errors()->first()); + + $importMap->jobsdone++; + $importMap->save(); + + $job->delete(); // count fixed + return; + } + \Log::debug('Imported ' . $payload['account_type'] . ': ' . $payload['data']['name']); + + /* + * Save meta data + */ + $repository->store($importMap, 'Account', intval($payload['data']['id']), $account->id); + $importMap->jobsdone++; + $importMap->save(); + $job->delete(); // count fixed. + return; + } + +// /** +// * Used for import +// * +// * @param $name +// * +// * @return mixed +// */ +// public function findByNameAny($name) +// { +// return $this->_user->accounts() +// ->where('name', 'like', '%' . $name . '%') +// ->first(); +// } + + /** + * @param $data + * + * @return \Account + * @throws \Firefly\Exception\FireflyException + */ + public function store($data) + { + /** + * If the AccountType has been passed through, use it: + */ + if (isset($data['account_type']) && is_object($data['account_type']) + && get_class($data['account_type']) == 'AccountType' + ) { + $accountType = $data['account_type']; + } else if (isset($data['account_type']) && is_string($data['account_type'])) { + // if it isnt but set as string, find it: + $accountType = \AccountType::where('type', $data['account_type'])->first(); + + } else { + $accountType = \AccountType::where('type', 'Asset account')->first(); + } + $active = isset($data['active']) && intval($data['active']) >= 0 && intval($data['active']) <= 1 ? intval( + $data['active'] + ) : 1; + + /** + * Create new account: + */ + $account = new \Account; + $account->accountType()->associate($accountType); + $account->user()->associate($this->_user); + + $account->name = $data['name']; + $account->active + = isset($data['active']) && intval($data['active']) >= 0 && intval($data['active']) <= 1 ? intval( + $data['active'] + ) : 1; + + // try to save it: + try { + if ($account->save()) { + // create initial balance, if necessary: + if (isset($data['openingbalance']) && isset($data['openingbalancedate'])) { + $amount = floatval($data['openingbalance']); + $date = new Carbon($data['openingbalancedate']); + if ($amount != 0) { + $this->_createInitialBalance($account, $amount, $date); + } + } + } + } catch (QueryException $e) { + // do nothing + } + + + // whatever the result, return the account. + return $account; + } + + /** + * @param \Account $account + * @param int $amount + * @param Carbon $date + * + * @return bool + * @SuppressWarnings(PHPMD.CamelCaseMethodName) + */ + protected function _createInitialBalance(\Account $account, $amount = 0, Carbon $date) + { + /* + * The repositories we need: + */ + /** @var \Firefly\Helper\Controllers\TransactionInterface $transactions */ + $transactions = \App::make('Firefly\Helper\Controllers\TransactionInterface'); + $transactions->overruleUser($this->_user); + + + /* + * get account type: + */ + $initialBalanceAT = $this->findAccountType('Initial balance account'); + + /* + * create new account + */ + $initial = new \Account; + $initial->accountType()->associate($initialBalanceAT); + $initial->user()->associate($this->_user); + $initial->name = $account->name . ' initial balance'; + $initial->active = 0; + if ($initial->validate()) { + $initial->save(); + /* + * create new transaction journal (and transactions): + */ + + $set = [ + 'account_from_id' => $initial->id, + 'account_to_id' => $account->id, + 'description' => 'Initial Balance for ' . $account->name, + 'what' => 'Opening balance', + 'amount' => $amount, + 'category' => '', + 'date' => $date->format('Y-m-d') + ]; + $transactions->store($set); + + return true; + } + + return false; + } + /** * Takes a transaction/account component and updates the transaction journal to match. * @@ -322,371 +689,6 @@ class EloquentAccountRepository implements AccountRepositoryInterface return $this->_user->accounts()->where('id', $accountId)->first(); } - /** - * @param Job $job - * @param array $payload - * - * @return mixed - */ - public function importAccount(Job $job, array $payload) - { - /** @var \Firefly\Storage\Import\ImportRepositoryInterface $repository */ - $repository = \App::make('Firefly\Storage\Import\ImportRepositoryInterface'); - - /** @var \Importmap $importMap */ - $importMap = $repository->findImportmap($payload['mapID']); - $user = $importMap->user; - $this->overruleUser($user); - - /* - * maybe Account is already imported: - */ - $importEntry = $repository->findImportEntry($importMap, 'Account', intval($payload['data']['id'])); - - /* - * if so, delete job and return: - */ - if (!is_null($importEntry)) { - \Log::debug('Already imported ' . $payload['data']['name'] . ' of type ' . $payload['account_type']); - $importMap->jobsdone++; - $importMap->save(); - $job->delete(); // count fixed - return; - } - - /* - * find the payload's account type: - */ - $payload['account_type'] = isset($payload['account_type']) ? $payload['account_type'] : 'Expense account'; - $type = $this->findAccountType($payload['account_type']); - - /* - * Create data array for store() procedure. - */ - $data = [ - 'account_type' => $type, - 'name' => $payload['data']['name'], - ]; - if (isset($payload['data']['openingbalance'])) { - $data['openingbalance'] = floatval($payload['data']['openingbalance']); - $data['openingbalancedate'] = $payload['data']['openingbalancedate']; - } - if (isset($payload['data']['inactive'])) { - $data['active'] = intval($payload['data']['inactive']) == 0 ? 1 : 0; - } - - /* - * Try to store: - */ - $account = $this->store($data); - - /* - * Check for failure. - */ - if (count($account->errors()) > 0) { - \Log::error('Account creation error: ' . $account->errors()->first()); - - $importMap->jobsdone++; - $importMap->save(); - - $job->delete(); // count fixed - return; - } - \Log::debug('Imported ' . $payload['account_type'] . ': ' . $payload['data']['name']); - - /* - * Save meta data - */ - $repository->store($importMap, 'Account', intval($payload['data']['id']), $account->id); - $importMap->jobsdone++; - $importMap->save(); - $job->delete(); // count fixed. - return; - } -// -// /** -// * @param $name -// * -// * @return \Account|mixed|null -// */ -// public function createOrFindBeneficiary($name) -// { -// if (is_null($name) || strlen($name) == 0) { -// return null; -// } -// $type = \AccountType::where('type', 'Expense account')->first(); -// return $this->createOrFind($name, $type); -// } -// -// /** -// * @param $name -// * @param \AccountType $type -// * -// * @return \Account|mixed -// */ -// public function createOrFind($name, \AccountType $type = null) -// { -// $account = $this->findByName($name, $type); -// if (!$account) { -// $data = [ -// 'name' => $name, -// 'account_type' => $type -// ]; -// -// return $this->store($data); -// } -// -// return $account; -// } -// -// /** -// * @param $name -// * @param \AccountType $type -// * -// * @return mixed -// */ -// public function findByName($name, \AccountType $type = null) -// { -// $type = is_null($type) ? \AccountType::where('type', 'Asset account')->first() : $type; -// -// return $this->_user->accounts()->where('account_type_id', $type->id) -// ->where('name', 'like', '%' . $name . '%') -// ->first(); -// } - - /** - * @param $data - * - * @return \Account - * @throws \Firefly\Exception\FireflyException - */ - public function store($data) - { - /** - * If the AccountType has been passed through, use it: - */ - if (isset($data['account_type']) && is_object($data['account_type']) - && get_class($data['account_type']) == 'AccountType' - ) { - $accountType = $data['account_type']; - } else if (isset($data['account_type']) && is_string($data['account_type'])) { - // if it isnt but set as string, find it: - $accountType = \AccountType::where('type', $data['account_type'])->first(); - - } else { - $accountType = \AccountType::where('type', 'Asset account')->first(); - } - $active = isset($data['active']) && intval($data['active']) >= 0 && intval($data['active']) <= 1 ? intval( - $data['active'] - ) : 1; - - /** - * Create new account: - */ - $account = new \Account; - $account->accountType()->associate($accountType); - $account->user()->associate($this->_user); - - $account->name = $data['name']; - $account->active - = - isset($data['active']) && intval($data['active']) >= 0 && intval($data['active']) <= 1 ? intval( - $data['active'] - ) : 1; - - // try to save it: - try { - if ($account->save()) { - // create initial balance, if necessary: - if (isset($data['openingbalance']) && isset($data['openingbalancedate'])) { - $amount = floatval($data['openingbalance']); - $date = new Carbon($data['openingbalancedate']); - if ($amount != 0) { - $this->_createInitialBalance($account, $amount, $date); - } - } - } - } catch (QueryException $e) { - // do nothing - } - - - // whatever the result, return the account. - return $account; - } - - /** - * @param \Account $account - * @param int $amount - * @param Carbon $date - * - * @return bool - * @SuppressWarnings(PHPMD.CamelCaseMethodName) - */ - protected function _createInitialBalance(\Account $account, $amount = 0, Carbon $date) - { - /* - * The repositories we need: - */ - /** @var \Firefly\Helper\Controllers\TransactionInterface $transactions */ - $transactions = \App::make('Firefly\Helper\Controllers\TransactionInterface'); - $transactions->overruleUser($this->_user); - - - /* - * get account type: - */ - $initialBalanceAT = $this->findAccountType('Initial balance account'); - - /* - * create new account - */ - $initial = new \Account; - $initial->accountType()->associate($initialBalanceAT); - $initial->user()->associate($this->_user); - $initial->name = $account->name . ' initial balance'; - $initial->active = 0; - if ($initial->validate()) { - $initial->save(); - /* - * create new transaction journal (and transactions): - */ - - $set = [ - 'account_from_id' => $initial->id, - 'account_to_id' => $account->id, - 'description' => 'Initial Balance for ' . $account->name, - 'what' => 'Opening balance', - 'amount' => $amount, - 'category' => '', - 'date' => $date->format('Y-m-d') - ]; - $transactions->store($set); - - return true; - } - - return false; - } - - /** - * Gets a list of accounts that have the mentioned type. Will automatically convert - * strings in this array to actual (model) account types. - * - * @param array $types - * - * @return Collection - */ - public function getOfTypes(array $types) - { - $accounts = $this->_user->accounts()->accountTypeIn($types)->get(['accounts.*']); - return $accounts; - } - - /** - * @return mixed - */ - public function count() - { - return $this->_user->accounts()->count(); - - } - -// /** -// * Used for import -// * -// * @param $name -// * -// * @return mixed -// */ -// public function findByNameAny($name) -// { -// return $this->_user->accounts() -// ->where('name', 'like', '%' . $name . '%') -// ->first(); -// } - - /** - * @param \Account $account - * - * @return bool|mixed - */ - public function destroy(\Account $account) - { - // find all transaction journals related to this account: - $journals = \TransactionJournal::withRelevantData()->accountIs($account)->get(['transaction_journals.*']); - $accountIDs = []; - - /** @var \TransactionJournal $journal */ - foreach ($journals as $journal) { - // remember the account id's of the transactions involved: - foreach ($journal->transactions as $t) { - $accountIDs[] = $t->account_id; - } - $journal->delete(); - - } - $accountIDs = array_unique($accountIDs); - if (count($accountIDs) > 0) { - // find the "initial balance" type accounts in this list. Should be just 1. - $query = $this->_user->accounts()->accountTypeIn(['Initial balance account']) - ->whereIn('accounts.id', $accountIDs); - if ($query->count() == 1) { - $iba = $query->first(['accounts.*']); - $iba->delete(); - } - } - $account->delete(); - - /** - * - * TODO - * Also delete: initial balance, initial balance account, and transactions - */ - - return true; - } - - public function getByAccountType(\AccountType $type) - { - return $this->_user->accounts()->with('accounttype')->orderBy('name', 'ASC') - ->where('account_type_id', $type->id)->get(); - } - - /** - * @param $ids - * - * @return array|mixed - */ - public function getByIds(array $ids) - { - if (count($ids) > 0) { - return $this->_user->accounts()->with('accounttype')->whereIn('id', $ids)->orderBy('name', 'ASC')->get(); - } else { - return $this->getActiveDefault(); - } - } - - /** - * @return mixed - */ - public function getActiveDefault() - { - return $this->_user->accounts()->accountTypeIn(['Default account', 'Asset account'])->where( - 'accounts.active', 1 - ) - ->get(['accounts.*']); - } - - /** - * @return mixed - */ - public function getDefault() - { - return $this->_user->accounts()->accountTypeIn(['Default account', 'Asset account']) - ->orderBy('accounts.name', 'ASC')->get(['accounts.*']); - } - /** * @param \Account $account * @param $data