First basic import #145

This commit is contained in:
James Cole 2018-07-30 20:39:19 +02:00
parent dfd9cf0874
commit 2add644706
No known key found for this signature in database
GPG Key ID: C16961E655E74B5E
8 changed files with 794 additions and 117 deletions

View File

@ -27,7 +27,8 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\ImportJob;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
use FireflyIII\Support\Import\JobConfiguration\Ynab\NewYnabJobHandler;
use FireflyIII\Support\Import\JobConfiguration\Ynab\SelectBudgetsHandler;
use FireflyIII\Support\Import\JobConfiguration\Ynab\SelectAccountsHandler;
use FireflyIII\Support\Import\JobConfiguration\Ynab\SelectBudgetHandler;
use FireflyIII\Support\Import\JobConfiguration\Ynab\YnabJobConfigurationInterface;
use Illuminate\Support\MessageBag;
use Log;
@ -121,8 +122,12 @@ class YnabJobConfiguration implements JobConfigurationInterface
$handler->setImportJob($this->importJob);
break;
case 'select_budgets':
/** @var SelectBudgetsHandler $handler */
$handler = app(SelectBudgetsHandler::class);
/** @var SelectBudgetHandler $handler */
$handler = app(SelectBudgetHandler::class);
$handler->setImportJob($this->importJob);
break;
case 'select_accounts':
$handler = app(SelectAccountsHandler::class);
$handler->setImportJob($this->importJob);
break;
default:

View File

@ -27,6 +27,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\ImportJob;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
use FireflyIII\Support\Import\Routine\Ynab\GetAccountsHandler;
use FireflyIII\Support\Import\Routine\Ynab\ImportDataHandler;
use FireflyIII\Support\Import\Routine\Ynab\StageGetAccessHandler;
use FireflyIII\Support\Import\Routine\Ynab\StageGetBudgetsHandler;
use Log;
@ -104,7 +105,18 @@ class YnabRoutine implements RoutineInterface
$this->repository->setStage($this->importJob, 'select_accounts');
$this->repository->setStatus($this->importJob, 'need_job_config');
return;
}
if('go-for-import' === $this->importJob->stage) {
$this->repository->setStatus($this->importJob, 'running');
$this->repository->setStage($this->importJob, 'do_import');
/** @var ImportDataHandler $handler */
$handler = app(ImportDataHandler::class);
$handler->setImportJob($this->importJob);
$handler->run();
$this->repository->setStatus($this->importJob, 'provider_finished');
$this->repository->setStage($this->importJob, 'final');
return;
}
// if ('match_accounts' === $this->importJob->stage) {

View File

@ -0,0 +1,57 @@
<?php
/**
* GetTransactionsRequest.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\Services\Ynab\Request;
use Log;
/**
* Class GetTransactionsRequest
*/
class GetTransactionsRequest extends YnabRequest
{
/** @var string */
public $accountId;
/** @var array */
public $accounts;
/** @var string */
public $budgetId;
/** @var array */
public $transactions;
/**
*
*/
public function call(): void
{
Log::debug('Now in GetTransactionsRequest::call()');
$uri = $this->api . sprintf('/budgets/%s/accounts/%s/transactions', $this->budgetId, $this->accountId);
Log::debug(sprintf('URI is %s', $uri));
$result = $this->authenticatedGetRequest($uri, []);
// expect data in [data][transactions]
$this->transactions = $result['data']['transactions'] ?? [];
}
}

View File

@ -0,0 +1,237 @@
<?php
/**
* SelectAccountsHandler.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\Support\Import\JobConfiguration\Ynab;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\ImportJob;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
use Illuminate\Support\MessageBag;
use Log;
/**
* Class SelectAccountsHandler
*/
class SelectAccountsHandler implements YnabJobConfigurationInterface
{
/** @var AccountRepositoryInterface */
private $accountRepository;
/** @var CurrencyRepositoryInterface */
private $currencyRepository;
/** @var ImportJob */
private $importJob;
/** @var ImportJobRepositoryInterface */
private $repository;
/**
* Return true when this stage is complete.
*
* @return bool
*/
public function configurationComplete(): bool
{
Log::debug('Now in SelectAccountsHandler::configurationComplete()');
$config = $this->importJob->configuration;
$mapping = $config['mapping'] ?? [];
if (\count($mapping) > 0) {
// mapping is complete.
Log::debug('Looks like user has mapped YNAB accounts to Firefly III accounts', $mapping);
$this->repository->setStage($this->importJob, 'go-for-import');
return true;
}
return false;
}
/**
* Store the job configuration.
*
* @param array $data
*
* @return MessageBag
*/
public function configureJob(array $data): MessageBag
{
Log::debug('Now in SelectAccountsHandler::configureJob()', $data);
$config = $this->importJob->configuration;
$mapping = $data['account_mapping'] ?? [];
$final = [];
$applyRules = 1 === (int)($data['apply_rules'] ?? 0);
foreach ($mapping as $ynabId => $localId) {
// validate each
$ynabId = $this->validYnabAccount($ynabId);
$accountId = $this->validLocalAccount((int)$localId);
$final[$ynabId] = $accountId;
}
Log::debug('Final mapping is:', $final);
$messages = new MessageBag;
$config['mapping'] = $final;
$config['apply-rules'] = $applyRules;
$this->repository->setConfiguration($this->importJob, $config);
if ($final === ['' => 0] || 0 === \count($final)) {
$messages->add('count', (string)trans('import.ynab_no_mapping'));
}
return $messages;
}
/**
* Get data for config view.
*
* @return array
* @throws FireflyException
*/
public function getNextData(): array
{
Log::debug('Now in ChooseAccountsHandler::getnextData()');
$config = $this->importJob->configuration;
$ynabAccounts = $config['accounts'] ?? [];
$budget = $this->getSelectedBudget();
if (0 === \count($ynabAccounts)) {
throw new FireflyException('It seems you have no accounts with this budget. The import cannot continue.'); // @codeCoverageIgnore
}
// list the users accounts:
$ffAccounts = $this->accountRepository->getAccountsByType([AccountType::ASSET]);
$array = [];
/** @var Account $account */
foreach ($ffAccounts as $account) {
$accountId = $account->id;
$currencyId = (int)$this->accountRepository->getMetaValue($account, 'currency_id');
$currency = $this->getCurrency($currencyId);
$array[$accountId] = [
'name' => $account->name,
'iban' => $account->iban,
'code' => $currency->code,
];
}
return [
'budget' => $budget,
'ynab_accounts' => $ynabAccounts,
'ff_accounts' => $array,
];
}
/**
* Get the view for this stage.
*
* @return string
*/
public function getNextView(): string
{
return 'import.ynab.accounts';
}
/**
* @codeCoverageIgnore
* Set the import job.
*
* @param ImportJob $importJob
*/
public function setImportJob(ImportJob $importJob): void
{
$this->importJob = $importJob;
$this->repository = app(ImportJobRepositoryInterface::class);
$this->accountRepository = app(AccountRepositoryInterface::class);
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
$this->repository->setUser($importJob->user);
$this->currencyRepository->setUser($importJob->user);
$this->accountRepository->setUser($importJob->user);
}
/**
* @param int $currencyId
*
* @return TransactionCurrency
*/
private function getCurrency(int $currencyId): TransactionCurrency
{
$currency = $this->currencyRepository->findNull($currencyId);
if (null === $currency) {
return app('amount')->getDefaultCurrencyByUser($this->importJob->user);
}
return $currency;
}
/**
* @return array
*/
private function getSelectedBudget(): array
{
$config = $this->repository->getConfiguration($this->importJob);
$budgets = $config['budgets'] ?? [];
$selected = $config['selected_budget'] ?? '';
foreach ($budgets as $budget) {
if ($budget['id'] === $selected) {
return $budget;
}
}
return $budgets[0] ?? [];
}
/**
* @param int $accountId
*
* @return int
*/
private function validLocalAccount(int $accountId): int
{
$account = $this->accountRepository->findNull($accountId);
if (null === $account) {
return 0;
}
return $accountId;
}
/**
* @param int $accountId
*
* @return string
*/
private function validYnabAccount(string $accountId): string
{
$config = $this->importJob->configuration;
$accounts = $config['accounts'] ?? [];
foreach ($accounts as $account) {
if ($account['id'] === $accountId) {
return $accountId;
}
}
return '';
}
}

View File

