mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-24 22:48:18 +00:00
Expand import routine to work over command line.
This commit is contained in:
@@ -23,8 +23,10 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Console\Commands;
|
namespace FireflyIII\Console\Commands;
|
||||||
|
|
||||||
use Artisan;
|
use Artisan;
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Import\Logging\CommandHandler;
|
use FireflyIII\Import\Logging\CommandHandler;
|
||||||
use FireflyIII\Import\Routine\ImportRoutine;
|
use FireflyIII\Import\Routine\ImportRoutine;
|
||||||
|
use FireflyIII\Import\Routine\RoutineInterface;
|
||||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
@@ -54,7 +56,7 @@ class CreateImport extends Command
|
|||||||
protected $signature
|
protected $signature
|
||||||
= 'firefly:create-import
|
= 'firefly:create-import
|
||||||
{file : The file to import.}
|
{file : The file to import.}
|
||||||
{configuration : The configuration file to use for the import/}
|
{configuration : The configuration file to use for the import.}
|
||||||
{--type=csv : The file type of the import.}
|
{--type=csv : The file type of the import.}
|
||||||
{--user= : The user ID that the import should import for.}
|
{--user= : The user ID that the import should import for.}
|
||||||
{--token= : The user\'s access token.}
|
{--token= : The user\'s access token.}
|
||||||
@@ -73,6 +75,7 @@ class CreateImport extends Command
|
|||||||
*
|
*
|
||||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // cannot be helped
|
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // cannot be helped
|
||||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five exactly.
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five exactly.
|
||||||
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
@@ -93,7 +96,7 @@ class CreateImport extends Command
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$configurationData = json_decode(file_get_contents($configuration));
|
$configurationData = json_decode(file_get_contents($configuration), true);
|
||||||
if (null === $configurationData) {
|
if (null === $configurationData) {
|
||||||
$this->error(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
$this->error(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||||
|
|
||||||
@@ -114,9 +117,8 @@ class CreateImport extends Command
|
|||||||
Artisan::call('firefly:encrypt-file', ['file' => $file, 'key' => $job->key]);
|
Artisan::call('firefly:encrypt-file', ['file' => $file, 'key' => $job->key]);
|
||||||
$this->line('Stored import data...');
|
$this->line('Stored import data...');
|
||||||
|
|
||||||
$job->configuration = $configurationData;
|
$jobRepository->setConfiguration($job, $configurationData);
|
||||||
$job->status = 'configured';
|
$jobRepository->updateStatus($job, 'configured');
|
||||||
$job->save();
|
|
||||||
$this->line('Stored configuration...');
|
$this->line('Stored configuration...');
|
||||||
|
|
||||||
if (true === $this->option('start')) {
|
if (true === $this->option('start')) {
|
||||||
@@ -131,18 +133,24 @@ class CreateImport extends Command
|
|||||||
$monolog->pushHandler($handler);
|
$monolog->pushHandler($handler);
|
||||||
|
|
||||||
// start the actual routine:
|
// start the actual routine:
|
||||||
/** @var ImportRoutine $routine */
|
$type = $job->file_type === 'csv' ? 'file' : $job->file_type;
|
||||||
$routine = app(ImportRoutine::class);
|
$key = sprintf('import.routine.%s', $type);
|
||||||
|
$className = config($key);
|
||||||
|
if (null === $className || !class_exists($className)) {
|
||||||
|
throw new FireflyException(sprintf('Cannot find import routine class for job of type "%s".', $type)); // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
/** @var RoutineInterface $routine */
|
||||||
|
$routine = app($className);
|
||||||
$routine->setJob($job);
|
$routine->setJob($job);
|
||||||
$routine->run();
|
$routine->run();
|
||||||
|
|
||||||
// give feedback.
|
// give feedback.
|
||||||
/** @var MessageBag $error */
|
/** @var MessageBag $error */
|
||||||
foreach ($routine->errors as $index => $error) {
|
foreach ($routine->getErrors() as $index => $error) {
|
||||||
$this->error(sprintf('Error importing line #%d: %s', $index, $error));
|
$this->error(sprintf('Error importing line #%d: %s', $index, $error));
|
||||||
}
|
}
|
||||||
$this->line(
|
$this->line(
|
||||||
sprintf('The import has finished. %d transactions have been imported out of %d records.', $routine->journals->count(), $routine->lines)
|
sprintf('The import has finished. %d transactions have been imported out of %d records.', $routine->getJournals()->count(), $routine->lines)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +174,7 @@ class CreateImport extends Command
|
|||||||
$configuration = $this->argument('configuration');
|
$configuration = $this->argument('configuration');
|
||||||
$user = $userRepository->find(intval($this->option('user')));
|
$user = $userRepository->find(intval($this->option('user')));
|
||||||
$cwd = getcwd();
|
$cwd = getcwd();
|
||||||
$validTypes = array_keys(config('firefly.import_formats'));
|
$validTypes = config('import.options.file.import_formats');
|
||||||
$type = strtolower($this->option('type'));
|
$type = strtolower($this->option('type'));
|
||||||
if (null === $user->id) {
|
if (null === $user->id) {
|
||||||
$this->error(sprintf('There is no user with ID %d.', $this->option('user')));
|
$this->error(sprintf('There is no user with ID %d.', $this->option('user')));
|
||||||
|
@@ -68,6 +68,7 @@ trait VerifiesAccessToken
|
|||||||
}
|
}
|
||||||
if (!($accessToken->data === $token)) {
|
if (!($accessToken->data === $token)) {
|
||||||
Log::error(sprintf('Invalid access token for user #%d.', $userId));
|
Log::error(sprintf('Invalid access token for user #%d.', $userId));
|
||||||
|
Log::error(sprintf('Token given is "%s", expected "%s".', $token, $accessToken->data));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -55,6 +55,30 @@ class FileRoutine implements RoutineInterface
|
|||||||
$this->errors = new Collection;
|
$this->errors = new Collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getErrors(): Collection
|
||||||
|
{
|
||||||
|
return $this->errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getJournals(): Collection
|
||||||
|
{
|
||||||
|
return $this->journals;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getLines(): int
|
||||||
|
{
|
||||||
|
return $this->lines;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -111,7 +135,7 @@ class FileRoutine implements RoutineInterface
|
|||||||
{
|
{
|
||||||
$objects = new Collection;
|
$objects = new Collection;
|
||||||
$config = $this->job->configuration;
|
$config = $this->job->configuration;
|
||||||
$fileType = $config['file-type'];
|
$fileType = $config['file-type'] ?? 'csv';
|
||||||
// will only respond to "file"
|
// will only respond to "file"
|
||||||
$class = config(sprintf('import.options.file.processors.%s', $fileType));
|
$class = config(sprintf('import.options.file.processors.%s', $fileType));
|
||||||
/** @var FileProcessorInterface $processor */
|
/** @var FileProcessorInterface $processor */
|
||||||
|
@@ -22,18 +22,26 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Import\Routine;
|
namespace FireflyIII\Import\Routine;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use DB;
|
|
||||||
use FireflyIII\Import\FileProcessor\FileProcessorInterface;
|
|
||||||
use FireflyIII\Import\Storage\ImportStorage;
|
|
||||||
use FireflyIII\Models\ImportJob;
|
use FireflyIII\Models\ImportJob;
|
||||||
use FireflyIII\Models\Tag;
|
|
||||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Log;
|
|
||||||
|
|
||||||
interface RoutineInterface
|
interface RoutineInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getErrors(): Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getJournals(): Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getLines(): int;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
@@ -45,4 +53,6 @@ interface RoutineInterface
|
|||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function setJob(ImportJob $job);
|
public function setJob(ImportJob $job);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -3,20 +3,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
||||||
// general strings for file upload
|
|
||||||
// 'import_index_intro' => 'This routine will help you import files from your bank into Firefly III. Please check out the help pages in the top right corner.',
|
|
||||||
// 'import_index_file' => 'Select your file',
|
|
||||||
// 'import_index_config' => 'If you have previously imported data into Firefly III, you may have a configuration file, which will pre-set configuration values for you. For some banks, other users have kindly provided their <a href="https://github.com/firefly-iii/import-configurations/wiki">configuration file</a>.',
|
|
||||||
//
|
|
||||||
// 'import_index_start' => 'Start importing',
|
|
||||||
// 'import_file' => 'Import a file',
|
|
||||||
//
|
|
||||||
// // supported file types:
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // import configuration routine:
|
|
||||||
|
|
||||||
// status of import:
|
// status of import:
|
||||||
'status_wait_title' => 'Please hold...',
|
'status_wait_title' => 'Please hold...',
|
||||||
'status_wait_text' => 'This box will disappear in a moment.',
|
'status_wait_text' => 'This box will disappear in a moment.',
|
||||||
|
Reference in New Issue
Block a user