diff --git a/app/Http/Controllers/Import/BankController.php b/app/Http/Controllers/Import/BankController.php index 0bf671d4dc..125f8968d3 100644 --- a/app/Http/Controllers/Import/BankController.php +++ b/app/Http/Controllers/Import/BankController.php @@ -52,7 +52,7 @@ class BankController extends Controller } $importJob = $repository->create($bank); - return redirect(route('import.bank.configure', [$bank, $importJob->key])); + return redirect(route('import.file.configure', [$importJob->key])); } /** diff --git a/app/Import/Configurator/SpectreConfigurator.php b/app/Import/Configurator/SpectreConfigurator.php index 9a8d295101..da118f8363 100644 --- a/app/Import/Configurator/SpectreConfigurator.php +++ b/app/Import/Configurator/SpectreConfigurator.php @@ -25,7 +25,8 @@ namespace FireflyIII\Import\Configurator; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\ImportJob; use FireflyIII\Support\Import\Configuration\ConfigurationInterface; -use FireflyIII\Support\Import\Configuration\Spectre\SelectBank; +use FireflyIII\Support\Import\Configuration\Spectre\SelectProvider; +use FireflyIII\Support\Import\Configuration\Spectre\InputMandatory; use FireflyIII\Support\Import\Configuration\Spectre\SelectCountry; use Log; @@ -97,8 +98,11 @@ class SpectreConfigurator implements ConfiguratorInterface if (!$this->job->configuration['selected-country']) { return 'import.spectre.select-country'; } - if (!$this->job->configuration['selected-bank']) { - return 'import.spectre.select-bank'; + if (!$this->job->configuration['selected-provider']) { + return 'import.spectre.select-provider'; + } + if (!$this->job->configuration['has-input-mandatory']) { + return 'import.spectre.input-fields'; } throw new FireflyException('No view for state'); @@ -119,13 +123,14 @@ class SpectreConfigurator implements ConfiguratorInterface */ public function isJobConfigured(): bool { - $config = $this->job->configuration; - $config['selected-country'] = $config['selected-country'] ?? false; - $config['selected-bank'] = $config['selected-bank'] ?? false; - $this->job->configuration = $config; + $config = $this->job->configuration; + $config['selected-country'] = $config['selected-country'] ?? false; + $config['selected-provider'] = $config['selected-provider'] ?? false; + $config['has-input-mandatory'] = $config['has-input-mandatory'] ?? false; + $this->job->configuration = $config; $this->job->save(); - if ($config['selected-country'] && $config['selected-bank'] && false) { + if ($config['selected-country'] && $config['selected-provider'] && $config['has-input-mandatory'] && false) { return true; } @@ -159,9 +164,11 @@ class SpectreConfigurator implements ConfiguratorInterface case !$this->job->configuration['selected-country']: $class = SelectCountry::class; break; - case !$this->job->configuration['selected-bank']: - $class = SelectBank::class; + case !$this->job->configuration['selected-provider']: + $class = SelectProvider::class; break; + case !$this->job->configuration['has-input-mandatory']: + $class = InputMandatory::class; default: break; } diff --git a/app/Support/Import/Configuration/Spectre/InputMandatory.php b/app/Support/Import/Configuration/Spectre/InputMandatory.php new file mode 100644 index 0000000000..818f21878c --- /dev/null +++ b/app/Support/Import/Configuration/Spectre/InputMandatory.php @@ -0,0 +1,100 @@ +job->configuration; + $providerId = $config['provider']; + $provider = SpectreProvider::where('spectre_id', $providerId)->first(); + if (is_null($provider)) { + throw new FireflyException(sprintf('Cannot find Spectre provider with ID #%d', $providerId)); + } + $fields = $provider->data['required_fields'] ?? []; + $positions = []; + // Obtain a list of columns + foreach ($fields as $key => $row) { + $positions[$key] = $row['position']; + } + array_multisort($positions, SORT_ASC, $fields); + $country = SelectCountry::$allCountries[$config['country']] ?? $config['country']; + + return compact('provider', 'country', 'fields'); + } + + /** + * Return possible warning to user. + * + * @return string + */ + public function getWarningMessage(): string + { + return ''; + } + + /** + * @param ImportJob $job + * + * @return ConfigurationInterface + */ + public function setJob(ImportJob $job) + { + $this->job = $job; + } + + /** + * Store the result. + * + * @param array $data + * + * @return bool + */ + public function storeConfiguration(array $data): bool + { + $config = $this->job->configuration; + $providerId = $config['provider']; + $provider = SpectreProvider::where('spectre_id', $providerId)->first(); + if (is_null($provider)) { + throw new FireflyException(sprintf('Cannot find Spectre provider with ID #%d', $providerId)); + } + $mandatory = []; + $fields = $provider->data['required_fields'] ?? []; + foreach ($fields as $field) { + $name = $field['name']; + $mandatory[$name] = app('crypt')->encrypt($data[$name]) ?? null; + } + + // store in config of job: + $config['mandatory-fields'] = $mandatory; + $config['has-input-mandatory'] = true; + $this->job->configuration = $config; + $this->job->save(); + + // try to grab login for this job. See what happens? + // fire job that creates login object. user is redirected to "wait here" page (status page). Page should + // refresh and go back to interactive when user is supposed to enter SMS code or something. + // otherwise start downloading stuff + + return true; + } +} \ No newline at end of file diff --git a/app/Support/Import/Configuration/Spectre/SelectCountry.php b/app/Support/Import/Configuration/Spectre/SelectCountry.php index de49d9545d..e34c15b4e7 100644 --- a/app/Support/Import/Configuration/Spectre/SelectCountry.php +++ b/app/Support/Import/Configuration/Spectre/SelectCountry.php @@ -13,7 +13,7 @@ use FireflyIII\Support\Import\Configuration\ConfigurationInterface; */ class SelectCountry implements ConfigurationInterface { - private $allCountries + public static $allCountries = [ 'AF' => 'Afghanistan', 'AX' => 'Aland Islands', @@ -282,7 +282,7 @@ class SelectCountry implements ConfigurationInterface $countries = []; /** @var SpectreProvider $provider */ foreach ($providers as $provider) { - $countries[$provider->country_code] = $this->allCountries[$provider->country_code] ?? $provider->country_code; + $countries[$provider->country_code] = self::$allCountries[$provider->country_code] ?? $provider->country_code; } asort($countries); diff --git a/app/Support/Import/Configuration/Spectre/SelectBank.php b/app/Support/Import/Configuration/Spectre/SelectProvider.php similarity index 81% rename from app/Support/Import/Configuration/Spectre/SelectBank.php rename to app/Support/Import/Configuration/Spectre/SelectProvider.php index 1a9622f710..ec41ed78c5 100644 --- a/app/Support/Import/Configuration/Spectre/SelectBank.php +++ b/app/Support/Import/Configuration/Spectre/SelectProvider.php @@ -9,9 +9,9 @@ use FireflyIII\Models\SpectreProvider; use FireflyIII\Support\Import\Configuration\ConfigurationInterface; /** - * Class SelectBank + * Class SelectProvider */ -class SelectBank implements ConfigurationInterface +class SelectProvider implements ConfigurationInterface { /** @var ImportJob */ private $job; @@ -32,8 +32,9 @@ class SelectBank implements ConfigurationInterface $name = $provider->data['name']; $providers[$providerId] = $name; } + $country = SelectCountry::$allCountries[$config['country']] ?? $config['country']; - return compact('providers'); + return compact('providers', 'country'); } /** @@ -66,8 +67,8 @@ class SelectBank implements ConfigurationInterface public function storeConfiguration(array $data): bool { $config = $this->job->configuration; - $config['bank'] = intval($data['bank_code']) ?? 0; // default to fake country. - $config['selected-bank'] = true; + $config['provider'] = intval($data['provider_code']) ?? 0; // default to fake country. + $config['selected-provider'] = true; $this->job->configuration = $config; $this->job->save(); diff --git a/resources/lang/en_US/bank.php b/resources/lang/en_US/bank.php index 1c970e1e7e..34e8812920 100644 --- a/resources/lang/en_US/bank.php +++ b/resources/lang/en_US/bank.php @@ -3,14 +3,19 @@ declare(strict_types=1); return [ - 'bunq_prerequisites_title' => 'Prerequisites for an import from bunq', - 'bunq_prerequisites_text' => 'In order to import from bunq, you need to obtain an API key. You can do this through the app.', + 'bunq_prerequisites_title' => 'Prerequisites for an import from bunq', + 'bunq_prerequisites_text' => 'In order to import from bunq, you need to obtain an API key. You can do this through the app.', // Spectre: - 'spectre_title' => 'Import using Spectre', - 'spectre_prerequisites_title' => 'Prerequisites for an import using Spectre', - 'spectre_prerequisites_text' => 'In order to import data using the Spectre API, you need to prove some secrets. They can be found on the secrets page.', - 'spectre_enter_pub_key' => 'The import will only work when you enter this public key on your security page.', - 'spectre_select_country_title' => 'Select a country', - 'spectre_select_country_text' => 'Firefly III has a large selection of banks and sites from which Spectre can download transactional data. These banks are sorted by country. Please not that there is a "Fake Country" for when you wish to test something. If you wish to import from other financial tools, please use the imaginary country called "Other financial applications". By default, Spectre only allows you to download data from fake banks. Make sure your status is "Live" on your Dashboard if you wish to download from real banks.', + 'spectre_title' => 'Import using Spectre', + 'spectre_prerequisites_title' => 'Prerequisites for an import using Spectre', + 'spectre_prerequisites_text' => 'In order to import data using the Spectre API, you need to prove some secrets. They can be found on the secrets page.', + 'spectre_enter_pub_key' => 'The import will only work when you enter this public key on your security page.', + 'spectre_select_country_title' => 'Select a country', + 'spectre_select_country_text' => 'Firefly III has a large selection of banks and sites from which Spectre can download transactional data. These banks are sorted by country. Please not that there is a "Fake Country" for when you wish to test something. If you wish to import from other financial tools, please use the imaginary country called "Other financial applications". By default, Spectre only allows you to download data from fake banks. Make sure your status is "Live" on your Dashboard if you wish to download from real banks.', + 'spectre_select_provider_title' => 'Select a bank', + 'spectre_select_provider_text' => 'Spectre supports the following banks or financial services grouped under :country. Please pick the one you wish to import from.', + 'spectre_input_fields_title' => 'Input mandatory fields', + 'spectre_input_fields_text' => 'The following fields are mandated by ":provider" (from :country).', + 'spectre_instructions_english' => 'These instructions are provided by Spectre for your convencience. They are in English:', ]; diff --git a/resources/views/import/spectre/input-fields.twig b/resources/views/import/spectre/input-fields.twig new file mode 100644 index 0000000000..de77ba5b3f --- /dev/null +++ b/resources/views/import/spectre/input-fields.twig @@ -0,0 +1,65 @@ +{% extends "./layout/default" %} + +{% block breadcrumbs %} + {{ Breadcrumbs.renderIfExists }} +{% endblock %} +{% block content %} +
+
+ +
+
+
+

{{ trans('bank.spectre_input_fields_title') }}

+
+
+
+
+

+ {{ trans('bank.spectre_input_fields_text',{provider: data.provider.data.name, country: data.country})|raw }} +

+

+ {{ trans('bank.spectre_instructions_english') }} +

+

+ {{ data.provider.data.instruction|nl2br }} +

+
+
+ +
+
+ {% for field in data.fields %} + {# text, password, select, file #} + {% if field.nature == 'text' %} + {{ ExpandedForm.text(field.name,null, {label: field.english_name ~ ' ('~field.localized_name~')'}) }} + {% endif %} + {% if field.nature == 'password' %} + {{ ExpandedForm.password(field.name, {label: field.english_name ~ ' ('~field.localized_name~')'}) }} + {% endif %} + {% if field.nature == 'select' %} + DO NOT SUPPORT + {{ dump(field) }} + {% endif %} + {% if field.narture == 'file' %} + DO NOT SUPPORT + {{ dump(field) }} + {% endif %} + + {% endfor %} +
+
+ +
+
+ +
+{% endblock %} +{% block scripts %} +{% endblock %} +{% block styles %} +{% endblock %} diff --git a/resources/views/import/spectre/select-country.twig b/resources/views/import/spectre/select-country.twig index 5c4f36a199..ba4f4a0c59 100644 --- a/resources/views/import/spectre/select-country.twig +++ b/resources/views/import/spectre/select-country.twig @@ -16,7 +16,7 @@

- {{ trans('bank.spectre_select_country_text') }} + {{ trans('bank.spectre_select_country_text')|raw }}

diff --git a/resources/views/import/spectre/select-bank.twig b/resources/views/import/spectre/select-provider.twig similarity index 91% rename from resources/views/import/spectre/select-bank.twig rename to resources/views/import/spectre/select-provider.twig index af0a8d56f4..5be257d082 100644 --- a/resources/views/import/spectre/select-bank.twig +++ b/resources/views/import/spectre/select-provider.twig @@ -16,14 +16,14 @@

- {{ trans('bank.spectre_select_bank_title') }} + {{ trans('bank.spectre_select_provider_text',{country: data.country})|raw }}

- {{ ExpandedForm.select('bank_code', data.providers, null)|raw }} + {{ ExpandedForm.select('provider_code', data.providers, null)|raw }}