Fake jobs can be configured and can reach the landing stage.

This commit is contained in:
James Cole 2018-04-29 20:01:03 +02:00
parent fa41d6df04
commit f027d71136
No known key found for this signature in database
GPG Key ID: C16961E655E74B5E
13 changed files with 1464 additions and 1180 deletions

View File

@ -87,6 +87,8 @@ class IndexController extends Controller
// redirect to global prerequisites // redirect to global prerequisites
return redirect(route('import.prerequisites.index', [$importProvider, $importJob->key])); return redirect(route('import.prerequisites.index', [$importProvider, $importJob->key]));
} }
// update job to say "has_prereq".
$this->repository->setStatus($importJob, 'has_prereq');
// Otherwise just redirect to job configuration. // Otherwise just redirect to job configuration.
return redirect(route('import.job.configuration.index', [$importJob->key])); return redirect(route('import.job.configuration.index', [$importJob->key]));

View File

@ -25,7 +25,7 @@ namespace FireflyIII\Http\Controllers\Import;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Middleware\IsDemoUser; use FireflyIII\Http\Middleware\IsDemoUser;
use FireflyIII\Import\Configuration\ConfiguratorInterface; use FireflyIII\Import\JobConfiguration\JobConfiguratorInterface;
use FireflyIII\Models\ImportJob; use FireflyIII\Models\ImportJob;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@ -73,10 +73,10 @@ class JobConfigurationController extends Controller
$configurator = $this->makeConfigurator($job); $configurator = $this->makeConfigurator($job);
// is the job already configured? // is the job already configured?
if ($configurator->isJobConfigured()) { if ($configurator->configurationComplete()) {
$this->repository->updateStatus($job, 'configured'); $this->repository->updateStatus($job, 'ready_to_run');
return redirect(route('import.status', [$job->key])); return redirect(route('import.job.landing', [$job->key]));
} }
$this->repository->updateStatus($job, 'configuring'); $this->repository->updateStatus($job, 'configuring');
@ -105,40 +105,39 @@ class JobConfigurationController extends Controller
$configurator = $this->makeConfigurator($job); $configurator = $this->makeConfigurator($job);
// is the job already configured? // is the job already configured?
if ($configurator->isJobConfigured()) { if ($configurator->configurationComplete()) {
return redirect(route('import.status', [$job->key])); $this->repository->updateStatus($job, 'ready_to_run');
return redirect(route('import.job.landing', [$job->key]));
} }
$data = $request->all();
$configurator->configureJob($data);
// get possible warning from configurator: $data = $request->all();
$warning = $configurator->getWarningMessage(); $messages = $configurator->configureJob($data);
if (\strlen($warning) > 0) { if ($messages->count() > 0) {
$request->session()->flash('warning', $warning); $request->session()->flash('warning', $messages->first());
} }
// return to configure // return to configure
return redirect(route('import.configure', [$job->key])); return redirect(route('import.job.configuration.index', [$job->key]));
} }
/** /**
* @param ImportJob $job * @param ImportJob $job
* *
* @return ConfiguratorInterface * @return JobConfiguratorInterface
* *
* @throws FireflyException * @throws FireflyException
*/ */
private function makeConfigurator(ImportJob $job): ConfiguratorInterface private function makeConfigurator(ImportJob $job): JobConfiguratorInterface
{ {
$type = $job->file_type; $key = sprintf('import.configuration.%s', $job->provider);
$key = sprintf('import.configuration.%s', $type); $className = (string)config($key);
$className = config($key);
if (null === $className || !class_exists($className)) { if (null === $className || !class_exists($className)) {
throw new FireflyException(sprintf('Cannot find configurator class for job of type "%s".', $type)); // @codeCoverageIgnore throw new FireflyException(sprintf('Cannot find configurator class for job with provider "%s".', $job->provider)); // @codeCoverageIgnore
} }
Log::debug(sprintf('Going to create class "%s"', $className)); Log::debug(sprintf('Going to create class "%s"', $className));
/** @var ConfiguratorInterface $configurator */ /** @var JobConfiguratorInterface $configurator */
$configurator = app($className); $configurator = app($className);
$configurator->setJob($job); $configurator->setJob($job);

View File

@ -145,6 +145,9 @@ class PrerequisitesController extends Controller
return redirect(route('import.index')); return redirect(route('import.index'));
} }
// update job:
$this->repository->setStatus($importJob, 'has_prereq');
// redirect to job config: // redirect to job config:
return redirect(route('import.job.configuration.index', [$importJob->key])); return redirect(route('import.job.configuration.index', [$importJob->key]));

View File

