Import fix asset account.

This commit is contained in:
James Cole
2015-07-09 16:37:42 +02:00
parent 18b8a05014
commit 28f601b54b
8 changed files with 246 additions and 24 deletions

View File

@@ -25,16 +25,19 @@ class Data
protected $hasHeaders; protected $hasHeaders;
/** @var array */ /** @var array */
protected $map; protected $map = [];
/** @var array */ /** @var array */
protected $mapped; protected $mapped = [];
/** @var Reader */ /** @var Reader */
protected $reader; protected $reader;
/** @var array */ /** @var array */
protected $roles; protected $roles = [];
/** @var array */ /** @var array */
protected $specifix; protected $specifix = [];
/** @var int */
protected $importAccount = 0;
/** /**
* *
@@ -48,6 +51,7 @@ class Data
$this->sessionRoles(); $this->sessionRoles();
$this->sessionMapped(); $this->sessionMapped();
$this->sessionSpecifix(); $this->sessionSpecifix();
$this->sessionImportAccount();
} }
protected function sessionHasHeaders() protected function sessionHasHeaders()
@@ -57,6 +61,13 @@ class Data
} }
} }
protected function sessionImportAccount()
{
if (Session::has('csv-import-account')) {
$this->importAccount = intval(Session::get('csv-import-account'));
}
}
protected function sessionDateFormat() protected function sessionDateFormat()
{ {
if (Session::has('csv-date-format')) { if (Session::has('csv-date-format')) {
@@ -116,6 +127,15 @@ class Data
$this->dateFormat = $dateFormat; $this->dateFormat = $dateFormat;
} }
/**
* @param int $importAccount
*/
public function setImportAccount($importAccount)
{
Session::put('csv-import-account', $importAccount);
$this->importAccount = $importAccount;
}
/** /**
* @return bool * @return bool
*/ */

View File

@@ -171,6 +171,7 @@ class Importer
// some extra's: // some extra's:
$filler['bill-id'] = null; $filler['bill-id'] = null;
$filler['opposing-account-object'] = null; $filler['opposing-account-object'] = null;
$filler['asset-account-object'] = null;
$filler['amount-modifier'] = '1'; $filler['amount-modifier'] = '1';
return $filler; return $filler;
@@ -241,7 +242,7 @@ class Importer
$date = $this->importData['date-rent']; $date = $this->importData['date-rent'];
} }
if (!($this->importData['asset-account'] instanceof Account)) { if (!($this->importData['asset-account-object'] instanceof Account)) {
return 'No asset account to import into.'; return 'No asset account to import into.';
} }
@@ -252,10 +253,13 @@ class Importer
'description' => $this->importData['description'], 'completed' => 0, 'date' => $date, 'bill_id' => $this->importData['bill-id'],] 'description' => $this->importData['description'], 'completed' => 0, 'date' => $date, 'bill_id' => $this->importData['bill-id'],]
); );
if ($journal->getErrors()->count() == 0) { if ($journal->getErrors()->count() == 0) {
$accountId = $this->importData['asset-account']->id; // create first transaction: // first transaction
$accountId = $this->importData['asset-account-object']->id; // create first transaction:
$amount = $this->importData['amount']; $amount = $this->importData['amount'];
$transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]); $transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]);
$errors = $transaction->getErrors(); $errors = $transaction->getErrors();
// second transaction
$accountId = $this->importData['opposing-account-object']->id; // create second transaction: $accountId = $this->importData['opposing-account-object']->id; // create second transaction:
$amount = bcmul($this->importData['amount'], -1); $amount = bcmul($this->importData['amount'], -1);
$transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]); $transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]);

View File

