diff --git a/app/Http/Controllers/Import/ConfigurationController.php b/app/Http/Controllers/Import/ConfigurationController.php index 08798efaad..3ef3d16620 100644 --- a/app/Http/Controllers/Import/ConfigurationController.php +++ b/app/Http/Controllers/Import/ConfigurationController.php @@ -135,6 +135,7 @@ class ConfigurationController extends Controller if (null === $className || !class_exists($className)) { throw new FireflyException(sprintf('Cannot find configurator class for job of type "%s".', $type)); // @codeCoverageIgnore } + Log::debug(sprintf('Going to create class "%s"', $className)); /** @var ConfiguratorInterface $configurator */ $configurator = app($className); $configurator->setJob($job); diff --git a/app/Import/Configuration/FileConfigurator.php b/app/Import/Configuration/FileConfigurator.php index 8e120c4208..2b16f268f8 100644 --- a/app/Import/Configuration/FileConfigurator.php +++ b/app/Import/Configuration/FileConfigurator.php @@ -43,10 +43,11 @@ class FileConfigurator implements ConfiguratorInterface private $warning = ''; /** - * ConfiguratorInterface constructor. + * FileConfigurator constructor. */ public function __construct() { + Log::debug('Created FileConfigurator'); } /** @@ -140,8 +141,11 @@ class FileConfigurator implements ConfiguratorInterface && $config['column-mapping-complete'] && $config['has-file-upload'] ) { + Log::debug('isJobConfigured returns true'); + return true; } + Log::debug('isJobConfigured returns false'); return false; } @@ -152,11 +156,27 @@ class FileConfigurator implements ConfiguratorInterface public function setJob(ImportJob $job) { $this->job = $job; - if (null === $this->job->configuration || 0 === count($this->job->configuration)) { - Log::debug(sprintf('Gave import job %s initial configuration.', $this->job->key)); - $this->job->configuration = config('csv.default_config'); - $this->job->save(); - } + // give job default config: + $defaultConfig = [ + 'initial-config-complete' => false, + 'has-headers' => false, // assume + 'date-format' => 'Ymd', // assume + 'delimiter' => ',', // assume + 'import-account' => 0, // none, + 'specifics' => [], // none + 'column-count' => 0, // unknown + 'column-roles' => [], // unknown + 'column-do-mapping' => [], // not yet set which columns must be mapped + 'column-roles-complete' => false, // not yet configured roles for columns + 'column-mapping-config' => [], // no mapping made yet. + 'column-mapping-complete' => false, // so mapping is not complete. + 'apply-rules' => true, + 'match-bills' => false, + ]; + $config = $this->job->configuration ?? []; + $finalConfig = array_merge($defaultConfig, $config); + $this->job->configuration = $finalConfig; + $this->job->save(); } /** @@ -166,12 +186,15 @@ class FileConfigurator implements ConfiguratorInterface */ private function getConfigurationClass(): string { + $class = false; switch (true) { case !$this->job->configuration['has-file-upload']: $class = Upload::class; break; case !$this->job->configuration['initial-config-complete']: + Log::debug(sprintf('Class is %s', Initial::class)); + Log::debug(sprintf('initial-config-complete is %s', var_export($this->job->configuration['initial-config-complete'], true))); $class = Initial::class; break; case !$this->job->configuration['column-roles-complete']: @@ -190,6 +213,7 @@ class FileConfigurator implements ConfiguratorInterface if (!class_exists($class)) { throw new FireflyException(sprintf('Class %s does not exist in getConfigurationClass().', $class)); } + Log::debug(sprintf('Configuration class is "%s"', $class)); return $class; } diff --git a/app/Import/Configuration/SpectreConfigurator.php b/app/Import/Configuration/SpectreConfigurator.php index 36d93cdeca..69fb4b429c 100644 --- a/app/Import/Configuration/SpectreConfigurator.php +++ b/app/Import/Configuration/SpectreConfigurator.php @@ -66,6 +66,7 @@ class SpectreConfigurator implements ConfiguratorInterface // update config to tell Firefly the user is redirected. $config = $this->job->configuration; $config['is-redirected'] = true; + $config['stage'] = 'redirected'; $this->job->configuration = $config; $this->job->status = 'configured'; $this->job->save(); @@ -117,7 +118,7 @@ class SpectreConfigurator implements ConfiguratorInterface */ public function setJob(ImportJob $job) { - $defaultConfig = [ + $defaultConfig = [ 'has-token' => false, 'token' => '', 'token-expires' => 0, @@ -125,12 +126,17 @@ class SpectreConfigurator implements ConfiguratorInterface 'is-redirected' => false, 'customer' => null, 'login' => null, - + 'stage' => 'initial', + 'accounts' => [], ]; + $extendedStatus = $job->extended_status; + $extendedStatus['steps'] = 100; - $config = $job->configuration; - $finalConfig = array_merge($defaultConfig, $config); - $job->configuration = $finalConfig; + + $config = $job->configuration; + $finalConfig = array_merge($defaultConfig, $config); + $job->configuration = $finalConfig; + $job->extended_status = $extendedStatus; $job->save(); $this->job = $job; } diff --git a/app/Import/Routine/SpectreRoutine.php b/app/Import/Routine/SpectreRoutine.php index b1ee3b3673..7b9ba5425a 100644 --- a/app/Import/Routine/SpectreRoutine.php +++ b/app/Import/Routine/SpectreRoutine.php @@ -24,6 +24,7 @@ namespace FireflyIII\Import\Routine; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\ImportJob; +use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; use FireflyIII\Services\Spectre\Exception\DuplicatedCustomerException; use FireflyIII\Services\Spectre\Object\Customer; use FireflyIII\Services\Spectre\Object\Login; @@ -50,6 +51,9 @@ class SpectreRoutine implements RoutineInterface /** @var ImportJob */ private $job; + /** @var ImportJobRepositoryInterface */ + private $repository; + /** * ImportRoutine constructor. */ @@ -84,16 +88,33 @@ class SpectreRoutine implements RoutineInterface } /** + * A Spectre job that ends up here is either "configured" or "running", and will be set to "running" + * when it is "configured". + * + * Job has several stages, stored in extended status key 'stage' + * + * initial: just begun, nothing happened. action: get a customer and a token. Next status: has-token + * has-token: redirect user to sandstorm, make user login. set job to: user-logged-in + * user-logged-in: customer has an attempt. action: analyse/get attempt and go for next status. + * if attempt failed: job status is error, save a warning somewhere? + * if success, try to get accounts. Save in config key 'accounts'. set status: have-accounts and "configuring" + * + * If job is "configuring" and stage "have-accounts" then present the accounts and make user link them to + * own asset accounts. Store this mapping, set config to "have-account-mapping" and job status configured". + * + * have-account-mapping: start downloading transactions? + * * * @throws \FireflyIII\Exceptions\FireflyException * @throws \FireflyIII\Services\Spectre\Exception\SpectreException */ public function run(): bool { - if ('configured' !== $this->job->status) { - //Log::error(sprintf('Job %s is in state "%s" so it cannot be started.', $this->job->key, $this->job->status)); - //return false; + if ('configured' === $this->job->status) { + $this->repository->updateStatus($this->job,'running'); } + + Log::info(sprintf('Start with import job %s using Spectre.', $this->job->key)); set_time_limit(0); @@ -184,6 +205,8 @@ class SpectreRoutine implements RoutineInterface public function setJob(ImportJob $job) { $this->job = $job; + $this->repository = app(ImportJobRepositoryInterface::class); + $this->repository->setUser($job->user); } /** diff --git a/app/Import/Storage/ImportStorage.php b/app/Import/Storage/ImportStorage.php index f548ae0068..a9ff0341d0 100644 --- a/app/Import/Storage/ImportStorage.php +++ b/app/Import/Storage/ImportStorage.php @@ -94,8 +94,8 @@ class ImportStorage $this->defaultCurrencyId = $currency->id; $this->transfers = $this->getTransfers(); $config = $job->configuration; - $this->applyRules = $config['apply_rules'] ?? false; - $this->matchBills = $config['match_bills'] ?? false; + $this->applyRules = $config['apply-rules'] ?? false; + $this->matchBills = $config['match-bills'] ?? false; if (true === $this->applyRules) { Log::debug('applyRules seems to be true, get the rules.'); $this->rules = $this->getRules(); diff --git a/app/Repositories/ImportJob/ImportJobRepository.php b/app/Repositories/ImportJob/ImportJobRepository.php index 8925dbaaf3..90aebe515a 100644 --- a/app/Repositories/ImportJob/ImportJobRepository.php +++ b/app/Repositories/ImportJob/ImportJobRepository.php @@ -62,7 +62,7 @@ class ImportJobRepository implements ImportJobRepositoryInterface $importJob->file_type = $type; $importJob->key = Str::random(12); $importJob->status = 'new'; - $importJob->configuration = config(sprintf('import.default_config.%s', $type)) ?? []; + $importJob->configuration = []; $importJob->extended_status = [ 'steps' => 0, 'done' => 0, diff --git a/app/Support/Import/Configuration/File/Initial.php b/app/Support/Import/Configuration/File/Initial.php index 66baa95f26..d5db1a8992 100644 --- a/app/Support/Import/Configuration/File/Initial.php +++ b/app/Support/Import/Configuration/File/Initial.php @@ -111,23 +111,29 @@ class Initial implements ConfigurationInterface */ public function storeConfiguration(array $data): bool { + Log::debug('Now in Initial::storeConfiguration()'); + + // get config from job: + $config = $this->job->configuration; + + // find import account: /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class); - $importId = $data['csv_import_account'] ?? 0; - $account = $repository->find(intval($importId)); + $importId = intval($data['csv_import_account'] ?? 0); + $account = $repository->find($importId); - $hasHeaders = isset($data['has_headers']) && 1 === intval($data['has_headers']) ? true : false; - $config = $this->job->configuration; + // set "headers": $config['initial-config-complete'] = true; - $config['has-headers'] = $hasHeaders; + $config['has-headers'] = intval($data['has_headers'] ?? 0) === 1; $config['date-format'] = $data['date_format']; $config['delimiter'] = $data['csv_delimiter']; $config['delimiter'] = 'tab' === $config['delimiter'] ? "\t" : $config['delimiter']; - $config['apply_rules'] = isset($data['apply_rules']) && 1 === intval($data['apply_rules']) ? true : false; - $config['match_bills'] = isset($data['match_bills']) && 1 === intval($data['match_bills']) ? true : false; + $config['apply-rules'] = intval($data['apply_rules'] ?? 0) === 1; + $config['match-bills'] = intval($data['match_bills'] ?? 0) === 1; Log::debug('Entered import account.', ['id' => $importId]); + if (null !== $account->id) { Log::debug('Found account.', ['id' => $account->id, 'name' => $account->name]); $config['import-account'] = $account->id; @@ -137,7 +143,9 @@ class Initial implements ConfigurationInterface Log::error('Could not find anything for csv_import_account.', ['id' => $importId]); } - $config = $this->storeSpecifics($data, $config); + $config = $this->storeSpecifics($data, $config); + Log::debug('Final config is ', $config); + $this->job->configuration = $config; $this->job->save(); diff --git a/config/csv.php b/config/csv.php index adf39792c3..ed530932c7 100644 --- a/config/csv.php +++ b/config/csv.php @@ -320,18 +320,4 @@ return [ // number of example rows: 'example_rows' => 5, - 'default_config' => [ - 'initial-config-complete' => false, - 'has-headers' => false, // assume - 'date-format' => 'Ymd', // assume - 'delimiter' => ',', // assume - 'import-account' => 0, // none, - 'specifics' => [], // none - 'column-count' => 0, // unknown - 'column-roles' => [], // unknown - 'column-do-mapping' => [], // not yet set which columns must be mapped - 'column-roles-complete' => false, // not yet configured roles for columns - 'column-mapping-config' => [], // no mapping made yet. - 'column-mapping-complete' => false, // so mapping is not complete. - ], ];