@ -1,6 +1,6 @@
<?php
/**
* SelectBudgetsHandler.php
* SelectBudgetHandler.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
@ -29,9 +29,9 @@ use Illuminate\Support\MessageBag;
use Log;
/**
* Class SelectBudgetsHandler
* Class SelectBudgetHandler
*/
class SelectBudgetsHandler implements YnabJobConfigurationInterface
class SelectBudgetHandler implements YnabJobConfigurationInterface
{
/** @var ImportJob */
private $importJob;
@ -45,7 +45,7 @@ class SelectBudgetsHandler implements YnabJobConfigurationInterface
*/
public function configurationComplete(): bool
{
Log::debug('Now in SelectBudgetsHandler::configComplete');
Log::debug('Now in SelectBudgetHandler::configComplete');
$configuration = $this->repository->getConfiguration($this->importJob);
$selectedBudget = $configuration['selected_budget'] ?? '';
if ($selectedBudget !== '') {
@ -67,7 +67,7 @@ class SelectBudgetsHandler implements YnabJobConfigurationInterface
*/
public function configureJob(array $data): MessageBag
{
Log::debug('Now in SelectBudgetsHandler::configureJob');
Log::debug('Now in SelectBudgetHandler::configureJob');
$configuration = $this->repository->getConfiguration($this->importJob);
$configuration['selected_budget'] = $data['budget_id'];
@ -87,7 +87,7 @@ class SelectBudgetsHandler implements YnabJobConfigurationInterface
*/
public function getNextData(): array
{
Log::debug('Now in SelectBudgetsHandler::getNextData');
Log::debug('Now in SelectBudgetHandler::getNextData');
$configuration = $this->repository->getConfiguration($this->importJob);
$budgets = $configuration['budgets'] ?? [];
$return = [];
@ -107,7 +107,7 @@ class SelectBudgetsHandler implements YnabJobConfigurationInterface
*/
public function getNextView(): string
{
Log::debug('Now in SelectBudgetsHandler::getNextView');
Log::debug('Now in SelectBudgetHandler::getNextView');
return 'import.ynab.select-budgets';
}

View File

@ -0,0 +1,248 @@
<?php
/**
* ImportDataHandler.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\Support\Import\Routine\Ynab;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\ImportJob;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
use FireflyIII\Services\Ynab\Request\GetTransactionsRequest;
use FireflyIII\Support\Import\Routine\File\OpposingAccountMapper;
use Log;
/**
* Class ImportDataHandler
*/
class ImportDataHandler
{
/** @var AccountRepositoryInterface */
private $accountRepository;
/** @var ImportJob */
private $importJob;
/** @var OpposingAccountMapper */
private $mapper;
/** @var ImportJobRepositoryInterface */
private $repository;
/**
* Get list of accounts for the selected budget.
*
* @throws FireflyException
*/
public function run(): void
{
$config = $this->repository->getConfiguration($this->importJob);
$token = $config['access_token'];
// make request for each mapping:
$mapping = $config['mapping'] ?? [];
$total = [[]];
/**
* @var string $ynabId
* @var int $localId
*/
foreach ($mapping as $ynabId => $localId) {
$localAccount = $this->getLocalAccount((int)$localId);
$transactions = $this->getTransactions($token, $ynabId);
$converted = $this->convertToArray($transactions, $localAccount);
$total[] = $converted;
}
$totalSet = array_merge(...$total);
Log::debug(sprintf('Found %d transactions in total.', \count($totalSet)));
$this->repository->setTransactions($this->importJob, $totalSet);
}
/**
* @param ImportJob $importJob
*/
public function setImportJob(ImportJob $importJob): void
{
$this->importJob = $importJob;
$this->repository = app(ImportJobRepositoryInterface::class);
$this->accountRepository = app(AccountRepositoryInterface::class);
$this->mapper = app(OpposingAccountMapper::class);
$this->accountRepository->setUser($importJob->user);
$this->repository->setUser($importJob->user);
$this->mapper->setUser($importJob->user);
}
/**
* @param array $transactions
* @param Account $localAccount
*
* @return array
* @throws FireflyException
*/
private function convertToArray(array $transactions, Account $localAccount): array
{
$array = [];
$total = \count($transactions);
$budget = $this->getSelectedBudget();
Log::debug(sprintf('Now in StageImportDataHandler::convertToArray() with count %d', \count($transactions)));
/** @var array $transaction */
foreach ($transactions as $index => $transaction) {
Log::debug(sprintf('Now creating array for transaction %d of %d', $index + 1, $total));
$amount = (string)($transaction['amount'] ?? 0);
if ('0' === $amount) {
continue;
}
$source = $localAccount;
$type = 'withdrawal';
$tags = [
$transaction['cleared'] ?? '',
$transaction['approved'] ? 'approved' : 'not-approved',
$transaction['flag_color'] ?? '',
];
$destinationData = [
'name' => $transaction['payee_name'],
'iban' => null,
'number' => $transaction['payee_id'],
'bic' => null,
];
$destination = $this->mapper->map(null, $amount, $destinationData);
if (1 === bccomp($amount, '0')) {
[$source, $destination] = [$destination, $source];
$type = 'deposit';
}
$entry = [
'type' => $type,
'date' => $transaction['date'] ?? date('Y-m-d'),
'tags' => $tags, // TODO
'user' => $this->importJob->user_id,
'notes' => null, // TODO
// all custom fields:
'external_id' => $transaction['id'] ?? '',
// journal data:
'description' => $transaction['memo'] ?? '(empty)',
'piggy_bank_id' => null,
'piggy_bank_name' => null,
'bill_id' => null,
'bill_name' => null,
// transaction data:
'transactions' => [
[
'currency_id' => null,
'currency_code' => $budget['currency_code'],
'description' => null,
'amount' => bcdiv((string)$transaction['amount'], '1000'),
'budget_id' => null,
'budget_name' => null,
'category_id' => null,
'category_name' => $transaction['category_name'],
'source_id' => $source->id,
'source_name' => null,
'destination_id' => $destination->id,
'destination_name' => null,
'foreign_currency_id' => null,
'foreign_currency_code' => null,
'foreign_amount' => null,
'reconciled' => false,
'identifier' => 0,
],
],
];
$array[] = $entry;
}
return $array;
}
/**
* @param int $accountId
*
* @return Account
* @throws FireflyException
*/
private function getLocalAccount(int $accountId): Account
{
$account = $this->accountRepository->findNull($accountId);
if (null === $account) {
throw new FireflyException(sprintf('Cannot find Firefly III asset account with ID #%d. Job must stop now.', $accountId)); // @codeCoverageIgnore
}
if ($account->accountType->type !== AccountType::ASSET) {
throw new FireflyException(sprintf('Account with ID #%d is not an asset account. Job must stop now.', $accountId)); // @codeCoverageIgnore
}
return $account;
}
/**
* @return array
* @throws FireflyException
*/
private function getSelectedBudget(): array
{
$config = $this->repository->getConfiguration($this->importJob);
$budgets = $config['budgets'] ?? [];
$selected = $config['selected_budget'] ?? '';
if ('' === $selected) {
$firstBudget = $config['budgets'][0] ?? false;
if (false === $firstBudget) {
throw new FireflyException('The configuration contains no budget. Erroring out.');
}
$selected = $firstBudget['id'];
}
foreach ($budgets as $budget) {
if ($budget['id'] === $selected) {
return $budget;
}
}
return $budgets[0] ?? [];
}
/**
* @param string $token
* @param string $budget
* @param string $account
*
* @return array
* @throws FireflyException
*/
private function getTransactions(string $token, string $account): array
{
$budget = $this->getSelectedBudget();
$request = new GetTransactionsRequest;
$request->budgetId = $budget['id'];
$request->accountId = $account;
// todo grab latest date for $ynabId
$request->setAccessToken($token);
$request->call();
return $request->transactions;
}
}

View File

@ -24,132 +24,150 @@ declare(strict_types=1);
return [
// ALL breadcrumbs and subtitles:
'index_breadcrumb' => 'Import data into Firefly III',
'prerequisites_breadcrumb_fake' => 'Prerequisites for the fake import provider',
'prerequisites_breadcrumb_spectre' => 'Prerequisites for Spectre',
'prerequisites_breadcrumb_bunq' => 'Prerequisites for bunq',
'prerequisites_breadcrumb_ynab' => 'Prerequisites for YNAB',
'job_configuration_breadcrumb' => 'Configuration for ":key"',
'job_status_breadcrumb' => 'Import status for ":key"',
'cannot_create_for_provider' => 'Firefly III cannot create a job for the ":provider"-provider.',
'disabled_for_demo_user' => 'disabled in demo',
'index_breadcrumb' => 'Import data into Firefly III',
'prerequisites_breadcrumb_fake' => 'Prerequisites for the fake import provider',
'prerequisites_breadcrumb_spectre' => 'Prerequisites for Spectre',
'prerequisites_breadcrumb_bunq' => 'Prerequisites for bunq',
'prerequisites_breadcrumb_ynab' => 'Prerequisites for YNAB',
'job_configuration_breadcrumb' => 'Configuration for ":key"',
'job_status_breadcrumb' => 'Import status for ":key"',
'cannot_create_for_provider' => 'Firefly III cannot create a job for the ":provider"-provider.',
'disabled_for_demo_user' => 'disabled in demo',
// index page:
'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_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.',
// import provider strings (index):
'button_fake' => 'Fake an import',
'button_file' => 'Import a file',
'button_bunq' => 'Import from bunq',
'button_spectre' => 'Import using Spectre',
'button_plaid' => 'Import using Plaid',
'button_yodlee' => 'Import using Yodlee',
'button_quovo' => 'Import using Quovo',
'button_ynab' => 'Import from You Need A Budget',
'button_fake' => 'Fake an import',
'button_file' => 'Import a file',
'button_bunq' => 'Import from bunq',
'button_spectre' => 'Import using Spectre',
'button_plaid' => 'Import using Plaid',
'button_yodlee' => 'Import using Yodlee',
'button_quovo' => 'Import using Quovo',
'button_ynab' => 'Import from You Need A Budget',
// global config box (index)
'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_title' => 'Global import configuration',
'global_config_text' => 'In the future, this box will feature preferences that apply to ALL import providers above.',
// prerequisites box (index)
'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.',
'do_prereq_fake' => 'Prerequisites for the fake provider',
'do_prereq_file' => 'Prerequisites for file imports',
'do_prereq_bunq' => 'Prerequisites for imports from bunq',
'do_prereq_spectre' => 'Prerequisites for imports using Spectre',
'do_prereq_plaid' => 'Prerequisites for imports using Plaid',
'do_prereq_yodlee' => 'Prerequisites for imports using Yodlee',
'do_prereq_quovo' => 'Prerequisites for imports using Quovo',
'do_prereq_ynab' => 'Prerequisites for imports from YNAB',
'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.',
'do_prereq_fake' => 'Prerequisites for the fake provider',
'do_prereq_file' => 'Prerequisites for file imports',
'do_prereq_bunq' => 'Prerequisites for imports from bunq',
'do_prereq_spectre' => 'Prerequisites for imports using Spectre',
'do_prereq_plaid' => 'Prerequisites for imports using Plaid',
'do_prereq_yodlee' => 'Prerequisites for imports using Yodlee',
'do_prereq_quovo' => 'Prerequisites for imports using Quovo',
'do_prereq_ynab' => 'Prerequisites for imports from YNAB',
// provider config box (index)
'can_config_title' => 'Import configuration',
'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_file' => 'Configuration for file imports',
'do_config_bunq' => 'Configuration for bunq imports',
'do_config_spectre' => 'Configuration for imports from Spectre',
'do_config_plaid' => 'Configuration for imports from Plaid',
'do_config_yodlee' => 'Configuration for imports from Yodlee',
'do_config_quovo' => 'Configuration for imports from Quovo',
'can_config_title' => 'Import configuration',
'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_file' => 'Configuration for file imports',
'do_config_bunq' => 'Configuration for bunq imports',
'do_config_spectre' => 'Configuration for imports from Spectre',
'do_config_plaid' => 'Configuration for imports from Plaid',
'do_config_yodlee' => 'Configuration for imports from Yodlee',
'do_config_quovo' => 'Configuration for imports from Quovo',
// prerequisites:
'prereq_fake_title' => 'Prerequisites for an import from the fake import provider',
'prereq_fake_text' => 'This fake provider requires a fake API key. It must be 32 characters long. You can use this one: 123456789012345678901234567890AA',
'prereq_spectre_title' => 'Prerequisites for an import using the Spectre API',
'prereq_spectre_text' => 'In order to import data using the Spectre API (v4), you must provide Firefly III with two secret values. They can be found on the <a href="https://www.saltedge.com/clients/profile/secrets">secrets page</a>.',
'prereq_spectre_pub' => 'Likewise, the Spectre API needs to know the public key you see below. Without it, it will not recognize you. Please enter this public key on your <a href="https://www.saltedge.com/clients/profile/secrets">secrets page</a>.',
'prereq_bunq_title' => 'Prerequisites for an import from bunq',
'prereq_bunq_text' => 'In order to import from bunq, you need to obtain an API key. You can do this through the app. Please note that the import function for bunq is in BETA. It has only been tested against the sandbox API.',
'prereq_bunq_ip' => 'bunq requires your externally facing IP address. Firefly III has tried to fill this in using <a href="https://www.ipify.org/">the ipify service</a>. Make sure this IP address is correct, or the import will fail.',
'prereq_ynab_title' => 'Prerequisites for an import from YNAB',
'prereq_ynab_text' => 'In order to be able to download transactions from YNAB, please create a new application on your <a href="https://app.youneedabudget.com/settings/developer">Developer Settings Page</a> and enter the client ID and secret on this page.',
'prereq_ynab_redirect' => 'To complete the configuration, enter the following URL at the <a href="https://app.youneedabudget.com/settings/developer">Developer Settings Page</a> under the "Redirect URI(s)".',
'prereq_fake_title' => 'Prerequisites for an import from the fake import provider',
'prereq_fake_text' => 'This fake provider requires a fake API key. It must be 32 characters long. You can use this one: 123456789012345678901234567890AA',
'prereq_spectre_title' => 'Prerequisites for an import using the Spectre API',
'prereq_spectre_text' => 'In order to import data using the Spectre API (v4), you must provide Firefly III with two secret values. They can be found on the <a href="https://www.saltedge.com/clients/profile/secrets">secrets page</a>.',
'prereq_spectre_pub' => 'Likewise, the Spectre API needs to know the public key you see below. Without it, it will not recognize you. Please enter this public key on your <a href="https://www.saltedge.com/clients/profile/secrets">secrets page</a>.',
'prereq_bunq_title' => 'Prerequisites for an import from bunq',
'prereq_bunq_text' => 'In order to import from bunq, you need to obtain an API key. You can do this through the app. Please note that the import function for bunq is in BETA. It has only been tested against the sandbox API.',
'prereq_bunq_ip' => 'bunq requires your externally facing IP address. Firefly III has tried to fill this in using <a href="https://www.ipify.org/">the ipify service</a>. Make sure this IP address is correct, or the import will fail.',
'prereq_ynab_title' => 'Prerequisites for an import from YNAB',
'prereq_ynab_text' => 'In order to be able to download transactions from YNAB, please create a new application on your <a href="https://app.youneedabudget.com/settings/developer">Developer Settings Page</a> and enter the client ID and secret on this page.',
'prereq_ynab_redirect' => 'To complete the configuration, enter the following URL at the <a href="https://app.youneedabudget.com/settings/developer">Developer Settings Page</a> under the "Redirect URI(s)".',
// prerequisites success messages:
'prerequisites_saved_for_fake' => 'Fake API key stored successfully!',
'prerequisites_saved_for_spectre' => 'App ID and secret stored!',
'prerequisites_saved_for_bunq' => 'API key and IP stored!',
'prerequisites_saved_for_ynab' => 'YNAB client ID and secret stored!',
'prerequisites_saved_for_fake' => 'Fake API key stored successfully!',
'prerequisites_saved_for_spectre' => 'App ID and secret stored!',
'prerequisites_saved_for_bunq' => 'API key and IP stored!',
'prerequisites_saved_for_ynab' => 'YNAB client ID and secret stored!',
// job configuration:
'job_config_apply_rules_title' => 'Job configuration - apply your rules?',
'job_config_apply_rules_text' => 'Once the fake provider has run, your rules can be applied to the transactions. This adds time to the import.',
'job_config_input' => 'Your input',
'job_config_apply_rules_title' => 'Job configuration - apply your rules?',
'job_config_apply_rules_text' => 'Once the fake provider has run, your rules can be applied to the transactions. This adds time to the import.',
'job_config_input' => 'Your input',
// job configuration for the fake provider:
'job_config_fake_artist_title' => 'Enter album name',
'job_config_fake_artist_text' => 'Many import routines have a few configuration steps you must go through. In the case of the fake import provider, you must answer some weird questions. In this case, enter "David Bowie" to continue.',
'job_config_fake_song_title' => 'Enter song name',
'job_config_fake_song_text' => 'Mention the song "Golden years" to continue with the fake import.',
'job_config_fake_album_title' => 'Enter album name',
'job_config_fake_album_text' => 'Some import routines require extra data halfway through the import. In the case of the fake import provider, you must answer some weird questions. Enter "Station to station" to continue.',
'job_config_fake_artist_title' => 'Enter album name',
'job_config_fake_artist_text' => 'Many import routines have a few configuration steps you must go through. In the case of the fake import provider, you must answer some weird questions. In this case, enter "David Bowie" to continue.',
'job_config_fake_song_title' => 'Enter song name',
'job_config_fake_song_text' => 'Mention the song "Golden years" to continue with the fake import.',
'job_config_fake_album_title' => 'Enter album name',
'job_config_fake_album_text' => 'Some import routines require extra data halfway through the import. In the case of the fake import provider, you must answer some weird questions. Enter "Station to station" to continue.',
// job configuration form the file provider
'job_config_file_upload_title' => 'Import setup (1/4) - Upload your file',
'job_config_file_upload_text' => 'This routine will help you import files from your bank into Firefly III. ',
'job_config_file_upload_help' => 'Select your file. Please make sure the file is UTF-8 encoded.',
'job_config_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>',
'job_config_file_upload_type_help' => 'Select the type of file you will upload',
'job_config_file_upload_submit' => 'Upload files',
'import_file_type_csv' => 'CSV (comma separated values)',
'file_not_utf8' => 'The file you have uploaded is not encoded as UTF-8 or ASCII. Firefly III cannot handle such files. Please use Notepad++ or Sublime to convert your file to UTF-8.',
'job_config_uc_title' => 'Import setup (2/4) - Basic file setup',
'job_config_uc_text' => 'To be able to import your file correctly, please validate the options below.',
'job_config_uc_header_help' => 'Check this box if the first row of your CSV file are the column titles.',
'job_config_uc_date_help' => 'Date time format in your file. Follow the format as <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.',
'job_config_uc_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
'job_config_uc_account_help' => 'If your file does NOT contain information about your asset account(s), use this dropdown to select to which account the transactions in the file belong to.',
'job_config_uc_apply_rules_title' => 'Apply rules',
'job_config_uc_apply_rules_text' => 'Applies your rules to every imported transaction. Note that this slows the import significantly.',
'job_config_uc_specifics_title' => 'Bank-specific options',
'job_config_uc_specifics_txt' => 'Some banks deliver badly formatted files. Firefly III can fix those automatically. If your bank delivers such files but it\'s not listed here, please open an issue on GitHub.',
'job_config_uc_submit' => 'Continue',
'invalid_import_account' => 'You have selected an invalid account to import into.',
'job_config_file_upload_title' => 'Import setup (1/4) - Upload your file',
'job_config_file_upload_text' => 'This routine will help you import files from your bank into Firefly III. ',
'job_config_file_upload_help' => 'Select your file. Please make sure the file is UTF-8 encoded.',
'job_config_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>',
'job_config_file_upload_type_help' => 'Select the type of file you will upload',
'job_config_file_upload_submit' => 'Upload files',
'import_file_type_csv' => 'CSV (comma separated values)',
'file_not_utf8' => 'The file you have uploaded is not encoded as UTF-8 or ASCII. Firefly III cannot handle such files. Please use Notepad++ or Sublime to convert your file to UTF-8.',
'job_config_uc_title' => 'Import setup (2/4) - Basic file setup',
'job_config_uc_text' => 'To be able to import your file correctly, please validate the options below.',
'job_config_uc_header_help' => 'Check this box if the first row of your CSV file are the column titles.',
'job_config_uc_date_help' => 'Date time format in your file. Follow the format as <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.',
'job_config_uc_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
'job_config_uc_account_help' => 'If your file does NOT contain information about your asset account(s), use this dropdown to select to which account the transactions in the file belong to.',
'job_config_uc_apply_rules_title' => 'Apply rules',
'job_config_uc_apply_rules_text' => 'Applies your rules to every imported transaction. Note that this slows the import significantly.',
'job_config_uc_specifics_title' => 'Bank-specific options',
'job_config_uc_specifics_txt' => 'Some banks deliver badly formatted files. Firefly III can fix those automatically. If your bank delivers such files but it\'s not listed here, please open an issue on GitHub.',
'job_config_uc_submit' => 'Continue',
'invalid_import_account' => 'You have selected an invalid account to import into.',
// job configuration for Spectre:
'job_config_spectre_login_title' => 'Choose your login',
'job_config_spectre_login_text' => 'Firefly III has found :count existing login(s) in your Spectre account. Which one would you like to use to import from?',
'spectre_login_status_active' => 'Active',
'spectre_login_status_inactive' => 'Inactive',
'spectre_login_status_disabled' => 'Disabled',
'spectre_login_new_login' => 'Login with another bank, or one of these banks with different credentials.',
'job_config_spectre_accounts_title' => 'Select accounts to import from',
'job_config_spectre_accounts_text' => 'You have selected ":name" (:country). You have :count account(s) available from this provider. Please select the Firefly III asset account(s) where the transactions from these accounts should be stored. Remember, in order to import data both the Firefly III account and the ":name"-account must have the same currency.',
'spectre_no_supported_accounts' => 'You cannot import from this account due to a currency mismatch.',
'spectre_do_not_import' => '(do not import)',
'spectre_no_mapping' => 'It seems you have not selected any accounts to import from.',
'imported_from_account' => 'Imported from ":account"',
'spectre_account_with_number' => 'Account :number',
'job_config_spectre_apply_rules' => 'Apply rules',
'job_config_spectre_apply_rules_text' => 'By default, your rules will be applied to the transactions created during this import routine. If you do not want this to happen, deselect this checkbox.',
'job_config_spectre_login_title' => 'Choose your login',
'job_config_spectre_login_text' => 'Firefly III has found :count existing login(s) in your Spectre account. Which one would you like to use to import from?',
'spectre_login_status_active' => 'Active',
'spectre_login_status_inactive' => 'Inactive',
'spectre_login_status_disabled' => 'Disabled',
'spectre_login_new_login' => 'Login with another bank, or one of these banks with different credentials.',
'job_config_spectre_accounts_title' => 'Select accounts to import from',
'job_config_spectre_accounts_text' => 'You have selected ":name" (:country). You have :count account(s) available from this provider. Please select the Firefly III asset account(s) where the transactions from these accounts should be stored. Remember, in order to import data both the Firefly III account and the ":name"-account must have the same currency.',
'spectre_no_supported_accounts' => 'You cannot import from this account due to a currency mismatch.',
'spectre_do_not_import' => '(do not import)',
'spectre_no_mapping' => 'It seems you have not selected any accounts to import from.',
'imported_from_account' => 'Imported from ":account"',
'spectre_account_with_number' => 'Account :number',
'job_config_spectre_apply_rules' => 'Apply rules',
'job_config_spectre_apply_rules_text' => 'By default, your rules will be applied to the transactions created during this import routine. If you do not want this to happen, deselect this checkbox.',
// job configuration for bunq:
'job_config_bunq_accounts_title' => 'bunq accounts',
'job_config_bunq_accounts_text' => 'These are the accounts associated with your bunq account. Please select the accounts from which you want to import, and in which account the transactions must be imported.',
'bunq_no_mapping' => 'It seems you have not selected any accounts.',
'should_download_config' => 'You should download <a href=":route">the configuration file</a> for this job. This will make future imports way easier.',
'share_config_file' => 'If you have imported data from a public bank, you should <a href="https://github.com/firefly-iii/import-configurations/wiki">share your configuration file</a> so it will be easy for other users to import their data. Sharing your configuration file will not expose your financial details.',
'job_config_bunq_apply_rules' => 'Apply rules',
'job_config_bunq_apply_rules_text' => 'By default, your rules will be applied to the transactions created during this import routine. If you do not want this to happen, deselect this checkbox.',
'job_config_bunq_accounts_title' => 'bunq accounts',
'job_config_bunq_accounts_text' => 'These are the accounts associated with your bunq account. Please select the accounts from which you want to import, and in which account the transactions must be imported.',
'bunq_no_mapping' => 'It seems you have not selected any accounts.',
'should_download_config' => 'You should download <a href=":route">the configuration file</a> for this job. This will make future imports way easier.',
'share_config_file' => 'If you have imported data from a public bank, you should <a href="https://github.com/firefly-iii/import-configurations/wiki">share your configuration file</a> so it will be easy for other users to import their data. Sharing your configuration file will not expose your financial details.',
'job_config_bunq_apply_rules' => 'Apply rules',
'job_config_bunq_apply_rules_text' => 'By default, your rules will be applied to the transactions created during this import routine. If you do not want this to happen, deselect this checkbox.',
'ynab_account_closed' => 'Account is closed!',
'ynab_account_deleted' => 'Account is deleted!',
'ynab_account_type_savings' => 'savings account',
'ynab_account_type_checking' => 'checking account',
'ynab_account_type_cash' => 'cash account',
'ynab_account_type_creditCard' => 'credit card',
'ynab_account_type_lineOfCredit' => 'line of credit',
'ynab_account_type_otherAsset' => 'other asset account',
'ynab_account_type_otherLiability' => 'other liabilities',
'ynab_account_type_payPal' => 'Paypal',
'ynab_account_type_merchantAccount' => 'merchant account',
'ynab_account_type_investmentAccount' => 'investment account',
'ynab_account_type_mortgage' => 'mortgage',
'ynab_do_not_import' => '(do not import)',
'job_config_ynab_apply_rules' => 'Apply rules',
'job_config_ynab_apply_rules_text' => 'By default, your rules will be applied to the transactions created during this import routine. If you do not want this to happen, deselect this checkbox.',
// job configuration for YNAB:
'job_config_select_budgets' => 'Select your budget',
'job_config_spectre_select_budgets_text' => 'You have :count budgets stored at YNAB. Please select the one from which Firefly III will import the transactions.',
'ynab_no_mapping' => 'It seems you have not selected any accounts to import from.',
// keys from "extra" array:
'spectre_extra_key_iban' => 'IBAN',

View File

@ -0,0 +1,100 @@
{% extends "./layout/default" %}
{% block breadcrumbs %}
{{ Breadcrumbs.render }}
{% endblock %}
{% block content %}
<div class="row">
<form class="form-horizontal" action="{{ route('import.job.configuration.post',[importJob.key]) }}" method="post">
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="box box-default">
<div class="box-header with-border">
<h3 class="box-title">{{ trans('import.job_config_ynab_apply_rules') }}</h3>
</div>
<div class="box-body">
<div class="row">
<div class="col-lg-6">
<p>
{{ trans('import.job_config_ynab_apply_rules_text') }}
</p>
{{ ExpandedForm.checkbox('apply_rules', 1, true) }}
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="box box-default">
<div class="box-header with-border">
<h3 class="box-title">{{ trans('import.job_config_ynab_accounts_title') }}</h3>
</div>
<div class="box-body">
<div class="row">
<div class="col-lg-8">
<p>
{{ trans('import.job_config_ynab_accounts_text', {count: data.accounts|length}) }}
</p>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>{{ trans('list.account_on_ynab') }}</th>
<th>{{ trans('list.account') }}</th>
</tr>
</thead>
<tbody>
{% for account in data.ynab_accounts %}
<tr>
<td>
{{ account.name }} ({{ trans('import.ynab_account_type_'~account.type) }})
{% if account.closed %}
<br/><span class="text-warning">{{ trans('import.ynab_account_closed') }}</span>
{% endif %}
{% if account.deleted %}
<br/><span class="text-danger">{{ trans('import.ynab_account_deleted') }}</span>
{% endif %}
</td>
<td>
<select class="form-control" name="account_mapping[{{ account.id }}]">
<option value="0" label="{{ trans('import.ynab_do_not_import') }}">
{{ trans('import.ynab_do_not_import') }}
</option>
{% for ffId, ffAccount in data.ff_accounts %}
{% if ffAccount.code == data.budget.currency_code %}
<option value="{{ ffId }}"{% if currentIban != '' and currentIban == ffAccount.iban %} selected{% endif %}>
{{ ffAccount.name }}{% if ffAccount.iban !='' %} ({{ ffAccount.iban }}){% endif %}
</option>
{% endif %}
{% endfor %}
</select>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<button type="submit" class="btn pull-right btn-success">
{{ ('submit')|_ }}
</button>
</div>
</div>
</div>
</form>
</div>
{% endblock %}
{% block scripts %}
{% endblock %}
{% block styles %}
{% endblock %}