diff --git a/app/Crud/Account/AccountCrud.php b/app/Crud/Account/AccountCrud.php index e9c4046b2f..11958fba4b 100644 --- a/app/Crud/Account/AccountCrud.php +++ b/app/Crud/Account/AccountCrud.php @@ -84,12 +84,20 @@ class AccountCrud implements AccountCrudInterface /** * @param string $iban + * @param array $types * * @return Account */ - public function findByIban(string $iban): Account + public function findByIban(string $iban, array $types): Account { - $accounts = $this->user->accounts()->where('iban', '!=', "")->get(); + $query = $this->user->accounts()->where('iban', '!=', ""); + + if (count($types) > 0) { + $query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); + $query->whereIn('account_types.type', $types); + } + + $accounts = $query->get(); /** @var Account $account */ foreach ($accounts as $account) { if ($account->iban === $iban) { @@ -100,6 +108,32 @@ class AccountCrud implements AccountCrudInterface return new Account; } + /** + * @param string $name + * @param array $types + * + * @return Account + */ + public function findByName(string $name, array $types): Account + { + $query = $this->user->accounts()->where('iban', '!=', ""); + + if (count($types) > 0) { + $query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); + $query->whereIn('account_types.type', $types); + } + + $accounts = $query->get(); + /** @var Account $account */ + foreach ($accounts as $account) { + if ($account->name === $name) { + return $account; + } + } + + return new Account; + } + /** * @param array $accountIds * diff --git a/app/Crud/Account/AccountCrudInterface.php b/app/Crud/Account/AccountCrudInterface.php index 8d3ac26634..1b11bdbbb0 100644 --- a/app/Crud/Account/AccountCrudInterface.php +++ b/app/Crud/Account/AccountCrudInterface.php @@ -39,10 +39,19 @@ interface AccountCrudInterface /** * @param string $iban + * @param array $types * * @return Account */ - public function findByIban(string $iban): Account; + public function findByIban(string $iban, array $types): Account; + + /** + * @param string $name + * @param array $types + * + * @return Account + */ + public function findByName(string $name, array $types): Account; /** * @param array $accountIds diff --git a/app/Import/Converter/Amount.php b/app/Import/Converter/Amount.php new file mode 100644 index 0000000000..274f9b5457 --- /dev/null +++ b/app/Import/Converter/Amount.php @@ -0,0 +1,63 @@ + 2 && $value{$decimalPosition} == '.') { + $decimal = '.'; + } + if ($len > 2 && $value{$decimalPosition} == ',') { + $decimal = ','; + } + + // if decimal is dot, replace all comma's and spaces with nothing. then parse as float (round to 4 pos) + if ($decimal === '.') { + $search = [',', ' ']; + $value = str_replace($search, '', $value); + } + if ($decimal === ',') { + $search = ['.', ' ']; + $value = str_replace($search, '', $value); + $value = str_replace(',', '.', $value); + } + if (is_null($decimal)) { + // replace all: + $search = ['.', ' ', ',']; + $value = str_replace($search, '', $value); + } + + + return round(floatval($value), 4); + + } +} \ No newline at end of file diff --git a/app/Import/Converter/AssetAccountIban.php b/app/Import/Converter/AssetAccountIban.php index f469a8ef92..e903312a63 100644 --- a/app/Import/Converter/AssetAccountIban.php +++ b/app/Import/Converter/AssetAccountIban.php @@ -13,6 +13,7 @@ namespace FireflyIII\Import\Converter; use FireflyIII\Crud\Account\AccountCrudInterface; use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; use Log; /** @@ -30,7 +31,12 @@ class AssetAccountIban extends BasicConverter implements ConverterInterface */ public function convert($value): Account { - Log::debug('Going to convert value ' . $value); + $value = trim($value); + Log::debug('Going to convert ', ['value' => $value]); + + if (strlen($value) === 0) { + return new Account; + } /** @var AccountCrudInterface $repository */ $repository = app(AccountCrudInterface::class, [$this->user]); @@ -47,7 +53,7 @@ class AssetAccountIban extends BasicConverter implements ConverterInterface } // not mapped? Still try to find it first: - $account = $repository->findByIban($value); + $account = $repository->findByIban($value, [AccountType::ASSET]); if (!is_null($account->id)) { Log::debug('Found account by IBAN', ['id' => $account->id]); diff --git a/app/Import/Converter/AssetAccountId.php b/app/Import/Converter/AssetAccountId.php new file mode 100644 index 0000000000..b335e8e621 --- /dev/null +++ b/app/Import/Converter/AssetAccountId.php @@ -0,0 +1,34 @@ +config = $config; + } + /** * @param mixed $doMap */ diff --git a/app/Import/Converter/ConverterInterface.php b/app/Import/Converter/ConverterInterface.php index c0d9b187fe..87e8fc5d62 100644 --- a/app/Import/Converter/ConverterInterface.php +++ b/app/Import/Converter/ConverterInterface.php @@ -10,6 +10,7 @@ declare(strict_types = 1); namespace FireflyIII\Import\Converter; + use FireflyIII\User; /** @@ -25,6 +26,11 @@ interface ConverterInterface */ public function convert($value); + /** + * @param array $config + */ + public function setConfig(array $config); + /** * @param bool $doMap */ diff --git a/app/Import/Converter/CurrencyCode.php b/app/Import/Converter/CurrencyCode.php new file mode 100644 index 0000000000..3ac41ce074 --- /dev/null +++ b/app/Import/Converter/CurrencyCode.php @@ -0,0 +1,65 @@ + $value]); + + /** @var CurrencyRepositoryInterface $repository */ + $repository = app(CurrencyRepositoryInterface::class); + + if (isset($this->mapping[$value])) { + Log::debug('Found currency in mapping. Should exist.', ['value' => $value, 'map' => $this->mapping[$value]]); + $currency = $repository->find(intval($this->mapping[$value])); + if (!is_null($currency->id)) { + Log::debug('Found currency by ID', ['id' => $currency->id]); + + return $currency; + } + } + + // not mapped? Still try to find it first: + $currency = $repository->findByCode($value); + if (!is_null($currency->id)) { + Log::debug('Found currency by code', ['id' => $currency->id]); + + return $currency; + } + $currency = $repository->store( + [ + 'name' => $value, + 'code' => $value, + 'symbol' => $value, + ] + ); + + return $currency; + } +} \ No newline at end of file diff --git a/app/Import/Converter/Date.php b/app/Import/Converter/Date.php new file mode 100644 index 0000000000..c9e9676b6f --- /dev/null +++ b/app/Import/Converter/Date.php @@ -0,0 +1,48 @@ + $value]); + Log::debug('Format: ', ['format' => $this->config['date-format']]); + try { + $date = Carbon::createFromFormat($this->config['date-format'], $value); + } catch (InvalidArgumentException $e) { + Log::critical($e->getMessage()); + Log::critical('Cannot convert this string using the given format.', ['value' => $value, 'format' => $this->config['date-format']]); + throw new FireflyException(sprintf('Cannot convert "%s" to a valid date using format "%s".', $value, $this->config['date-format'])); + } + Log::debug('Converted date', ['converted' => $date->toAtomString()]); + + return $date; + } +} \ No newline at end of file diff --git a/app/Import/Converter/Description.php b/app/Import/Converter/Description.php new file mode 100644 index 0000000000..18b90ee92e --- /dev/null +++ b/app/Import/Converter/Description.php @@ -0,0 +1,36 @@ + $value]); + + if (strlen($value) === 0) { + return new Account; + } + + /** @var AccountCrudInterface $repository */ + $repository = app(AccountCrudInterface::class, [$this->user]); + + + if (isset($this->mapping[$value])) { + Log::debug('Found account in mapping. Should exist.', ['value' => $value, 'map' => $this->mapping[$value]]); + $account = $repository->find(intval($this->mapping[$value])); + if (!is_null($account->id)) { + Log::debug('Found account by ID', ['id' => $account->id]); + + return $account; + } + } + + // not mapped? Still try to find it first: + $account = $repository->findByIban($value, []); + if (!is_null($account->id)) { + Log::debug('Found account by IBAN', ['id' => $account->id]); + Log::warning( + 'The match between IBAN and account is uncertain because the type of transactions may not have been determined.', + ['id' => $account->id, 'iban' => $value] + ); + + return $account; + } + + $account = $repository->store( + ['name' => $value, 'iban' => $value, 'user' => $this->user->id, 'accountType' => 'import', 'virtualBalance' => 0, 'active' => true, + 'openingBalance' => 0 $value]); + + if (strlen($value) === 0) { + $value = '(empty account name)'; + } + + /** @var AccountCrudInterface $repository */ + $repository = app(AccountCrudInterface::class, [$this->user]); + + + if (isset($this->mapping[$value])) { + Log::debug('Found account in mapping. Should exist.', ['value' => $value, 'map' => $this->mapping[$value]]); + $account = $repository->find(intval($this->mapping[$value])); + if (!is_null($account->id)) { + Log::debug('Found account by ID', ['id' => $account->id]); + + return $account; + } + } + + // not mapped? Still try to find it first: + $account = $repository->findByName($value, []); + if (!is_null($account->id)) { + Log::debug('Found account by name', ['id' => $account->id]); + Log::warning( + 'The match between name and account is uncertain because the type of transactions may not have been determined.', + ['id' => $account->id, 'name' => $value] + ); + + return $account; + } + + $account = $repository->store( + ['name' => $value, 'iban' => null, 'user' => $this->user->id, 'accountType' => 'import', 'virtualBalance' => 0, 'active' => true, + 'openingBalance' => 0, + ] + ); + + return $account; + } +} \ No newline at end of file diff --git a/app/Import/Converter/RabobankDebetCredit.php b/app/Import/Converter/RabobankDebetCredit.php new file mode 100644 index 0000000000..ca450b5b76 --- /dev/null +++ b/app/Import/Converter/RabobankDebetCredit.php @@ -0,0 +1,39 @@ + $value]); + + if ($value === 'D') { + return -1; + } + + return 1; + } +} \ No newline at end of file diff --git a/app/Import/Importer/CsvImporter.php b/app/Import/Importer/CsvImporter.php index ec60721ef8..beea9b5ad6 100644 --- a/app/Import/Importer/CsvImporter.php +++ b/app/Import/Importer/CsvImporter.php @@ -438,6 +438,7 @@ class CsvImporter implements ImporterInterface $converter->setMapping($mapping); $converter->setDoMap($doMap); $converter->setUser($this->job->user); + $converter->setConfig($config); // run the converter for this value: $convertedValue = $converter->convert($value); diff --git a/config/firefly.php b/config/firefly.php index f764212203..a053f95031 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -60,12 +60,15 @@ return [ 'Beneficiary account' => 'fa-shopping-cart', 'revenue' => 'fa-download', 'Revenue account' => 'fa-download', + 'import' => 'fa-download', + 'Import account' => 'fa-download', ], 'accountTypesByIdentifier' => [ 'asset' => ['Default account', 'Asset account'], 'expense' => ['Expense account', 'Beneficiary account'], 'revenue' => ['Revenue account'], + 'import' => ['Import account'], ], 'accountTypeByIdentifier' => [ @@ -74,11 +77,13 @@ return [ 'revenue' => 'Revenue account', 'opening' => 'Initial balance account', 'initial' => 'Initial balance account', + 'import' => 'Import account', ], 'shortNamesByFullName' => [ 'Default account' => 'asset', 'Asset account' => 'asset', + 'Import account' => 'import', 'Expense account' => 'expense', 'Beneficiary account' => 'expense', 'Revenue account' => 'revenue', @@ -136,7 +141,7 @@ return [ 'end_date' => 'FireflyIII\Support\Binder\Date', ], - 'rule-triggers' => [ + 'rule-triggers' => [ 'user_action' => 'FireflyIII\Rules\Triggers\UserAction', 'from_account_starts' => 'FireflyIII\Rules\Triggers\FromAccountStarts', 'from_account_ends' => 'FireflyIII\Rules\Triggers\FromAccountEnds', @@ -155,7 +160,7 @@ return [ 'description_contains' => 'FireflyIII\Rules\Triggers\DescriptionContains', 'description_is' => 'FireflyIII\Rules\Triggers\DescriptionIs', ], - 'rule-actions' => [ + 'rule-actions' => [ 'set_category' => 'FireflyIII\Rules\Actions\SetCategory', 'clear_category' => 'FireflyIII\Rules\Actions\ClearCategory', 'set_budget' => 'FireflyIII\Rules\Actions\SetBudget', @@ -168,7 +173,7 @@ return [ 'prepend_description' => 'FireflyIII\Rules\Actions\PrependDescription', ], // all rule actions that require text input: - 'rule-actions-text' => [ + 'rule-actions-text' => [ 'set_category', 'set_budget', 'add_tag', @@ -177,7 +182,7 @@ return [ 'append_description', 'prepend_description', ], - 'test-triggers' => [ + 'test-triggers' => [ // The maximum number of transactions shown when testing a list of triggers 'limit' => 10,