@@ -0,0 +1,185 @@
<?php
namespace FireflyIII\Helpers\Csv\PostProcessing;
use Auth;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use Log;
use Validator;
/**
* Class AssetAccount
*
* @package FireflyIII\Helpers\Csv\PostProcessing
*/
class AssetAccount implements PostProcessorInterface
{
/** @var array */
protected $data;
/**
* @return array
*/
public function process()
{
$result = $this->checkIdNameObject(); // has object in ID or Name?
if (!is_null($result)) {
return $result;
}
$result = $this->checkIbanString();
if (!is_null($result)) {
return $result;
}
$result = $this->checkNameString();
if (!is_null($result)) {
return $result;
}
return null;
}
/**
* @param array $data
*/
public function setData(array $data)
{
$this->data = $data;
}
/**
* @return array
*/
protected function checkIdNameObject()
{
if ($this->data['asset-account-id'] instanceof Account) { // first priority. try to find the account based on ID, if any
$this->data['asset-account-object'] = $this->data['asset-account-id'];
return $this->data;
}
if ($this->data['asset-account-iban'] instanceof Account) { // second: try to find the account based on IBAN, if any.
$this->data['asset-account-object'] = $this->data['asset-account-iban'];
return $this->data;
}
return null;
}
/**
* @return array|null
*/
protected function checkIbanString()
{
$rules = ['iban' => 'iban'];
$check = ['iban' => $this->data['asset-account-iban']];
$validator = Validator::make($check, $rules);
if (!$validator->fails()) {
$this->data['asset-account-object'] = $this->parseIbanString();
return $this->data;
}
return null;
}
/**
* @return Account|null
*/
protected function parseIbanString()
{
// create by name and/or iban.
$accounts = Auth::user()->accounts()->get();
foreach ($accounts as $entry) {
if ($entry->iban == $this->data['asset-account-iban']) {
return $entry;
}
}
$account = $this->createAccount();
return $account;
}
/**
* @return Account|null
*/
protected function createAccount()
{
$accountType = $this->getAccountType();
// create if not exists:
$name = is_string($this->data['asset-account-name']) && strlen($this->data['asset-account-name']) > 0 ? $this->data['asset-account-name']
: $this->data['asset-account-iban'];
$account = Account::firstOrCreateEncrypted(
[
'user_id' => Auth::user()->id,
'account_type_id' => $accountType->id,
'name' => $name,
'iban' => $this->data['asset-account-iban'],
'active' => true,
]
);
return $account;
}
/**
*
* @return AccountType
*/
protected function getAccountType()
{
return AccountType::where('type', 'Asset account')->first();
}
/**
* @return array|null
*/
protected function checkNameString()
{
if ($this->data['asset-account-name'] instanceof Account) { // third: try to find account based on name, if any.
$this->data['asset-account-object'] = $this->data['asset-account-name'];
return $this->data;
}
if (is_string($this->data['asset-account-name'])) {
$this->data['asset-account-object'] = $this->parseNameString();
return $this->data;
}
return null;
}
/**
* @return Account|null
*/
protected function parseNameString()
{
$accountType = $this->getAccountType();
$accounts = Auth::user()->accounts()->where('account_type_id', $accountType->id)->get();
foreach ($accounts as $entry) {
if ($entry->name == $this->data['asset-account-name']) {
Log::debug('Found an asset account with this name (#' . $entry->id . ': ' . $entry->name . ')');
return $entry;
}
}
// create if not exists:
$account = Account::firstOrCreateEncrypted(
[
'user_id' => Auth::user()->id,
'account_type_id' => $accountType->id,
'name' => $this->data['asset-account-name'],
'iban' => '',
'active' => true,
]
);
return $account;
}
}

View File