@ -0,0 +1,133 @@
<?php
/**
* FakeJobConfiguration.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Import\JobConfiguration;
use FireflyIII\Models\ImportJob;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
use Illuminate\Support\MessageBag;
/**
* Class FakeJobConfiguration
*/
class FakeJobConfiguration implements JobConfiguratorInterface
{
/** @var ImportJob */
private $job;
/** @var ImportJobRepositoryInterface */
private $repository;
/**
* ConfiguratorInterface constructor.
*/
public function __construct()
{
$this->repository = app(ImportJobRepositoryInterface::class);
}
/**
* Returns true when the initial configuration for this job is complete.
*
* @return bool
*/
public function configurationComplete(): bool
{
// configuration array of job must have two values:
// 'artist' must be 'david bowie', case insensitive
// 'song' must be 'golden years', case insensitive.
$config = $this->job->configuration;
return (isset($config['artist']) && 'david bowie' === strtolower($config['artist']))
&& (isset($config['song']) && 'golden years' === strtolower($config['song']));
}
/**
* Store any data from the $data array into the job.
*
* @param array $data
*
* @return MessageBag
*/
public function configureJob(array $data): MessageBag
{
$artist = strtolower($data['artist'] ?? '');
$configuration = $this->job->configuration;
if ($artist === 'david bowie') {
// store artist
$configuration['artist'] = $artist;
}
$song = strtolower($data['song'] ?? '');
if ($song === 'golden years') {
// store artist
$configuration['song'] = $song;
}
$this->repository->setConfiguration($this->job, $configuration);
$messages = new MessageBag();
if (\count($configuration) !== 2) {
$messages->add('some_key', 'Ignore this error');
}
return $messages;
}
/**
* Return the data required for the next step in the job configuration.
*
* @return array
*/
public function getNextData(): array
{
return [];
}
/**
* Returns the view of the next step in the job configuration.
*
* @return string
*/
public function getNextView(): string
{
// first configure artist:
$config = $this->job->configuration;
$artist = $config['artist'] ?? '';
$song = $config['song'] ?? '';
if (strtolower($artist) !== 'david bowie') {
return 'import.fake.enter-artist';
}
if (strtolower($song) !== 'golden years') {
return 'import.fake.enter-song';
}
}
/**
* @param ImportJob $job
*/
public function setJob(ImportJob $job): void
{
$this->job = $job;
$this->repository->setUser($job->user);
}
}

View File

@ -0,0 +1,73 @@
<?php
/**
* JobConfiguratorInterface.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Import\JobConfiguration;
use FireflyIII\Models\ImportJob;
use Illuminate\Support\MessageBag;
/**
* Interface JobConfiguratorInterface.
*/
interface JobConfiguratorInterface
{
/**
* ConfiguratorInterface constructor.
*/
public function __construct();
/**
* Store any data from the $data array into the job. Anything in the message bag will be flashed
* as an error to the user, regardless of its content.
*
* @param array $data
*
* @return MessageBag
*/
public function configureJob(array $data): MessageBag;
/**
* Return the data required for the next step in the job configuration.
*
* @return array
*/
public function getNextData(): array;
/**
* Returns the view of the next step in the job configuration.
*
* @return string
*/
public function getNextView(): string;
/**
* Returns true when the initial configuration for this job is complete.
*
* @return bool
*/
public function configurationComplete(): bool;
/**
* @param ImportJob $job
*/
public function setJob(ImportJob $job): void;
}

View File

