diff --git a/app/Helpers/Csv/Converter/AssetAccountNumber.php b/app/Helpers/Csv/Converter/AssetAccountNumber.php new file mode 100644 index 0000000000..b66ee6a7f4 --- /dev/null +++ b/app/Helpers/Csv/Converter/AssetAccountNumber.php @@ -0,0 +1,89 @@ +mapped[$this->index][$this->value])) { + $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); + + return $account; + } + // if not, search for it (or create it): + $value = $this->value ?? ''; + if (strlen($value) > 0) { + // find or create new account: + $account = $this->findAccount(); + + if (is_null($account->id)) { + // create it if doesn't exist. + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + + + $accountData = [ + 'name' => $this->value, + 'accountType' => 'asset', + 'virtualBalance' => 0, + 'virtualBalanceCurrency' => 1, // TODO hard coded. + 'active' => true, + 'user' => Auth::user()->id, + 'iban' => null, + 'accountNumber' => $this->value, + 'accountRole' => null, + 'openingBalance' => 0, + 'openingBalanceDate' => new Carbon, + 'openingBalanceCurrency' => 1, // TODO hard coded. + + ]; + + $account = $repository->store($accountData); + } + + return $account; + } + + return null; + } + + /** + * @return Account + */ + protected function findAccount(): Account + { + $set = Auth::user()->accounts()->with(['accountmeta'])->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']); + /** @var Account $entry */ + foreach ($set as $entry) { + $accountNumber = $entry->getMeta('accountNumber'); + if ($accountNumber == $this->value) { + + return $entry; + } + } + + return new Account; + } +} diff --git a/app/Helpers/Csv/PostProcessing/AssetAccount.php b/app/Helpers/Csv/PostProcessing/AssetAccount.php index 8e12cb3b61..a6a8e043c2 100644 --- a/app/Helpers/Csv/PostProcessing/AssetAccount.php +++ b/app/Helpers/Csv/PostProcessing/AssetAccount.php @@ -3,6 +3,7 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\PostProcessing; use Auth; +use Carbon\Carbon; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use Log; @@ -29,15 +30,22 @@ class AssetAccount implements PostProcessorInterface return $result; } + // no object? maybe asset-account-iban is a string and we can find the matching account. $result = $this->checkIbanString(); if (!is_null($result)) { return $result; } + // no object still? maybe we can find the account by name. $result = $this->checkNameString(); if (!is_null($result)) { return $result; } + // still nothing? Perhaps the account number can lead us to an account: + $result = $this->checkAccountNumberString(); + if (!is_null($result)) { + return $result; + } return null; } @@ -51,17 +59,18 @@ class AssetAccount implements PostProcessorInterface } /** - * @return array + * @return array|null */ - protected function checkIdNameObject() + protected function checkAccountNumberString() { - if ($this->data['asset-account-id'] instanceof Account) { // first priority. try to find the account based on ID, if any - $this->data['asset-account-object'] = $this->data['asset-account-id']; + $accountNumber = $this->data['asset-account-number'] ?? null; + if ($accountNumber instanceof Account) { // fourth: try to find account based on name, if any. + $this->data['asset-account-object'] = $accountNumber; return $this->data; } - if ($this->data['asset-account-iban'] instanceof Account) { // second: try to find the account based on IBAN, if any. - $this->data['asset-account-object'] = $this->data['asset-account-iban']; + if (is_string($accountNumber)) { // it's an actual account number + $this->data['asset-account-object'] = $this->parseAccountNumberString(); return $this->data; } @@ -74,8 +83,9 @@ class AssetAccount implements PostProcessorInterface */ protected function checkIbanString() { + $iban = $this->data['asset-account-iban'] ?? ''; $rules = ['iban' => 'iban']; - $check = ['iban' => $this->data['asset-account-iban']]; + $check = ['iban' => $iban]; $validator = Validator::make($check, $rules); if (!$validator->fails()) { $this->data['asset-account-object'] = $this->parseIbanString(); @@ -87,21 +97,52 @@ class AssetAccount implements PostProcessorInterface } /** - * @return Account|null + * @return array */ - protected function parseIbanString() + protected function checkIdNameObject() { - // create by name and/or iban. - $accounts = Auth::user()->accounts()->get(); - foreach ($accounts as $entry) { - if ($entry->iban == $this->data['asset-account-iban']) { + $accountId = $this->data['asset-account-id'] ?? null; + $accountIban = $this->data['asset-account-iban'] ?? null; + $accountNumber = $this->data['asset-account-number'] ?? null; + if ($accountId instanceof Account) { // first priority. try to find the account based on ID, if any + $this->data['asset-account-object'] = $accountId; - return $entry; - } + return $this->data; } - $account = $this->createAccount(); + if ($accountIban instanceof Account) { // second: try to find the account based on IBAN, if any. + $this->data['asset-account-object'] = $accountIban; - return $account; + return $this->data; + } + + if ($accountNumber instanceof Account) { // second: try to find the account based on account number, if any. + $this->data['asset-account-object'] = $accountNumber; + + return $this->data; + } + + + return null; + } + + /** + * @return array|null + */ + protected function checkNameString() + { + $accountName = $this->data['asset-account-name'] ?? null; + if ($accountName instanceof Account) { // third: try to find account based on name, if any. + $this->data['asset-account-object'] = $accountName; + + return $this->data; + } + if (is_string($accountName)) { + $this->data['asset-account-object'] = $this->parseNameString(); + + return $this->data; + } + + return null; } /** @@ -110,16 +151,17 @@ class AssetAccount implements PostProcessorInterface protected function createAccount() { $accountType = $this->getAccountType(); + $name = $this->data['asset-account-name'] ?? ''; + $iban = $this->data['asset-account-iban'] ?? ''; - // create if not exists: - $name = is_string($this->data['asset-account-name']) && strlen($this->data['asset-account-name']) > 0 ? $this->data['asset-account-name'] - : $this->data['asset-account-iban']; - $account = Account::firstOrCreateEncrypted( + // create if not exists: // TODO should be through repository. + $name = strlen($name) > 0 ? $name : $iban; + $account = Account::firstOrCreateEncrypted( // TODO use repository [ 'user_id' => Auth::user()->id, 'account_type_id' => $accountType->id, 'name' => $name, - 'iban' => $this->data['asset-account-iban'], + 'iban' => $iban, 'active' => true, ] ); @@ -137,22 +179,22 @@ class AssetAccount implements PostProcessorInterface } /** - * @return array|null + * @return Account|null */ - protected function checkNameString() + protected function parseIbanString() { - if ($this->data['asset-account-name'] instanceof Account) { // third: try to find account based on name, if any. - $this->data['asset-account-object'] = $this->data['asset-account-name']; + // create by name and/or iban. + $iban = $this->data['asset-account-iban'] ?? ''; + $accounts = Auth::user()->accounts()->get(); + foreach ($accounts as $entry) { + if ($iban !== '' && $entry->iban === $iban) { - return $this->data; + return $entry; + } } - if (is_string($this->data['asset-account-name'])) { - $this->data['asset-account-object'] = $this->parseNameString(); + $account = $this->createAccount(); - return $this->data; - } - - return null; + return $account; } /** @@ -169,7 +211,7 @@ class AssetAccount implements PostProcessorInterface return $entry; } } - // create if not exists: + // create if not exists: // TODO use repository $account = Account::firstOrCreateEncrypted( [ 'user_id' => Auth::user()->id, @@ -182,4 +224,43 @@ class AssetAccount implements PostProcessorInterface return $account; } + + /** + * @return Account|null + */ + private function parseAccountNumberString() + { + $accountNumber = $this->data['asset-account-number'] ?? ''; + $accountType = $this->getAccountType(); + $accounts = Auth::user()->accounts()->with(['accountmeta'])->where('account_type_id', $accountType->id)->get(); + /** @var Account $entry */ + foreach ($accounts as $entry) { + $metaFieldValue = $entry->getMeta('accountNumber'); + if ($metaFieldValue === $accountNumber && $metaFieldValue !== '') { + Log::debug('Found an asset account with this account number (#' . $entry->id . ')'); + + return $entry; + } + } + // create new if not exists and return that one: + /** @var \FireflyIII\Repositories\Account\AccountRepositoryInterface $repository */ + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $accountData = [ + 'name' => $accountNumber, + 'accountType' => 'asset', + 'virtualBalance' => 0, + 'virtualBalanceCurrency' => 1, // TODO hard coded. + 'active' => true, + 'user' => Auth::user()->id, + 'iban' => null, + 'accountNumber' => $accountNumber, + 'accountRole' => null, + 'openingBalance' => 0, + 'openingBalanceDate' => new Carbon, + 'openingBalanceCurrency' => 1, // TODO hard coded. + ]; + $account = $repository->store($accountData); + + return $account; + } }