@@ -3,10 +3,12 @@
namespace FireflyIII\Http\Controllers; namespace FireflyIII\Http\Controllers;
use Config; use Config;
use ExpandedForm;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Csv\Data; use FireflyIII\Helpers\Csv\Data;
use FireflyIII\Helpers\Csv\Importer; use FireflyIII\Helpers\Csv\Importer;
use FireflyIII\Helpers\Csv\WizardInterface; use FireflyIII\Helpers\Csv\WizardInterface;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Input; use Input;
use Log; use Log;
@@ -55,7 +57,7 @@ class CsvController extends Controller
public function columnRoles() public function columnRoles()
{ {
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers']; $fields = ['csv-file', 'csv-date-format', 'csv-has-headers','csv-import-account'];
if (!$this->wizard->sessionHasValues($fields)) { if (!$this->wizard->sessionHasValues($fields)) {
Session::flash('warning', 'Could not recover upload.'); Session::flash('warning', 'Could not recover upload.');
@@ -142,13 +144,14 @@ class CsvController extends Controller
* *
* @return \Illuminate\View\View * @return \Illuminate\View\View
*/ */
public function index() public function index(AccountRepositoryInterface $repository)
{ {
$subTitle = trans('firefly.csv_import'); $subTitle = trans('firefly.csv_import');
Session::forget('csv-date-format'); Session::forget('csv-date-format');
Session::forget('csv-has-headers'); Session::forget('csv-has-headers');
Session::forget('csv-file'); Session::forget('csv-file');
Session::forget('csv-import-account');
Session::forget('csv-map'); Session::forget('csv-map');
Session::forget('csv-roles'); Session::forget('csv-roles');
Session::forget('csv-mapped'); Session::forget('csv-mapped');
@@ -160,11 +163,14 @@ class CsvController extends Controller
$specifix[$entry] = trans('firefly.csv_specifix_' . $entry); $specifix[$entry] = trans('firefly.csv_specifix_' . $entry);
} }
// get a list of asset accounts:
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Asset account', 'Default account']));
// can actually upload? // can actually upload?
$uploadPossible = is_writable(storage_path('upload')); $uploadPossible = is_writable(storage_path('upload'));
$path = storage_path('upload'); $path = storage_path('upload');
return view('csv.index', compact('subTitle', 'uploadPossible', 'path', 'specifix')); return view('csv.index', compact('subTitle', 'uploadPossible', 'path', 'specifix', 'accounts'));
} }
/** /**
@@ -366,19 +372,17 @@ class CsvController extends Controller
return redirect(route('csv.index')); return redirect(route('csv.index'));
} }
$fullPath = $this->wizard->storeCsvFile($request->file('csv')->getRealPath()); $fullPath = $this->wizard->storeCsvFile($request->file('csv')->getRealPath());
$settings = []; $settings = [];
$settings['date-format'] = Input::get('date_format'); $settings['date-format'] = Input::get('date_format');
$settings['has-headers'] = intval(Input::get('has_headers')) === 1; $settings['has-headers'] = intval(Input::get('has_headers')) === 1;
$settings['specifix'] = Input::get('specifix'); $settings['specifix'] = Input::get('specifix');
$settings['map'] = []; $settings['import-account'] = intval(Input::get('csv_import_account'));
$settings['mapped'] = []; $settings['map'] = [];
$settings['roles'] = []; $settings['mapped'] = [];
$settings['roles'] = [];
/* if ($request->hasFile('csv_config')) { // Process config file if present.
* Process config file if present.
*/
if ($request->hasFile('csv_config')) {
$data = file_get_contents($request->file('csv_config')->getRealPath()); $data = file_get_contents($request->file('csv_config')->getRealPath());
$json = json_decode($data, true); $json = json_decode($data, true);
if (is_array($json)) { if (is_array($json)) {
@@ -393,6 +397,7 @@ class CsvController extends Controller
$this->data->setMapped($settings['mapped']); $this->data->setMapped($settings['mapped']);
$this->data->setRoles($settings['roles']); $this->data->setRoles($settings['roles']);
$this->data->setSpecifix($settings['specifix']); $this->data->setSpecifix($settings['specifix']);
$this->data->setImportAccount($settings['import-account']);
return redirect(route('csv.column-roles')); return redirect(route('csv.column-roles'));

View File

@@ -131,21 +131,21 @@ return [
'name' => 'Asset account ID (matching Firefly)', 'name' => 'Asset account ID (matching Firefly)',
'mappable' => true, 'mappable' => true,
'mapper' => 'AssetAccount', 'mapper' => 'AssetAccount',
'field' => 'asset-account', 'field' => 'asset-account-id',
'converter' => 'AccountId' 'converter' => 'AccountId'
], ],
'account-name' => [ 'account-name' => [
'name' => 'Asset account name', 'name' => 'Asset account name',
'mappable' => true, 'mappable' => true,
'mapper' => 'AssetAccount', 'mapper' => 'AssetAccount',
'field' => 'asset-account', 'field' => 'asset-account-name',
'converter' => 'AssetAccountName' 'converter' => 'AssetAccountName'
], ],
'account-iban' => [ 'account-iban' => [
'name' => 'Asset account IBAN', 'name' => 'Asset account IBAN',
'mappable' => true, 'mappable' => true,
'converter' => 'AssetAccountIban', 'converter' => 'AssetAccountIban',
'field' => 'asset-account', 'field' => 'asset-account-iban',
'mapper' => 'AssetAccount' 'mapper' => 'AssetAccount'
], ],
'opposing-id' => [ 'opposing-id' => [

View File

@@ -117,6 +117,9 @@ return [
'csv_column_tags-space' => 'Tags (space separated)', 'csv_column_tags-space' => 'Tags (space separated)',
'csv_specifix_RabobankDescription' => 'Select this when you\'re importing Rabobank CSV export files.', 'csv_specifix_RabobankDescription' => 'Select this when you\'re importing Rabobank CSV export files.',
'csv_specifix_Dummy' => 'Checking this has no effect whatsoever.', 'csv_specifix_Dummy' => 'Checking this has no effect whatsoever.',
'csv_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.',
// create new stuff: // create new stuff:
'create_new_withdrawal' => 'Create new withdrawal', 'create_new_withdrawal' => 'Create new withdrawal',

View File

@@ -51,6 +51,7 @@ return [
'date_format' => 'Date format', 'date_format' => 'Date format',
'csv_config' => 'CSV import configuration', 'csv_config' => 'CSV import configuration',
'specifix' => 'Bank- or file specific fixes', 'specifix' => 'Bank- or file specific fixes',
'csv_import_account' => 'Default import account',
'store_new_withdrawal' => 'Store new withdrawal', 'store_new_withdrawal' => 'Store new withdrawal',
'store_new_deposit' => 'Store new deposit', 'store_new_deposit' => 'Store new deposit',

View File

@@ -61,8 +61,12 @@
{{ ExpandedForm.file('csv_config',{helpText: 'csv_csv_config_file_help'|_}) }} {{ ExpandedForm.file('csv_config',{helpText: 'csv_csv_config_file_help'|_}) }}
{{ ExpandedForm.select('csv_import_account', accounts, 0, {helpText: 'csv_import_account_help'|_} ) }}
{{ ExpandedForm.multiCheckbox('specifix', specifix) }} {{ ExpandedForm.multiCheckbox('specifix', specifix) }}
{% if not uploadPossible %} {% if not uploadPossible %}
<div class="form-group" id="csv_holder"> <div class="form-group" id="csv_holder">
<div class="col-sm-4"> <div class="col-sm-4">