@ -22,12 +22,9 @@ declare(strict_types=1);
namespace FireflyIII\Models; namespace FireflyIII\Models;
use Crypt;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Log;
use Storage;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/** /**
@ -37,13 +34,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
*/ */
class ImportJob extends Model class ImportJob extends Model
{ {
/**
* @var array
*/
public $validStatus
= [
'new',
];
/** /**
* The attributes that should be casted to native types. * The attributes that should be casted to native types.
* *
@ -58,7 +49,7 @@ class ImportJob extends Model
'transactions' => 'array', 'transactions' => 'array',
]; ];
/** @var array */ /** @var array */
protected $fillable = ['key', 'user_id', 'file_type', 'source', 'status', 'stage', 'configuration', 'extended_status', 'transactions']; protected $fillable = ['key', 'user_id', 'file_type', 'provider', 'status', 'stage', 'configuration', 'extended_status', 'transactions'];
/** /**
* @param $value * @param $value
@ -74,49 +65,12 @@ class ImportJob extends Model
$key = trim($value); $key = trim($value);
$importJob = auth()->user()->importJobs()->where('key', $key)->first(); $importJob = auth()->user()->importJobs()->where('key', $key)->first();
if (null !== $importJob) { if (null !== $importJob) {
// must have valid status:
if (!\in_array($importJob->status, $importJob->validStatus)) {
throw new FireflyException(sprintf('ImportJob with key "%s" has invalid status "%s"', $importJob->key, $importJob->status));
}
return $importJob; return $importJob;
} }
} }
throw new NotFoundHttpException; throw new NotFoundHttpException;
} }
/**
* @deprecated
*
* @param int $count
*/
public function addTotalSteps(int $count): void
{
$status = $this->extended_status;
$status['steps'] += $count;
$this->extended_status = $status;
$this->save();
Log::debug(sprintf('Add %d to total steps for job "%s" making total steps %d', $count, $this->key, $status['steps']));
}
/**
* @return string
* @deprecated
* @throws \Illuminate\Contracts\Encryption\DecryptException
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function uploadFileContents(): string
{
$fileName = $this->key . '.upload';
$disk = Storage::disk('upload');
$encryptedContent = $disk->get($fileName);
$content = Crypt::decrypt($encryptedContent);
$content = trim($content);
Log::debug(sprintf('Content size is %d bytes.', \strlen($content)));
return $content;
}
/** /**
* @codeCoverageIgnore * @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo * @return \Illuminate\Database\Eloquent\Relations\BelongsTo

View File

@ -116,7 +116,7 @@ class ImportJobRepository implements ImportJobRepositoryInterface
*/ */
public function create(string $importProvider): ImportJob public function create(string $importProvider): ImportJob
{ {
$count = 0; $count = 0;
$importProvider = strtolower($importProvider); $importProvider = strtolower($importProvider);
while ($count < 30) { while ($count < 30) {
@ -126,7 +126,7 @@ class ImportJobRepository implements ImportJobRepositoryInterface
$importJob = ImportJob::create( $importJob = ImportJob::create(
[ [
'user_id' => $this->user->id, 'user_id' => $this->user->id,
'source' => $importProvider, 'provider' => $importProvider,
'file_type' => '', 'file_type' => '',
'key' => Str::random(12), 'key' => Str::random(12),
'status' => 'new', 'status' => 'new',

View File

@ -5,6 +5,7 @@ use FireflyIII\Import\Configuration\BunqConfigurator;
use FireflyIII\Import\Configuration\FileConfigurator; use FireflyIII\Import\Configuration\FileConfigurator;
use FireflyIII\Import\Configuration\SpectreConfigurator; use FireflyIII\Import\Configuration\SpectreConfigurator;
use FireflyIII\Import\FileProcessor\CsvProcessor; use FireflyIII\Import\FileProcessor\CsvProcessor;
use FireflyIII\Import\JobConfiguration\FakeJobConfiguration;
use FireflyIII\Import\Prerequisites\BunqPrerequisites; use FireflyIII\Import\Prerequisites\BunqPrerequisites;
use FireflyIII\Import\Prerequisites\FakePrerequisites; use FireflyIII\Import\Prerequisites\FakePrerequisites;
use FireflyIII\Import\Prerequisites\FilePrerequisites; use FireflyIII\Import\Prerequisites\FilePrerequisites;
@ -72,6 +73,7 @@ return [
'yodlee' => true, 'yodlee' => true,
], ],
'configuration' => [ 'configuration' => [
'fake' => FakeJobConfiguration::class,
'file' => FileConfigurator::class, 'file' => FileConfigurator::class,
'bunq' => BunqConfigurator::class, 'bunq' => BunqConfigurator::class,
'spectre' => SpectreConfigurator::class, 'spectre' => SpectreConfigurator::class,

View File

@ -23,201 +23,204 @@ declare(strict_types=1);
return [ return [
// 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.',
'status_fatal_title' => 'A fatal error occurred', 'status_fatal_title' => 'A fatal error occurred',
'status_fatal_text' => 'A fatal error occurred, which the import-routine cannot recover from. Please see the explanation in red below.', 'status_fatal_text' => 'A fatal error occurred, which the import-routine cannot recover from. Please see the explanation in red below.',
'status_fatal_more' => 'If the error is a time-out, the import will have stopped half-way. For some server configurations, it is merely the server that stopped while the import keeps running in the background. To verify this, check out the log files. If the problem persists, consider importing over the command line instead.', 'status_fatal_more' => 'If the error is a time-out, the import will have stopped half-way. For some server configurations, it is merely the server that stopped while the import keeps running in the background. To verify this, check out the log files. If the problem persists, consider importing over the command line instead.',
'status_ready_title' => 'Import is ready to start', 'status_ready_title' => 'Import is ready to start',
'status_ready_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.', 'status_ready_text' => 'The import is ready to start. All the configuration you needed to do has been done. Please download the configuration file. It will help you with the import should it not go as planned. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.',
'status_ready_noconfig_text' => 'The import is ready to start. All the configuration you needed to do has been done. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.', 'status_ready_noconfig_text' => 'The import is ready to start. All the configuration you needed to do has been done. To actually run the import, you can either execute the following command in your console, or run the web-based import. Depending on your configuration, the console import will give you more feedback.',
'status_ready_config' => 'Download configuration', 'status_ready_config' => 'Download configuration',
'status_ready_start' => 'Start the import', 'status_ready_start' => 'Start the import',
'status_ready_share' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.', 'status_ready_share' => 'Please consider downloading your configuration and sharing it at the <strong><a href="https://github.com/firefly-iii/import-configurations/wiki">import configuration center</a></strong>. This will allow other users of Firefly III to import their files more easily.',
'status_job_new' => 'The job is brand new.', 'status_job_new' => 'The job is brand new.',
'status_job_configuring' => 'The import is being configured.', 'status_job_configuring' => 'The import is being configured.',
'status_job_configured' => 'The import is configured.', 'status_job_configured' => 'The import is configured.',
'status_job_running' => 'The import is running.. Please wait..', 'status_job_running' => 'The import is running.. Please wait..',
'status_job_error' => 'The job has generated an error.', 'status_job_error' => 'The job has generated an error.',
'status_job_finished' => 'The import has finished!', 'status_job_finished' => 'The import has finished!',
'status_running_title' => 'The import is running', 'status_running_title' => 'The import is running',
'status_running_placeholder' => 'Please hold for an update...', 'status_running_placeholder' => 'Please hold for an update...',
'status_finished_title' => 'Import routine finished', 'status_finished_title' => 'Import routine finished',
'status_finished_text' => 'The import routine has imported your data.', 'status_finished_text' => 'The import routine has imported your data.',
'status_errors_title' => 'Errors during the import', 'status_errors_title' => 'Errors during the import',
'status_errors_single' => 'An error has occurred during the import. It does not appear to be fatal.', 'status_errors_single' => 'An error has occurred during the import. It does not appear to be fatal.',
'status_errors_multi' => 'Some errors occurred during the import. These do not appear to be fatal.', 'status_errors_multi' => 'Some errors occurred during the import. These do not appear to be fatal.',
'status_bread_crumb' => 'Import status', 'status_bread_crumb' => 'Import status',
'status_sub_title' => 'Import status', 'status_sub_title' => 'Import status',
'config_sub_title' => 'Set up your import', 'config_sub_title' => 'Set up your import',
'status_finished_job' => 'The :count transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.', 'status_finished_job' => 'The :count transactions imported can be found in tag <a href=":link" class="label label-success" style="font-size:100%;font-weight:normal;">:tag</a>.',
'status_finished_no_tag' => 'Firefly III has not collected any transactions from your import file.', 'status_finished_no_tag' => 'Firefly III has not collected any transactions from your import file.',
'import_with_key' => 'Import with key \':key\'', 'import_with_key' => 'Import with key \':key\'',
// file, upload something // file, upload something
'file_upload_title' => 'Import setup (1/4) - Upload your file', 'file_upload_title' => 'Import setup (1/4) - Upload your file',
'file_upload_text' => 'This routine will help you import files from your bank into Firefly III. Please check out the help pages in the top right corner.', 'file_upload_text' => 'This routine will help you import files from your bank into Firefly III. Please check out the help pages in the top right corner.',
'file_upload_fields' => 'Fields', 'file_upload_fields' => 'Fields',
'file_upload_help' => 'Select your file', 'file_upload_help' => 'Select your file',
'file_upload_config_help' => '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>', 'file_upload_config_help' => '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>',
'file_upload_type_help' => 'Select the type of file you will upload', 'file_upload_type_help' => 'Select the type of file you will upload',
'file_upload_submit' => 'Upload files', 'file_upload_submit' => 'Upload files',
// file, upload types // file, upload types
'import_file_type_csv' => 'CSV (comma separated values)', 'import_file_type_csv' => 'CSV (comma separated values)',
// file, initial config for CSV // file, initial config for CSV
'csv_initial_title' => 'Import setup (2/4) - Basic CSV import setup', 'csv_initial_title' => 'Import setup (2/4) - Basic CSV import setup',
'csv_initial_text' => 'To be able to import your file correctly, please validate the options below.', 'csv_initial_text' => 'To be able to import your file correctly, please validate the options below.',
'csv_initial_box' => 'Basic CSV import setup', 'csv_initial_box' => 'Basic CSV import setup',
'csv_initial_box_title' => 'Basic CSV import setup options', 'csv_initial_box_title' => 'Basic CSV import setup options',
'csv_initial_header_help' => 'Check this box if the first row of your CSV file are the column titles.', 'csv_initial_header_help' => 'Check this box if the first row of your CSV file are the column titles.',
'csv_initial_date_help' => 'Date time format in your CSV. Follow the format like <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">this page</a> indicates. The default value will parse dates that look like this: :dateExample.', 'csv_initial_date_help' => 'Date time format in your CSV. Follow the format like <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">this page</a> indicates. The default value will parse dates that look like this: :dateExample.',
'csv_initial_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.', 'csv_initial_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
'csv_initial_import_account_help' => 'If your CSV file does NOT contain information about your asset account(s), use this dropdown to select to which account the transactions in the CSV belong to.', 'csv_initial_import_account_help' => 'If your CSV file does NOT contain information about your asset account(s), use this dropdown to select to which account the transactions in the CSV belong to.',
'csv_initial_submit' => 'Continue with step 3/4', 'csv_initial_submit' => 'Continue with step 3/4',
// file, new options: // file, new options:
'file_apply_rules_title' => 'Apply rules', 'file_apply_rules_title' => 'Apply rules',
'file_apply_rules_description' => 'Apply your rules. Note that this slows the import significantly.', 'file_apply_rules_description' => 'Apply your rules. Note that this slows the import significantly.',
'file_match_bills_title' => 'Match bills', 'file_match_bills_title' => 'Match bills',
'file_match_bills_description' => 'Match your bills to newly created withdrawals. Note that this slows the import significantly.', 'file_match_bills_description' => 'Match your bills to newly created withdrawals. Note that this slows the import significantly.',
// file, roles config // file, roles config
'csv_roles_title' => 'Import setup (3/4) - Define each column\'s role', 'csv_roles_title' => 'Import setup (3/4) - Define each column\'s role',
'csv_roles_text' => 'Each column in your CSV file contains certain data. Please indicate what kind of data the importer should expect. The option to "map" data means that you will link each entry found in the column to a value in your database. An often mapped column is the column that contains the IBAN of the opposing account. That can be easily matched to IBAN\'s present in your database already.', 'csv_roles_text' => 'Each column in your CSV file contains certain data. Please indicate what kind of data the importer should expect. The option to "map" data means that you will link each entry found in the column to a value in your database. An often mapped column is the column that contains the IBAN of the opposing account. That can be easily matched to IBAN\'s present in your database already.',
'csv_roles_table' => 'Table', 'csv_roles_table' => 'Table',
'csv_roles_column_name' => 'Name of column', 'csv_roles_column_name' => 'Name of column',
'csv_roles_column_example' => 'Column example data', 'csv_roles_column_example' => 'Column example data',
'csv_roles_column_role' => 'Column data meaning', 'csv_roles_column_role' => 'Column data meaning',
'csv_roles_do_map_value' => 'Map these values', 'csv_roles_do_map_value' => 'Map these values',
'csv_roles_column' => 'Column', 'csv_roles_column' => 'Column',
'csv_roles_no_example_data' => 'No example data available', 'csv_roles_no_example_data' => 'No example data available',
'csv_roles_submit' => 'Continue with step 4/4', 'csv_roles_submit' => 'Continue with step 4/4',
// not csv, but normal warning // not csv, but normal warning
'roles_warning' => 'At the very least, mark one column as the amount-column. It is advisable to also select a column for the description, date and the opposing account.', 'roles_warning' => 'At the very least, mark one column as the amount-column. It is advisable to also select a column for the description, date and the opposing account.',
'foreign_amount_warning' => 'If you mark a column as containing an amount in a foreign currency, you must also set the column that contains which currency it is.', 'foreign_amount_warning' => 'If you mark a column as containing an amount in a foreign currency, you must also set the column that contains which currency it is.',
// file, map data // file, map data
'file_map_title' => 'Import setup (4/4) - Connect import data to Firefly III data', 'file_map_title' => 'Import setup (4/4) - Connect import data to Firefly III data',
'file_map_text' => 'In the following tables, the left value shows you information found in your uploaded file. It is your task to map this value, if possible, to a value already present in your database. Firefly will stick to this mapping. If there is no value to map to, or you do not wish to map the specific value, select nothing.', 'file_map_text' => 'In the following tables, the left value shows you information found in your uploaded file. It is your task to map this value, if possible, to a value already present in your database. Firefly will stick to this mapping. If there is no value to map to, or you do not wish to map the specific value, select nothing.',
'file_map_field_value' => 'Field value', 'file_map_field_value' => 'Field value',
'file_map_field_mapped_to' => 'Mapped to', 'file_map_field_mapped_to' => 'Mapped to',
'map_do_not_map' => '(do not map)', 'map_do_not_map' => '(do not map)',
'file_map_submit' => 'Start the import', 'file_map_submit' => 'Start the import',
'file_nothing_to_map' => 'There is no data present in your file that you can map to existing values. Please press "Start the import" to continue.', 'file_nothing_to_map' => 'There is no data present in your file that you can map to existing values. Please press "Start the import" to continue.',
// map things. // map things.
'column__ignore' => '(ignore this column)', 'column__ignore' => '(ignore this column)',
'column_account-iban' => 'Asset account (IBAN)', 'column_account-iban' => 'Asset account (IBAN)',
'column_account-id' => 'Asset account ID (matching FF3)', 'column_account-id' => 'Asset account ID (matching FF3)',
'column_account-name' => 'Asset account (name)', 'column_account-name' => 'Asset account (name)',
'column_amount' => 'Amount', 'column_amount' => 'Amount',
'column_amount_foreign' => 'Amount (in foreign currency)', 'column_amount_foreign' => 'Amount (in foreign currency)',
'column_amount_debit' => 'Amount (debit column)', 'column_amount_debit' => 'Amount (debit column)',
'column_amount_credit' => 'Amount (credit column)', 'column_amount_credit' => 'Amount (credit column)',
'column_amount-comma-separated' => 'Amount (comma as decimal separator)', 'column_amount-comma-separated' => 'Amount (comma as decimal separator)',
'column_bill-id' => 'Bill ID (matching FF3)', 'column_bill-id' => 'Bill ID (matching FF3)',
'column_bill-name' => 'Bill name', 'column_bill-name' => 'Bill name',
'column_budget-id' => 'Budget ID (matching FF3)', 'column_budget-id' => 'Budget ID (matching FF3)',
'column_budget-name' => 'Budget name', 'column_budget-name' => 'Budget name',
'column_category-id' => 'Category ID (matching FF3)', 'column_category-id' => 'Category ID (matching FF3)',
'column_category-name' => 'Category name', 'column_category-name' => 'Category name',
'column_currency-code' => 'Currency code (ISO 4217)', 'column_currency-code' => 'Currency code (ISO 4217)',
'column_foreign-currency-code' => 'Foreign currency code (ISO 4217)', 'column_foreign-currency-code' => 'Foreign currency code (ISO 4217)',
'column_currency-id' => 'Currency ID (matching FF3)', 'column_currency-id' => 'Currency ID (matching FF3)',
'column_currency-name' => 'Currency name (matching FF3)', 'column_currency-name' => 'Currency name (matching FF3)',
'column_currency-symbol' => 'Currency symbol (matching FF3)', 'column_currency-symbol' => 'Currency symbol (matching FF3)',
'column_date-interest' => 'Interest calculation date', 'column_date-interest' => 'Interest calculation date',
'column_date-book' => 'Transaction booking date', 'column_date-book' => 'Transaction booking date',
'column_date-process' => 'Transaction process date', 'column_date-process' => 'Transaction process date',
'column_date-transaction' => 'Date', 'column_date-transaction' => 'Date',
'column_date-due' => 'Transaction due date', 'column_date-due' => 'Transaction due date',
'column_date-payment' => 'Transaction payment date', 'column_date-payment' => 'Transaction payment date',
'column_date-invoice' => 'Transaction invoice date', 'column_date-invoice' => 'Transaction invoice date',
'column_description' => 'Description', 'column_description' => 'Description',
'column_opposing-iban' => 'Opposing account (IBAN)', 'column_opposing-iban' => 'Opposing account (IBAN)',
'column_opposing-bic' => 'Opposing account (BIC)', 'column_opposing-bic' => 'Opposing account (BIC)',
'column_opposing-id' => 'Opposing account ID (matching FF3)', 'column_opposing-id' => 'Opposing account ID (matching FF3)',
'column_external-id' => 'External ID', 'column_external-id' => 'External ID',
'column_opposing-name' => 'Opposing account (name)', 'column_opposing-name' => 'Opposing account (name)',
'column_rabo-debit-credit' => 'Rabobank specific debit/credit indicator', 'column_rabo-debit-credit' => 'Rabobank specific debit/credit indicator',
'column_ing-debit-credit' => 'ING specific debit/credit indicator', 'column_ing-debit-credit' => 'ING specific debit/credit indicator',
'column_sepa-ct-id' => 'SEPA end-to-end Identifier', 'column_sepa-ct-id' => 'SEPA end-to-end Identifier',
'column_sepa-ct-op' => 'SEPA Opposing Account Identifier', 'column_sepa-ct-op' => 'SEPA Opposing Account Identifier',
'column_sepa-db' => 'SEPA Mandate Identifier', 'column_sepa-db' => 'SEPA Mandate Identifier',
'column_sepa-cc' => 'SEPA Clearing Code', 'column_sepa-cc' => 'SEPA Clearing Code',
'column_sepa-ci' => 'SEPA Creditor Identifier', 'column_sepa-ci' => 'SEPA Creditor Identifier',
'column_sepa-ep' => 'SEPA External Purpose', 'column_sepa-ep' => 'SEPA External Purpose',
'column_sepa-country' => 'SEPA Country Code', 'column_sepa-country' => 'SEPA Country Code',
'column_tags-comma' => 'Tags (comma separated)', 'column_tags-comma' => 'Tags (comma separated)',
'column_tags-space' => 'Tags (space separated)', 'column_tags-space' => 'Tags (space separated)',
'column_account-number' => 'Asset account (account number)', 'column_account-number' => 'Asset account (account number)',
'column_opposing-number' => 'Opposing account (account number)', 'column_opposing-number' => 'Opposing account (account number)',
'column_note' => 'Note(s)', 'column_note' => 'Note(s)',
'column_internal-reference' => 'Internal reference', 'column_internal-reference' => 'Internal reference',
// prerequisites // prerequisites
'prerequisites' => 'Prerequisites', 'prerequisites' => 'Prerequisites',
'prerequisites_breadcrumb_fake' => 'Prerequisites for fake provider', 'prerequisites_breadcrumb_fake' => 'Prerequisites for fake provider',
'prerequisites_breadcrumb_file' => 'Prerequisites for file imports', 'prerequisites_breadcrumb_file' => 'Prerequisites for file imports',
'prerequisites_breadcrumb_bunq' => 'Prerequisites for Bunq', 'prerequisites_breadcrumb_bunq' => 'Prerequisites for Bunq',
'prerequisites_breadcrumb_spectre' => 'Prerequisites for Spectre', 'prerequisites_breadcrumb_spectre' => 'Prerequisites for Spectre',
'prerequisites_breadcrumb_plaid' => 'Prerequisites for Plaid', 'prerequisites_breadcrumb_plaid' => 'Prerequisites for Plaid',
'prerequisites_breadcrumb_quovo' => 'Prerequisites for Quovo', 'prerequisites_breadcrumb_quovo' => 'Prerequisites for Quovo',
'prerequisites_breadcrumb_yodlee' => 'Prerequisites for Yodlee', 'prerequisites_breadcrumb_yodlee' => 'Prerequisites for Yodlee',
// success messages: // success messages:
'prerequisites_saved_for_fake' => 'API key stored for fake provider', 'prerequisites_saved_for_fake' => 'API key stored for fake provider',
'prerequisites_saved_for_file' => 'Data stored for file imports', 'prerequisites_saved_for_file' => 'Data stored for file imports',
'prerequisites_saved_for_bunq' => 'API key and IP stored for bunq', 'prerequisites_saved_for_bunq' => 'API key and IP stored for bunq',
'prerequisites_saved_for_spectre' => 'App ID and secret stored for Spectre', 'prerequisites_saved_for_spectre' => 'App ID and secret stored for Spectre',
'prerequisites_saved_for_plaid' => 'Data stored for Plaid', 'prerequisites_saved_for_plaid' => 'Data stored for Plaid',
'prerequisites_saved_for_quovo' => 'Data stored for Quovo', 'prerequisites_saved_for_quovo' => 'Data stored for Quovo',
'prerequisites_saved_for_yodlee' => 'Data stored for Yodlee', 'prerequisites_saved_for_yodlee' => 'Data stored for Yodlee',
// index of import: // index of import:
'general_index_title' => 'Import a file', 'general_index_title' => 'Import a file',
'general_index_intro' => 'Welcome to Firefly III\'s import routine. There are a few ways of importing data into Firefly III, displayed here as buttons.', 'general_index_intro' => 'Welcome to Firefly III\'s import routine. There are a few ways of importing data into Firefly III, displayed here as buttons.',
// import provider strings (index): // import provider strings (index):
'button_fake' => 'Fake an import', 'button_fake' => 'Fake an import',
'button_file' => 'Import a file', 'button_file' => 'Import a file',
'button_bunq' => 'Import from bunq', 'button_bunq' => 'Import from bunq',
'button_spectre' => 'Import using Spectre', 'button_spectre' => 'Import using Spectre',
'button_plaid' => 'Import using Plaid', 'button_plaid' => 'Import using Plaid',
'button_yodlee' => 'Import using Yodlee', 'button_yodlee' => 'Import using Yodlee',
'button_quovo' => 'Import using Quovo', 'button_quovo' => 'Import using Quovo',
// global config box // global config box
'global_config_title' => 'Global import configuration', 'global_config_title' => 'Global import configuration',
'global_config_text' => 'In the future, this box will feature preferences that apply to ALL import providers above.', 'global_config_text' => 'In the future, this box will feature preferences that apply to ALL import providers above.',
// prereq box: // prereq box:
'need_prereq_title' => 'Import prerequisites', 'need_prereq_title' => 'Import prerequisites',
'need_prereq_intro' => 'Some import methods need your attention before they can be used. For example, they might require special API keys or application secrets. You can configure them here. The icon indicates if these prerequisites have been met.', 'need_prereq_intro' => 'Some import methods need your attention before they can be used. For example, they might require special API keys or application secrets. You can configure them here. The icon indicates if these prerequisites have been met.',
'do_prereq_fake' => 'Prerequisites for the fake provider', 'do_prereq_fake' => 'Prerequisites for the fake provider',
'do_prereq_file' => 'Prerequisites for file imports', 'do_prereq_file' => 'Prerequisites for file imports',
'do_prereq_bunq' => 'Prerequisites for imports from bunq', 'do_prereq_bunq' => 'Prerequisites for imports from bunq',
'do_prereq_spectre' => 'Prerequisites for imports using Spectre', 'do_prereq_spectre' => 'Prerequisites for imports using Spectre',
'do_prereq_plaid' => 'Prerequisites for imports using Plaid', 'do_prereq_plaid' => 'Prerequisites for imports using Plaid',
'do_prereq_yodlee' => 'Prerequisites for imports using Yodlee', 'do_prereq_yodlee' => 'Prerequisites for imports using Yodlee',
'do_prereq_quovo' => 'Prerequisites for imports using Quovo', 'do_prereq_quovo' => 'Prerequisites for imports using Quovo',
// provider config box: // provider config box:
'can_config_title' => 'Import configuration', 'can_config_title' => 'Import configuration',
'can_config_intro' => 'Some import methods can be configured to your liking. They have extra settings you can tweak.', 'can_config_intro' => 'Some import methods can be configured to your liking. They have extra settings you can tweak.',
'do_config_fake' => 'Configuration for the fake provider', 'do_config_fake' => 'Configuration for the fake provider',
'do_config_file' => 'Configuration for file imports', 'do_config_file' => 'Configuration for file imports',
'do_config_bunq' => 'Configuration for bunq imports', 'do_config_bunq' => 'Configuration for bunq imports',
'do_config_spectre' => 'Configuration for imports from Spectre', 'do_config_spectre' => 'Configuration for imports from Spectre',
'do_config_plaid' => 'Configuration for imports from Plaid', 'do_config_plaid' => 'Configuration for imports from Plaid',
'do_config_yodlee' => 'Configuration for imports from Yodlee', 'do_config_yodlee' => 'Configuration for imports from Yodlee',
'do_config_quovo' => 'Configuration for imports from Quovo', 'do_config_quovo' => 'Configuration for imports from Quovo',
// job configuration:
'job_configuration_breadcrumb' => 'Configuration for job ":key"',
// import index page: // import index page:
'index_breadcrumb' => 'Index', 'index_breadcrumb' => 'Index',
'upload_error' => 'The file you have uploaded could not be processed. Possibly it is of an invalid file type or encoding. The log files will have more information.', 'upload_error' => 'The file you have uploaded could not be processed. Possibly it is of an invalid file type or encoding. The log files will have more information.',

View File

@ -0,0 +1,53 @@
{% extends "./layout/default" %}
{% block breadcrumbs %}
{{ Breadcrumbs.render }}
{% endblock %}
{% block content %}
<div class="row">
<div class="col-lg-12">
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">Enter artist for fake import</h3>
</div>
<div class="box-body">
<p>
Enter "David Bowie", no matter the capitalization.
</p>
</div>
</div>
</div>
</div>
<form method="POST" action="{{ route('import.job.configuration.post', job.key) }}" accept-charset="UTF-8" class="form-horizontal" enctype="multipart/form-data">
<input name="_token" type="hidden" value="{{ csrf_token() }}">
<div class="row">
<div class="col-lg-12">
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">Fields be here.</h3>
</div>
<div class="box-body">
{{ ExpandedForm.text('artist') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="box">
<div class="box-body">
<button type="submit" class="btn btn-success pull-right">
Submit it!
</button>
</div>
</div>
</div>
</div>
</form>
{% endblock %}
{% block scripts %}
{% endblock %}
{% block styles %}
{% endblock %}

View File

@ -0,0 +1,53 @@
{% extends "./layout/default" %}
{% block breadcrumbs %}
{{ Breadcrumbs.render }}
{% endblock %}
{% block content %}
<div class="row">
<div class="col-lg-12">
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">Enter song for fake import</h3>
</div>
<div class="box-body">
<p>
Enter "golden years", no matter the capitalization.
</p>
</div>
</div>
</div>
</div>
<form method="POST" action="{{ route('import.job.configuration.post', job.key) }}" accept-charset="UTF-8" class="form-horizontal" enctype="multipart/form-data">
<input name="_token" type="hidden" value="{{ csrf_token() }}">
<div class="row">
<div class="col-lg-12">
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">Fields be here.</h3>
</div>
<div class="box-body">
{{ ExpandedForm.text('song') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="box">
<div class="box-body">
<button type="submit" class="btn btn-success pull-right">
Submit it!
</button>
</div>
</div>
</div>
</div>
</form>
{% endblock %}
{% block scripts %}
{% endblock %}
{% block styles %}
{% endblock %}

File diff suppressed because it is too large Load Diff

View File

@ -451,6 +451,11 @@ Route::group(
// set global prerequisites for an import source, possible with a job already attached. // set global prerequisites for an import source, possible with a job already attached.
Route::get('prerequisites/{import_provider}/{importJob?}', ['uses' => 'Import\PrerequisitesController@index', 'as' => 'prerequisites.index']); Route::get('prerequisites/{import_provider}/{importJob?}', ['uses' => 'Import\PrerequisitesController@index', 'as' => 'prerequisites.index']);
Route::post('prerequisites/{import_provider}/{importJob?}', ['uses' => 'Import\PrerequisitesController@post', 'as' => 'prerequisites.post']); Route::post('prerequisites/{import_provider}/{importJob?}', ['uses' => 'Import\PrerequisitesController@post', 'as' => 'prerequisites.post']);
// configure a job:
Route::get('job/configuration/{importJob}', ['uses' => 'Import\JobConfigurationController@index', 'as' => 'job.configuration.index']);
Route::post('job/configuration/{importJob}', ['uses' => 'Import\JobConfigurationController@post', 'as' => 'job.configuration.post']);
// import method prerequisites: // import method prerequisites:
# #
# #
@ -460,7 +465,7 @@ Route::group(
#Route::get('create/{bank}', ['uses' => 'Import\IndexController@create', 'as' => 'create-job']); #Route::get('create/{bank}', ['uses' => 'Import\IndexController@create', 'as' => 'create-job']);
// configure the job: // configure the job:
#Route::get('configure/{importJob}', ['uses' => 'Import\ConfigurationController@index', 'as' => 'configure']);
#Route::post('configure/{importJob}', ['uses' => 'Import\ConfigurationController@post', 'as' => 'configure.post']); #Route::post('configure/{importJob}', ['uses' => 'Import\ConfigurationController@post', 'as' => 'configure.post']);
// get status of any job: // get status of any job: