mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-19 10:53:37 +00:00
This code fixes #349
This commit is contained in:
153
app/Console/Commands/CreateImport.php
Normal file
153
app/Console/Commands/CreateImport.php
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* CreateImport.php
|
||||||
|
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This software may be modified and distributed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Console\Commands;
|
||||||
|
|
||||||
|
use Artisan;
|
||||||
|
use FireflyIII\Models\ImportJob;
|
||||||
|
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CreateImport
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Console\Commands
|
||||||
|
*/
|
||||||
|
class CreateImport extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Use this command to create a new import. Your user ID can be found on the /profile page.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'firefly:create-import {file} {configuration} {--user=1} {--type=csv} {--start}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
// find the file
|
||||||
|
/** @var UserRepositoryInterface $userRepository */
|
||||||
|
$userRepository = app(UserRepositoryInterface::class);
|
||||||
|
$file = $this->argument('file');
|
||||||
|
$configuration = $this->argument('configuration');
|
||||||
|
$user = $userRepository->find(intval($this->option('user')));
|
||||||
|
$cwd = getcwd();
|
||||||
|
$type = strtolower($this->option('type'));
|
||||||
|
|
||||||
|
if (!$this->validArguments()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to parse configuration data:
|
||||||
|
$configurationData = json_decode(file_get_contents($configuration));
|
||||||
|
if (is_null($configurationData)) {
|
||||||
|
$this->error(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info(sprintf('Going to create a job to import file: %s', $file));
|
||||||
|
$this->info(sprintf('Using configuration file: %s', $configuration));
|
||||||
|
$this->info(sprintf('Import into user: #%d (%s)', $user->id, $user->email));
|
||||||
|
$this->info(sprintf('Type of import: %s', $type));
|
||||||
|
|
||||||
|
/** @var ImportJobRepositoryInterface $jobRepository */
|
||||||
|
$jobRepository = app(ImportJobRepositoryInterface::class, [$user]);
|
||||||
|
|
||||||
|
$job = $jobRepository->create($type);
|
||||||
|
$this->line(sprintf('Created job "%s"...', $job->key));
|
||||||
|
|
||||||
|
// put the file in the proper place:
|
||||||
|
Artisan::call('firefly:encrypt', ['file' => $file, 'key' => $job->key]);
|
||||||
|
$this->line('Stored import data...');
|
||||||
|
|
||||||
|
// store the configuration in the job:
|
||||||
|
$job->configuration = $configurationData;
|
||||||
|
$job->status = 'settings_complete';
|
||||||
|
$job->save();
|
||||||
|
$this->line('Stored configuration...');
|
||||||
|
|
||||||
|
// if user wants to run it, do!
|
||||||
|
if ($this->option('start') === true) {
|
||||||
|
$this->line('The import will start in a moment. This process is not visible...');
|
||||||
|
Log::debug('Go for import!');
|
||||||
|
Artisan::call('firefly:start-import', ['key' => $job->key]);
|
||||||
|
$this->line('Done!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function validArguments(): bool
|
||||||
|
{
|
||||||
|
// find the file
|
||||||
|
/** @var UserRepositoryInterface $userRepository */
|
||||||
|
$userRepository = app(UserRepositoryInterface::class);
|
||||||
|
$file = $this->argument('file');
|
||||||
|
$configuration = $this->argument('configuration');
|
||||||
|
$user = $userRepository->find(intval($this->option('user')));
|
||||||
|
$cwd = getcwd();
|
||||||
|
$validTypes = array_keys(config('firefly.import_formats'));
|
||||||
|
$type = strtolower($this->option('type'));
|
||||||
|
|
||||||
|
if (is_null($user->id)) {
|
||||||
|
$this->error(sprintf('There is no user with ID %d.', $this->option('user')));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!in_array($type, $validTypes)) {
|
||||||
|
$this->error(sprintf('Cannot import file of type "%s"', $type));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists($file)) {
|
||||||
|
$this->error(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists($configuration)) {
|
||||||
|
$this->error(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -32,14 +32,14 @@ class Import extends Command
|
|||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $description = 'Import stuff into Firefly III.';
|
protected $description = 'This will start a new import.';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name and signature of the console command.
|
* The name and signature of the console command.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $signature = 'firefly:import {key}';
|
protected $signature = 'firefly:start-import {key}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new command instance.
|
* Create a new command instance.
|
||||||
@@ -57,9 +57,11 @@ class Import extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
Log::debug('Start start-import command');
|
||||||
$jobKey = $this->argument('key');
|
$jobKey = $this->argument('key');
|
||||||
$job = ImportJob::whereKey($jobKey)->first();
|
$job = ImportJob::whereKey($jobKey)->first();
|
||||||
if (!$this->isValid($job)) {
|
if (!$this->isValid($job)) {
|
||||||
|
Log::error('Job is not valid for some reason. Exit.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,6 +13,7 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Console;
|
namespace FireflyIII\Console;
|
||||||
|
|
||||||
|
use FireflyIII\Console\Commands\CreateImport;
|
||||||
use FireflyIII\Console\Commands\EncryptFile;
|
use FireflyIII\Console\Commands\EncryptFile;
|
||||||
use FireflyIII\Console\Commands\Import;
|
use FireflyIII\Console\Commands\Import;
|
||||||
use FireflyIII\Console\Commands\ScanAttachments;
|
use FireflyIII\Console\Commands\ScanAttachments;
|
||||||
@@ -58,6 +59,7 @@ class Kernel extends ConsoleKernel
|
|||||||
UpgradeFireflyInstructions::class,
|
UpgradeFireflyInstructions::class,
|
||||||
VerifyDatabase::class,
|
VerifyDatabase::class,
|
||||||
Import::class,
|
Import::class,
|
||||||
|
CreateImport::class,
|
||||||
EncryptFile::class,
|
EncryptFile::class,
|
||||||
ScanAttachments::class,
|
ScanAttachments::class,
|
||||||
UpgradeDatabase::class,
|
UpgradeDatabase::class,
|
||||||
|
@@ -35,6 +35,9 @@ class ProfileController extends Controller
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
|
View::share('title', trans('firefly.profile'));
|
||||||
|
View::share('mainTitleIcon', 'fa-user');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,7 +66,10 @@ class ProfileController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
return view('profile.index')->with('title', trans('firefly.profile'))->with('subTitle', auth()->user()->email)->with('mainTitleIcon', 'fa-user');
|
$subTitle = auth()->user()->email;
|
||||||
|
$userId = auth()->user()->id;
|
||||||
|
|
||||||
|
return view('profile.index', compact('subTitle', 'userId'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -13,6 +13,7 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
namespace FireflyIII\Import\Converter;
|
namespace FireflyIII\Import\Converter;
|
||||||
|
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use Log;
|
use Log;
|
||||||
@@ -69,11 +70,20 @@ class OpposingAccountIban extends BasicConverter implements ConverterInterface
|
|||||||
return $account;
|
return $account;
|
||||||
}
|
}
|
||||||
|
|
||||||
$account = $repository->store(
|
// the IBAN given may not be a valid IBAN. If not, we cannot store by
|
||||||
['name' => $value, 'iban' => $value, 'user' => $this->user->id, 'accountType' => 'import', 'virtualBalance' => 0, 'active' => true,
|
// iban and we have no opposing account. There should be some kind of fall back
|
||||||
'openingBalance' => 0]
|
// routine.
|
||||||
);
|
try {
|
||||||
$this->setCertainty(100);
|
$account = $repository->store(
|
||||||
|
['name' => $value, 'iban' => $value, 'user' => $this->user->id, 'accountType' => 'import', 'virtualBalance' => 0, 'active' => true,
|
||||||
|
'openingBalance' => 0]
|
||||||
|
);
|
||||||
|
$this->setCertainty(100);
|
||||||
|
} catch (FireflyException $e) {
|
||||||
|
Log::error($e);
|
||||||
|
|
||||||
|
$account = new Account;
|
||||||
|
}
|
||||||
|
|
||||||
return $account;
|
return $account;
|
||||||
}
|
}
|
||||||
|
@@ -59,6 +59,21 @@ class UserRepository implements UserRepositoryInterface
|
|||||||
return $this->all()->count();
|
return $this->all()->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $userId
|
||||||
|
*
|
||||||
|
* @return User
|
||||||
|
*/
|
||||||
|
public function find(int $userId): User
|
||||||
|
{
|
||||||
|
$user = User::find($userId);
|
||||||
|
if (!is_null($user)) {
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new User;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return basic user information.
|
* Return basic user information.
|
||||||
*
|
*
|
||||||
|
@@ -31,6 +31,13 @@ interface UserRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function all(): Collection;
|
public function all(): Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $userId
|
||||||
|
*
|
||||||
|
* @return User
|
||||||
|
*/
|
||||||
|
public function find(int $userId): User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return basic user information.
|
* Return basic user information.
|
||||||
*
|
*
|
||||||
|
@@ -69,6 +69,7 @@ return [
|
|||||||
'no_budget_pointer' => 'You seem to have no budgets yet. You should create some on the <a href="/budgets">budgets</a>-page. Budgets can help you keep track of expenses.',
|
'no_budget_pointer' => 'You seem to have no budgets yet. You should create some on the <a href="/budgets">budgets</a>-page. Budgets can help you keep track of expenses.',
|
||||||
'source_accounts' => 'Source account(s)',
|
'source_accounts' => 'Source account(s)',
|
||||||
'destination_accounts' => 'Destination account(s)',
|
'destination_accounts' => 'Destination account(s)',
|
||||||
|
'user_id_is' => 'Your user id is <strong>:user</strong>',
|
||||||
|
|
||||||
// repeat frequencies:
|
// repeat frequencies:
|
||||||
'repeat_freq_monthly' => 'monthly',
|
'repeat_freq_monthly' => 'monthly',
|
||||||
@@ -669,48 +670,49 @@ return [
|
|||||||
'add_money_to_piggy_title' => 'Add money to piggy bank ":name"',
|
'add_money_to_piggy_title' => 'Add money to piggy bank ":name"',
|
||||||
'remove_money_from_piggy_title' => 'Remove money from piggy bank ":name"',
|
'remove_money_from_piggy_title' => 'Remove money from piggy bank ":name"',
|
||||||
'add' => 'Add',
|
'add' => 'Add',
|
||||||
'remove' => 'Remove',
|
|
||||||
'max_amount_add' => 'The maximum amount you can add is',
|
'remove' => 'Remove',
|
||||||
'max_amount_remove' => 'The maximum amount you can remove is',
|
'max_amount_add' => 'The maximum amount you can add is',
|
||||||
'update_piggy_button' => 'Update piggy bank',
|
'max_amount_remove' => 'The maximum amount you can remove is',
|
||||||
'update_piggy_title' => 'Update piggy bank ":name"',
|
'update_piggy_button' => 'Update piggy bank',
|
||||||
'updated_piggy_bank' => 'Updated piggy bank ":name"',
|
'update_piggy_title' => 'Update piggy bank ":name"',
|
||||||
'details' => 'Details',
|
'updated_piggy_bank' => 'Updated piggy bank ":name"',
|
||||||
'events' => 'Events',
|
'details' => 'Details',
|
||||||
'target_amount' => 'Target amount',
|
'events' => 'Events',
|
||||||
'start_date' => 'Start date',
|
'target_amount' => 'Target amount',
|
||||||
'target_date' => 'Target date',
|
'start_date' => 'Start date',
|
||||||
'no_target_date' => 'No target date',
|
'target_date' => 'Target date',
|
||||||
'todo' => 'to do',
|
'no_target_date' => 'No target date',
|
||||||
'table' => 'Table',
|
'todo' => 'to do',
|
||||||
'piggy_bank_not_exists' => 'Piggy bank no longer exists.',
|
'table' => 'Table',
|
||||||
'add_any_amount_to_piggy' => 'Add money to this piggy bank to reach your target of :amount.',
|
'piggy_bank_not_exists' => 'Piggy bank no longer exists.',
|
||||||
'add_set_amount_to_piggy' => 'Add :amount to fill this piggy bank on :date',
|
'add_any_amount_to_piggy' => 'Add money to this piggy bank to reach your target of :amount.',
|
||||||
'delete_piggy_bank' => 'Delete piggy bank ":name"',
|
'add_set_amount_to_piggy' => 'Add :amount to fill this piggy bank on :date',
|
||||||
'cannot_add_amount_piggy' => 'Could not add :amount to ":name".',
|
'delete_piggy_bank' => 'Delete piggy bank ":name"',
|
||||||
'deleted_piggy_bank' => 'Deleted piggy bank ":name"',
|
'cannot_add_amount_piggy' => 'Could not add :amount to ":name".',
|
||||||
'added_amount_to_piggy' => 'Added :amount to ":name"',
|
'deleted_piggy_bank' => 'Deleted piggy bank ":name"',
|
||||||
'removed_amount_from_piggy' => 'Removed :amount from ":name"',
|
'added_amount_to_piggy' => 'Added :amount to ":name"',
|
||||||
'cannot_remove_amount_piggy' => 'Could not remove :amount from ":name".',
|
'removed_amount_from_piggy' => 'Removed :amount from ":name"',
|
||||||
|
'cannot_remove_amount_piggy' => 'Could not remove :amount from ":name".',
|
||||||
|
|
||||||
// tags
|
// tags
|
||||||
'regular_tag' => 'Just a regular tag.',
|
'regular_tag' => 'Just a regular tag.',
|
||||||
'balancing_act' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
|
'balancing_act' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
|
||||||
'advance_payment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
|
'advance_payment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
|
||||||
'delete_tag' => 'Delete tag ":tag"',
|
'delete_tag' => 'Delete tag ":tag"',
|
||||||
'deleted_tag' => 'Deleted tag ":tag"',
|
'deleted_tag' => 'Deleted tag ":tag"',
|
||||||
'new_tag' => 'Make new tag',
|
'new_tag' => 'Make new tag',
|
||||||
'edit_tag' => 'Edit tag ":tag"',
|
'edit_tag' => 'Edit tag ":tag"',
|
||||||
'updated_tag' => 'Updated tag ":tag"',
|
'updated_tag' => 'Updated tag ":tag"',
|
||||||
'created_tag' => 'Tag ":tag" has been created!',
|
'created_tag' => 'Tag ":tag" has been created!',
|
||||||
'no_year' => 'No year set',
|
'no_year' => 'No year set',
|
||||||
'no_month' => 'No month set',
|
'no_month' => 'No month set',
|
||||||
'tag_title_nothing' => 'Default tags',
|
'tag_title_nothing' => 'Default tags',
|
||||||
'tag_title_balancingAct' => 'Balancing act tags',
|
'tag_title_balancingAct' => 'Balancing act tags',
|
||||||
'tag_title_advancePayment' => 'Advance payment tags',
|
'tag_title_advancePayment' => 'Advance payment tags',
|
||||||
'tags_introduction' => 'Usually tags are singular words, designed to quickly band items together using things like <span class="label label-info">expensive</span>, <span class="label label-info">bill</span> or <span class="label label-info">for-party</span>. In Firefly III, tags can have more properties such as a date, description and location. This allows you to join transactions together in a more meaningful way. For example, you could make a tag called <span class="label label-success"> Christmas dinner with friends</span> and add information about the restaurant. Such tags are "singular", you would only use them for a single occasion, perhaps with multiple transactions.',
|
'tags_introduction' => 'Usually tags are singular words, designed to quickly band items together using things like <span class="label label-info">expensive</span>, <span class="label label-info">bill</span> or <span class="label label-info">for-party</span>. In Firefly III, tags can have more properties such as a date, description and location. This allows you to join transactions together in a more meaningful way. For example, you could make a tag called <span class="label label-success"> Christmas dinner with friends</span> and add information about the restaurant. Such tags are "singular", you would only use them for a single occasion, perhaps with multiple transactions.',
|
||||||
'tags_group' => 'Tags group transactions together, which makes it possible to store reimbursements (in case you front money for others) and other "balancing acts" where expenses are summed up (the payments on your new TV) or where expenses and deposits are cancelling each other out (buying something with saved money). It\'s all up to you. Using tags the old-fashioned way is of course always possible.',
|
'tags_group' => 'Tags group transactions together, which makes it possible to store reimbursements (in case you front money for others) and other "balancing acts" where expenses are summed up (the payments on your new TV) or where expenses and deposits are cancelling each other out (buying something with saved money). It\'s all up to you. Using tags the old-fashioned way is of course always possible.',
|
||||||
'tags_start' => 'Create a tag to get started or enter tags when creating new transactions.',
|
'tags_start' => 'Create a tag to get started or enter tags when creating new transactions.',
|
||||||
|
|
||||||
'transaction_journal_information' => 'Transaction information',
|
'transaction_journal_information' => 'Transaction information',
|
||||||
'transaction_journal_meta' => 'Meta information',
|
'transaction_journal_meta' => 'Meta information',
|
||||||
|
@@ -12,6 +12,9 @@
|
|||||||
<h3 class="box-title">Options</h3>
|
<h3 class="box-title">Options</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
|
<p>
|
||||||
|
{{ trans('firefly.user_id_is',{user: userId})|raw }}
|
||||||
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{{ route('profile.change-password') }}">{{ 'change_your_password'|_ }}</a></li>
|
<li><a href="{{ route('profile.change-password') }}">{{ 'change_your_password'|_ }}</a></li>
|
||||||
<li><a class="text-danger" href="{{ route('profile.delete-account') }}">{{ 'delete_account'|_ }}</a></li>
|
<li><a class="text-danger" href="{{ route('profile.delete-account') }}">{{ 'delete_account'|_ }}</a></li>
|
||||||
|
Reference in New Issue
Block a user