mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2024-12-27 01:11:37 -06:00
First set of data mappers.
This commit is contained in:
parent
57b5981904
commit
162c762973
@ -14,6 +14,7 @@ namespace FireflyIII\Import\Importer;
|
||||
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Crud\Account\AccountCrud;
|
||||
use FireflyIII\Import\Mapper\MapperInterface;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use Illuminate\Http\Request;
|
||||
@ -111,54 +112,18 @@ class CsvImporter implements ImporterInterface
|
||||
*/
|
||||
public function getDataForSettings(): array
|
||||
{
|
||||
$config = $this->job->configuration;
|
||||
$data = [
|
||||
'columns' => [],
|
||||
'columnCount' => 0,
|
||||
];
|
||||
|
||||
if ($this->doColumnRoles()) {
|
||||
|
||||
// show user column role configuration.
|
||||
$content = $this->job->uploadFileContents();
|
||||
|
||||
// create CSV reader.
|
||||
$reader = Reader::createFromString($content);
|
||||
$start = $config['has-headers'] ? 1 : 0;
|
||||
$end = $start + self::EXAMPLE_ROWS; // first X rows
|
||||
|
||||
// collect example data in $data['columns']
|
||||
while ($start < $end) {
|
||||
$row = $reader->fetchOne($start);
|
||||
foreach ($row as $index => $value) {
|
||||
$value = trim($value);
|
||||
if (strlen($value) > 0) {
|
||||
$data['columns'][$index][] = $value;
|
||||
}
|
||||
}
|
||||
$start++;
|
||||
$data['columnCount'] = count($row);
|
||||
}
|
||||
|
||||
// make unique example data
|
||||
foreach ($data['columns'] as $index => $values) {
|
||||
$data['columns'][$index] = array_unique($values);
|
||||
}
|
||||
|
||||
$data['set_roles'] = [];
|
||||
// collect possible column roles:
|
||||
$data['available_roles'] = [];
|
||||
foreach (array_keys(config('csv.import_roles')) as $role) {
|
||||
$data['available_roles'][$role] = trans('csv.column_' . $role);
|
||||
}
|
||||
|
||||
$config['column-count'] = $data['columnCount'];
|
||||
$this->job->configuration = $config;
|
||||
$this->job->save();
|
||||
$data = $this->getDataForColumnRoles();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ($this->doColumnMapping()) {
|
||||
$data = $this->getDataForColumnMapping();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
echo 'no settings to do.';
|
||||
exit;
|
||||
@ -176,6 +141,11 @@ class CsvImporter implements ImporterInterface
|
||||
if ($this->doColumnRoles()) {
|
||||
return 'import.csv.roles';
|
||||
}
|
||||
|
||||
if ($this->doColumnMapping()) {
|
||||
return 'import.csv.map';
|
||||
}
|
||||
|
||||
echo 'no view for settings';
|
||||
exit;
|
||||
}
|
||||
@ -269,6 +239,14 @@ class CsvImporter implements ImporterInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function doColumnMapping(): bool
|
||||
{
|
||||
return $this->job->configuration['column-mapping-complete'] === false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
@ -276,4 +254,94 @@ class CsvImporter implements ImporterInterface
|
||||
{
|
||||
return $this->job->configuration['column-roles-complete'] === false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getDataForColumnMapping(): array
|
||||
{
|
||||
$config = $this->job->configuration;
|
||||
$data = [];
|
||||
|
||||
foreach ($config['column-do-mapping'] as $index => $mustBeMapped) {
|
||||
if ($mustBeMapped) {
|
||||
$column = $config['column-roles'][$index] ?? '_ignore';
|
||||
$canBeMapped = config('csv.import_roles.' . $column . '.mappable');
|
||||
if ($canBeMapped) {
|
||||
$mapperName = '\FireflyIII\Import\Mapper\\' . config('csv.import_roles.' . $column . '.mapper');
|
||||
/** @var MapperInterface $mapper */
|
||||
$mapper = new $mapperName;
|
||||
$data[$index] = [
|
||||
'name' => $column,
|
||||
'mapper' => $mapperName,
|
||||
'options' => $mapper->getMap(),
|
||||
'values' => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
echo '<pre>';
|
||||
var_dump($data);
|
||||
var_dump($config);
|
||||
|
||||
|
||||
exit;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getDataForColumnRoles():array
|
||||
{
|
||||
$config = $this->job->configuration;
|
||||
$data = [
|
||||
'columns' => [],
|
||||
'columnCount' => 0,
|
||||
];
|
||||
|
||||
// show user column role configuration.
|
||||
$content = $this->job->uploadFileContents();
|
||||
|
||||
// create CSV reader.
|
||||
$reader = Reader::createFromString($content);
|
||||
$start = $config['has-headers'] ? 1 : 0;
|
||||
$end = $start + self::EXAMPLE_ROWS; // first X rows
|
||||
|
||||
// collect example data in $data['columns']
|
||||
while ($start < $end) {
|
||||
$row = $reader->fetchOne($start);
|
||||
foreach ($row as $index => $value) {
|
||||
$value = trim($value);
|
||||
if (strlen($value) > 0) {
|
||||
$data['columns'][$index][] = $value;
|
||||
}
|
||||
}
|
||||
$start++;
|
||||
$data['columnCount'] = count($row);
|
||||
}
|
||||
|
||||
// make unique example data
|
||||
foreach ($data['columns'] as $index => $values) {
|
||||
$data['columns'][$index] = array_unique($values);
|
||||
}
|
||||
|
||||
$data['set_roles'] = [];
|
||||
// collect possible column roles:
|
||||
$data['available_roles'] = [];
|
||||
foreach (array_keys(config('csv.import_roles')) as $role) {
|
||||
$data['available_roles'][$role] = trans('csv.column_' . $role);
|
||||
}
|
||||
|
||||
$config['column-count'] = $data['columnCount'];
|
||||
$this->job->configuration = $config;
|
||||
$this->job->save();
|
||||
|
||||
return $data;
|
||||
|
||||
|
||||
}
|
||||
}
|
53
app/Import/Mapper/AssetAccounts.php
Normal file
53
app/Import/Mapper/AssetAccounts.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* AssetAccounts.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Mapper;
|
||||
|
||||
use FireflyIII\Crud\Account\AccountCrudInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
|
||||
/**
|
||||
* Class AssetAccounts
|
||||
*
|
||||
* @package FireflyIII\Import\Mapper
|
||||
*/
|
||||
class AssetAccounts implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap(): array
|
||||
{
|
||||
/** @var AccountCrudInterface $crud */
|
||||
$crud = app(AccountCrudInterface::class);
|
||||
$set = $crud->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
$list = [];
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($set as $account) {
|
||||
$name = $account->name;
|
||||
$iban = $account->iban ?? '';
|
||||
if (strlen($iban) > 0) {
|
||||
$name .= ' (' . $account->iban . ')';
|
||||
}
|
||||
$list[$account->id] = $name;
|
||||
}
|
||||
|
||||
asort($list);
|
||||
|
||||
$list = [0 => trans('csv.do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
|
||||
}
|
||||
}
|
26
app/Import/Mapper/MapperInterface.php
Normal file
26
app/Import/Mapper/MapperInterface.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* MapperInterface.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Mapper;
|
||||
|
||||
/**
|
||||
* Interface MapperInterface
|
||||
*
|
||||
* @package FireflyIII\Import\Mapper
|
||||
*/
|
||||
interface MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap(): array;
|
||||
}
|
57
app/Import/Mapper/OpposingAccounts.php
Normal file
57
app/Import/Mapper/OpposingAccounts.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* OpposingAccounts.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Mapper;
|
||||
|
||||
use FireflyIII\Crud\Account\AccountCrudInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
|
||||
/**
|
||||
* Class OpposingAccounts
|
||||
*
|
||||
* @package FireflyIII\Import\Mapper
|
||||
*/
|
||||
class OpposingAccounts implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap(): array
|
||||
{
|
||||
/** @var AccountCrudInterface $crud */
|
||||
$crud = app(AccountCrudInterface::class);
|
||||
$set = $crud->getAccountsByType(
|
||||
[
|
||||
AccountType::DEFAULT, AccountType::ASSET,
|
||||
AccountType::EXPENSE, AccountType::BENEFICIARY,
|
||||
AccountType::REVENUE
|
||||
]);
|
||||
$list = [];
|
||||
|
||||
/** @var Account $account */
|
||||
foreach ($set as $account) {
|
||||
$name = $account->name;
|
||||
$iban = $account->iban ?? '';
|
||||
if (strlen($iban) > 0) {
|
||||
$name .= ' (' . $account->iban . ')';
|
||||
}
|
||||
$list[$account->id] = $name;
|
||||
}
|
||||
|
||||
asort($list);
|
||||
|
||||
$list = [0 => trans('csv.do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
42
app/Import/Mapper/TransactionCurrencies.php
Normal file
42
app/Import/Mapper/TransactionCurrencies.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* TransactionCurrencies.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Import\Mapper;
|
||||
|
||||
use FireflyIII\Models\TransactionCurrency as TC;
|
||||
|
||||
/**
|
||||
* Class TransactionCurrencies
|
||||
*
|
||||
* @package FireflyIII\Import\Mapper
|
||||
*/
|
||||
class TransactionCurrencies implements MapperInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap(): array
|
||||
{
|
||||
$currencies = TC::get();
|
||||
$list = [];
|
||||
foreach ($currencies as $currency) {
|
||||
$list[$currency->id] = $currency->name . ' (' . $currency->code . ')';
|
||||
}
|
||||
|
||||
asort($list);
|
||||
|
||||
$list = [0 => trans('csv.do_not_map')] + $list;
|
||||
|
||||
return $list;
|
||||
|
||||
}
|
||||
}
|
@ -13,6 +13,8 @@ namespace FireflyIII\Models;
|
||||
|
||||
use Auth;
|
||||
use Crypt;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@ -183,10 +185,14 @@ class Account extends Model
|
||||
*/
|
||||
public function getIbanAttribute($value): string
|
||||
{
|
||||
if (is_null($value)) {
|
||||
if (is_null($value) || strlen(strval($value)) === 0) {
|
||||
return '';
|
||||
}
|
||||
$result = Crypt::decrypt($value);
|
||||
try {
|
||||
$result = Crypt::decrypt($value);
|
||||
} catch (DecryptException $e) {
|
||||
throw new FireflyException('Cannot decrypt value "' . $value . '" for account #' . $this->id);
|
||||
}
|
||||
if (is_null($result)) {
|
||||
return '';
|
||||
}
|
||||
|
@ -25,37 +25,37 @@ return [
|
||||
'mappable' => false,
|
||||
'field' => 'bill',
|
||||
'converter' => 'BillId',
|
||||
'mapper' => 'Bill',
|
||||
'mapper' => 'Bills',
|
||||
],
|
||||
'bill-name' => [
|
||||
'mappable' => true,
|
||||
'converter' => 'BillName',
|
||||
'field' => 'bill',
|
||||
'mapper' => 'Bill',
|
||||
'mapper' => 'Bills',
|
||||
],
|
||||
'currency-id' => [
|
||||
'mappable' => true,
|
||||
'converter' => 'CurrencyId',
|
||||
'field' => 'currency',
|
||||
'mapper' => 'TransactionCurrency'
|
||||
'mapper' => 'TransactionCurrencies'
|
||||
],
|
||||
'currency-name' => [
|
||||
'mappable' => true,
|
||||
'converter' => 'CurrencyName',
|
||||
'field' => 'currency',
|
||||
'mapper' => 'TransactionCurrency'
|
||||
'mapper' => 'TransactionCurrencies'
|
||||
],
|
||||
'currency-code' => [
|
||||
'mappable' => true,
|
||||
'converter' => 'CurrencyCode',
|
||||
'field' => 'currency',
|
||||
'mapper' => 'TransactionCurrency'
|
||||
'mapper' => 'TransactionCurrencies'
|
||||
],
|
||||
'currency-symbol' => [
|
||||
'mappable' => true,
|
||||
'converter' => 'CurrencySymbol',
|
||||
'field' => 'currency',
|
||||
'mapper' => 'TransactionCurrency'
|
||||
'mapper' => 'TransactionCurrencies'
|
||||
],
|
||||
'description' => [
|
||||
'mappable' => false,
|
||||
@ -76,13 +76,13 @@ return [
|
||||
'mappable' => true,
|
||||
'converter' => 'BudgetId',
|
||||
'field' => 'budget',
|
||||
'mapper' => 'Budget',
|
||||
'mapper' => 'Budgets',
|
||||
],
|
||||
'budget-name' => [
|
||||
'mappable' => true,
|
||||
'converter' => 'BudgetName',
|
||||
'field' => 'budget',
|
||||
'mapper' => 'Budget',
|
||||
'mapper' => 'Budgets',
|
||||
],
|
||||
'rabo-debet-credit' => [
|
||||
'mappable' => false,
|
||||
@ -98,73 +98,73 @@ return [
|
||||
'mappable' => true,
|
||||
'converter' => 'CategoryId',
|
||||
'field' => 'category',
|
||||
'mapper' => 'Category',
|
||||
'mapper' => 'Categories',
|
||||
],
|
||||
'category-name' => [
|
||||
'mappable' => true,
|
||||
'converter' => 'CategoryName',
|
||||
'field' => 'category',
|
||||
'mapper' => 'Category',
|
||||
'mapper' => 'Categories',
|
||||
],
|
||||
'tags-comma' => [
|
||||
'mappable' => true,
|
||||
'field' => 'tags',
|
||||
'converter' => 'TagsComma',
|
||||
'mapper' => 'Tag',
|
||||
'mapper' => 'Tags',
|
||||
],
|
||||
'tags-space' => [
|
||||
'mappable' => true,
|
||||
'field' => 'tags',
|
||||
'converter' => 'TagsSpace',
|
||||
'mapper' => 'Tag',
|
||||
'mapper' => 'Tags',
|
||||
],
|
||||
'account-id' => [
|
||||
'mappable' => true,
|
||||
'mapper' => 'AssetAccount',
|
||||
'mapper' => 'AssetAccountId',
|
||||
'field' => 'asset-account-id',
|
||||
'converter' => 'AccountId'
|
||||
'converter' => 'AssetAccounts'
|
||||
],
|
||||
'account-name' => [
|
||||
'mappable' => true,
|
||||
'mapper' => 'AssetAccount',
|
||||
'mapper' => 'AssetAccountName',
|
||||
'field' => 'asset-account-name',
|
||||
'converter' => 'AssetAccountName'
|
||||
'converter' => 'AssetAccounts'
|
||||
],
|
||||
'account-iban' => [
|
||||
'mappable' => true,
|
||||
'converter' => 'AssetAccountIban',
|
||||
'field' => 'asset-account-iban',
|
||||
'mapper' => 'AssetAccount'
|
||||
'mapper' => 'AssetAccounts'
|
||||
],
|
||||
'account-number' => [
|
||||
'mappable' => true,
|
||||
'converter' => 'AssetAccountNumber',
|
||||
'field' => 'asset-account-number',
|
||||
'mapper' => 'AssetAccount'
|
||||
'mapper' => 'AssetAccounts'
|
||||
],
|
||||
'opposing-id' => [
|
||||
'mappable' => true,
|
||||
'field' => 'opposing-account-id',
|
||||
'converter' => 'OpposingAccountId',
|
||||
'mapper' => 'AnyAccount',
|
||||
'mapper' => 'OpposingAccounts',
|
||||
],
|
||||
'opposing-name' => [
|
||||
'mappable' => true,
|
||||
'field' => 'opposing-account-name',
|
||||
'converter' => 'OpposingAccountName',
|
||||
'mapper' => 'AnyAccount',
|
||||
'mapper' => 'OpposingAccounts',
|
||||
],
|
||||
'opposing-iban' => [
|
||||
'mappable' => true,
|
||||
'field' => 'opposing-account-iban',
|
||||
'converter' => 'OpposingAccountIban',
|
||||
'mapper' => 'AnyAccount',
|
||||
'mapper' => 'OpposingAccounts',
|
||||
],
|
||||
'opposing-number' => [
|
||||
'mappable' => true,
|
||||
'field' => 'opposing-account-number',
|
||||
'converter' => 'OpposingAccountNumber',
|
||||
'mapper' => 'AnyAccount',
|
||||
'mapper' => 'OpposingAccounts',
|
||||
],
|
||||
'amount' => [
|
||||
'mappable' => false,
|
||||
|
@ -32,6 +32,7 @@ return [
|
||||
'column' => 'Column',
|
||||
'no_example_data' => 'No example data available',
|
||||
'store_column_roles' => 'Continue import',
|
||||
'do_not_map' => '(do not map)',
|
||||
|
||||
'column__ignore' => '(ignore this column)',
|
||||
'column_account-iban' => 'Asset account (IBAN)',
|
||||
|
84
resources/views/import/csv/map.twig
Normal file
84
resources/views/import/csv/map.twig
Normal file
@ -0,0 +1,84 @@
|
||||
{% extends "./layout/default.twig" %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ trans('csv.map_title') }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<p>
|
||||
{{ trans('csv.map_text') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<form action="{{ route('import.postSettings', job.key) }}" method="post">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
|
||||
|
||||
{#
|
||||
|
||||
{% for index,columnName in map %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ Config.get('csv.roles.'~columnName~'.name') }}</h3>
|
||||
</div>
|
||||
<div class="box-body no-padding">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:50%;">{{ 'csv_field_value'|_ }}</th>
|
||||
<th>{{ 'csv_field_mapped_to'|_ }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for value in values[index] %}
|
||||
<tr>
|
||||
<td><code>{{ value }}</code></td>
|
||||
<td>
|
||||
{{ Form.select('mapping['~index~']['~value~']',options[index], mapped[index][value], {class: 'form-control'}) }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
#}
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="box">
|
||||
<div class="box-body">
|
||||
<button type="submit" class="btn btn-success pull-right">
|
||||
{{ trans('csv.store_column_mapping') }} <i class="fa fa-arrow-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in New Issue
Block a user