diff --git a/app/Console/Commands/Import.php b/app/Console/Commands/Import.php index 3d70737e7e..6109cab5e2 100644 --- a/app/Console/Commands/Import.php +++ b/app/Console/Commands/Import.php @@ -13,6 +13,7 @@ namespace FireflyIII\Console\Commands; use FireflyIII\Crud\Account\AccountCrud; use FireflyIII\Import\Importer\ImporterInterface; +use FireflyIII\Import\ImportResult; use FireflyIII\Import\ImportStorage; use FireflyIII\Import\ImportValidator; use FireflyIII\Import\Logging\CommandHandler; @@ -70,6 +71,8 @@ class Import extends Command return; } + $job->status = 'import_running'; + $job->save(); $this->line('Going to import job with key "' . $job->key . '" of type ' . $job->file_type); $valid = array_keys(config('firefly.import_formats')); @@ -105,9 +108,25 @@ class Import extends Command $storage->setUser($job->user); // and run store routine: - $storage->store(); + $result = $storage->store(); + + $job->status = 'import_complete'; + $job->save(); + + /** + * @var int $index + * @var ImportResult $entry + */ + foreach ($result as $index => $entry) { + if ($entry->isSuccess()) { + $this->line(sprintf('Line #%d has been imported as transaction #%d.', $index, $entry->journal->id)); + continue; + } + $errors = join(', ', $entry->errors->all()); + $this->error(sprintf('Could not store line #%d, because: %s', $index, $errors)); + } - $this->line('Something something import: ' . $jobKey); + $this->line('The import has completed.'); } } diff --git a/app/Import/Converter/AssetAccountNumber.php b/app/Import/Converter/AssetAccountNumber.php index cbad7b39a5..b19fce1433 100644 --- a/app/Import/Converter/AssetAccountNumber.php +++ b/app/Import/Converter/AssetAccountNumber.php @@ -80,7 +80,7 @@ class AssetAccountNumber extends BasicConverter implements ConverterInterface if (is_null($account->id)) { $this->setCertainty(0); - Log::notice('Could not store new asset account by account number', $account->getErrors()->toArray()); + Log::info('Could not store new asset account by account number', $account->getErrors()->toArray()); return new Account; } diff --git a/app/Import/Converter/Date.php b/app/Import/Converter/Date.php index e873f9c128..1ffe496b78 100644 --- a/app/Import/Converter/Date.php +++ b/app/Import/Converter/Date.php @@ -37,8 +37,8 @@ class Date extends BasicConverter implements ConverterInterface try { $date = Carbon::createFromFormat($this->config['date-format'], $value); } catch (InvalidArgumentException $e) { - Log::notice($e->getMessage()); - Log::notice('Cannot convert this string using the given format.', ['value' => $value, 'format' => $this->config['date-format']]); + Log::info($e->getMessage()); + Log::info('Cannot convert this string using the given format.', ['value' => $value, 'format' => $this->config['date-format']]); $this->setCertainty(0); return new Carbon; } diff --git a/app/Import/Converter/OpposingAccountIban.php b/app/Import/Converter/OpposingAccountIban.php index 4fc2a1cc9d..123dc0a9b3 100644 --- a/app/Import/Converter/OpposingAccountIban.php +++ b/app/Import/Converter/OpposingAccountIban.php @@ -56,7 +56,7 @@ class OpposingAccountIban extends BasicConverter implements ConverterInterface $account = $repository->findByIban($value, []); if (!is_null($account->id)) { Log::debug('Found account by IBAN', ['id' => $account->id]); - Log::notice( + Log::info( 'The match between IBAN and account is uncertain because the type of transactions may not have been determined.', ['id' => $account->id, 'iban' => $value] ); diff --git a/app/Import/ImportResult.php b/app/Import/ImportResult.php index afc68bee82..a65612d854 100644 --- a/app/Import/ImportResult.php +++ b/app/Import/ImportResult.php @@ -10,6 +10,8 @@ declare(strict_types = 1); namespace FireflyIII\Import; + +use FireflyIII\Models\TransactionJournal; use Illuminate\Support\Collection; /** @@ -25,6 +27,8 @@ class ImportResult /** @var Collection */ public $errors; + /** @var TransactionJournal */ + public $journal; /** @var Collection */ public $messages; /** @var int */ @@ -102,6 +106,14 @@ class ImportResult return $this; } + /** + * @return bool + */ + public function isSuccess(): bool + { + return $this->status === self::IMPORT_SUCCESS; + } + /** * @param Collection $errors */ @@ -110,6 +122,14 @@ class ImportResult $this->errors = $errors; } + /** + * @param TransactionJournal $journal + */ + public function setJournal(TransactionJournal $journal) + { + $this->journal = $journal; + } + /** * @param Collection $messages */ diff --git a/app/Import/ImportStorage.php b/app/Import/ImportStorage.php index e016e93d24..3f14f636e7 100644 --- a/app/Import/ImportStorage.php +++ b/app/Import/ImportStorage.php @@ -53,15 +53,20 @@ class ImportStorage } /** - * + * @return Collection */ - public function store() + public function store(): Collection { + $collection = new Collection; + Log::notice(sprintf('Started storing %d entry(ies).', $this->entries->count())); foreach ($this->entries as $index => $entry) { Log::debug(sprintf('--- import store start for row %d ---', $index)); - $this->storeSingle($index, $entry); + $result = $this->storeSingle($index, $entry); + $collection->put($index, $result); } + Log::notice(sprintf('Finished storing %d entry(ies).', $collection->count())); + return $collection; } /** @@ -200,10 +205,10 @@ class ImportStorage private function storeSingle(int $index, ImportEntry $entry): ImportResult { if ($entry->valid === false) { - Log::error(sprintf('Cannot import row %d, because valid=false', $index)); + Log::warning(sprintf('Cannot import row %d, because valid=false', $index)); $result = new ImportResult(); $result->failed(); - $result->appendError(sprintf('Cannot import row %d, because valid=false', $index)); + $result->appendError(sprintf('Cannot import row %d, because the current line is not valid.', $index)); return $result; } @@ -242,6 +247,13 @@ class ImportStorage $this->storeCategory($journal, $entry); $this->storeBill($journal, $entry); + $result = new ImportResult(); + $result->success(); + $result->appendMessage(sprintf('Journal titled "%s" imported.', $journal->description)); + $result->setJournal($journal); + + return $result; + } } diff --git a/app/Import/ImportValidator.php b/app/Import/ImportValidator.php index af55598b53..1f837118dd 100644 --- a/app/Import/ImportValidator.php +++ b/app/Import/ImportValidator.php @@ -50,6 +50,7 @@ class ImportValidator */ public function clean(): Collection { + Log::notice(sprintf('Started validating %d entry(ies).', $this->entries->count())); $newCollection = new Collection; /** @var ImportEntry $entry */ foreach ($this->entries as $index => $entry) { @@ -71,6 +72,7 @@ class ImportValidator $newCollection->put($index, $entry); } + Log::notice(sprintf('Finished validating %d entry(ies).', $newCollection->count())); return $newCollection; } @@ -100,7 +102,7 @@ class ImportValidator { if ($entry->fields['amount'] == 0) { $entry->valid = false; - Log::error('Amount of transaction is zero, cannot handle.'); + Log::warning('Amount of transaction is zero, cannot handle.'); return $entry; } @@ -229,7 +231,7 @@ class ImportValidator // default import is null? should not happen. Entry cannot be imported. // set error message and block. $entry->valid = false; - Log::error('Cannot import entry. Asset account is NULL and import account is also NULL.'); + Log::warning('Cannot import entry. Asset account is NULL and import account is also NULL.'); } Log::debug('Asset account is OK.', ['id' => $entry->fields['asset-account']->id, 'name' => $entry->fields['asset-account']->name]); @@ -379,7 +381,7 @@ class ImportValidator return $entry; } - Log::error(sprintf('Opposing account is of type %s, cannot handle this.', $type)); + Log::warning(sprintf('Opposing account is of type %s, cannot handle this.', $type)); $entry->valid = false; return $entry; diff --git a/app/Import/Importer/CsvImporter.php b/app/Import/Importer/CsvImporter.php index 3ce6694247..75f07b6b50 100644 --- a/app/Import/Importer/CsvImporter.php +++ b/app/Import/Importer/CsvImporter.php @@ -54,15 +54,20 @@ class CsvImporter implements ImporterInterface $reader->setDelimiter($config['delimiter']); $start = $config['has-headers'] ? 1 : 0; $results = $reader->fetch(); + + Log::notice('Building importable objects from CSV file.'); + foreach ($results as $index => $row) { if ($index >= $start) { + $line = $index + 1; Log::debug('----- import entry build start --'); Log::debug(sprintf('Now going to import row %d.', $index)); $importEntry = $this->importSingleRow($index, $row); - $this->collection->put($index, $importEntry); + $this->collection->put($line, $importEntry); } } Log::debug(sprintf('Import collection contains %d entries', $this->collection->count())); + Log::notice(sprintf('Built %d importable object(s) from your CSV file.', $this->collection->count())); return $this->collection; }