Merge pull request #146 from roberthorlings/feature/abn-amro-import-specifix

ABN AMRO Specifix
This commit is contained in:
James Cole
2016-01-19 08:36:06 +01:00
5 changed files with 213 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
<?php
namespace FireflyIII\Helpers\Csv\Converter;
use FireflyIII\Models\Account;
/**
* Class AmountComma
*
* Parses the input as the amount with a comma as decimal separator
*
* @package FireflyIII\Helpers\Csv\Converter
*/
class AmountComma extends BasicConverter implements ConverterInterface
{
/**
* @return Account|null
*/
public function convert()
{
$value = str_replace(",", ".", $this->value );
if (is_numeric($value)) {
return floatval($value);
}
return 0;
}
}

View File

@@ -0,0 +1,172 @@
<?php
namespace FireflyIII\Helpers\Csv\Specifix;
use Log;
/**
* Parses the description from txt files for ABN AMRO bank accounts.
*
* Based on the logic as described in the following Gist:
* https://gist.github.com/vDorst/68d555a6a90f62fec004
*
* @package FireflyIII\Helpers\Csv\Specifix
*/
class AbnAmroDescription
{
/** @var array */
protected $data;
/** @var array */
protected $row;
/**
* @return array
*/
public function fix()
{
// Try to parse the description in known formats.
$parsed = $this->parseSepaDescription() || $this->parseTRTPDescription() || $this->parseGEABEADescription() || $this->parseABNAMRODescription();
// If the description could not be parsed, specify an unknown opposing
// account, as an opposing account is required
if( !$parsed ) {
$this->data[ "opposing-account-name" ] = trans('firefly.unknown');
}
return $this->data;
}
/**
* @param array $data
*/
public function setData($data)
{
$this->data = $data;
}
/**
* @param array $row
*/
public function setRow($row)
{
$this->row = $row;
}
/**
* Parses the current description in SEPA format
* @return boolean true if the description is SEPA format, false otherwise
*/
protected function parseSepaDescription()
{
// See if the current description is formatted as a SEPA plain description
if( preg_match( "/^SEPA(.{28})/", $this->data[ "description" ], $matches ) ) {
Log::debug('AbnAmroSpecifix: Description is structured as SEPA plain description.');
$type = trim($matches[1]);
// SEPA plain descriptions contain several key-value pairs, split by a colon
preg_match_all( "/([A-Za-z]+(?=:\s)):\s([A-Za-z 0-9._#-]+(?=\s))/", $this->data[ "description" ], $matches, PREG_SET_ORDER );
foreach( $matches as $match ) {
$key = $match[1];
$value = trim($match[2]);
switch( strtoupper($key) ) {
case 'OMSCHRIJVING':
$this->data['description'] = $value;
break;
case 'NAAM':
$this->data['opposing-account-name'] = $value;
break;
case 'IBAN':
$this->data['opposing-account-iban'] = $value;
break;
default:
// Ignore the rest
}
}
return true;
}
return false;
}
/**
* Parses the current description in TRTP format
* @return boolean true if the description is TRTP format, false otherwise
*/
protected function parseTRTPDescription()
{
// See if the current description is formatted in TRTP format
if( preg_match_all( "!\/([A-Z]{3,4})\/([^/]*)!", $this->data[ "description" ], $matches, PREG_SET_ORDER ) ) {
Log::debug('AbnAmroSpecifix: Description is structured as TRTP format.');
foreach( $matches as $match ) {
$key = $match[1];
$value = trim($match[2]);
switch( strtoupper($key) ) {
case 'TRTP':
$type = $value;
break;
case 'NAME':
$this->data['opposing-account-name'] = $value;
break;
case 'REMI':
$this->data['description'] = $value;
break;
case 'IBAN':
$this->data['opposing-account-iban'] = $value;
break;
default:
// Ignore the rest
}
}
return true;
}
return false;
}
/**
* Parses the current description in GEA/BEA format
* @return boolean true if the description is GEA/BEAformat, false otherwise
*/
protected function parseGEABEADescription()
{
// See if the current description is formatted in GEA/BEA format
if( preg_match( "/([BG]EA) +(NR:[a-zA-Z:0-9]+) +([0-9.\/]+) +([^,]*)/", $this->data[ "description" ], $matches ) ) {
Log::debug('AbnAmroSpecifix: Description is structured as GEA or BEA format.');
$this->data[ "opposing-account-name" ] = $matches[4];
$this->data[ "description" ] = $matches[4];
return true;
}
return false;
}
/**
* Parses the current description with costs from ABN AMRO itself
* @return boolean true if the description is GEA/BEAformat, false otherwise
*/
protected function parseABNAMRODescription()
{
// See if the current description is formatted in ABN AMRO format
if( preg_match( "/ABN AMRO.{24} (.*)/", $this->data[ "description" ], $matches ) ) {
Log::debug('AbnAmroSpecifix: Description is structured as costs from ABN AMRO itself.');
$this->data[ "opposing-account-name" ] = "ABN AMRO";
$this->data[ "description" ] = $matches[1];
return true;
}
return false;
}
}

View File

@@ -2,6 +2,7 @@
return [
'specifix' => [
'RabobankDescription',
'AbnAmroDescription',
'Dummy'
],
'post_processors' => [
@@ -176,6 +177,12 @@ return [
'converter' => 'Amount',
'field' => 'amount',
],
'amount-comma-separated' => [
'name' => 'Amount (comma as decimal separator)',
'mappable' => false,
'converter' => 'AmountComma',
'field' => 'amount',
],
'sepa-ct-id' => [
'name' => 'SEPA Credit Transfer end-to-end ID',
'mappable' => false,

View File

@@ -257,6 +257,7 @@ return [
'csv_column_account-id' => 'Asset account ID (matching Firefly)',
'csv_column_account-name' => 'Asset account (name)',
'csv_column_amount' => 'Amount',
'csv_column_amount-comma-separated' => 'Amount (comma as decimal separator)',
'csv_column_bill-id' => 'Bill ID (matching Firefly)',
'csv_column_bill-name' => 'Bill name',
'csv_column_budget-id' => 'Budget ID (matching Firefly)',
@@ -280,6 +281,7 @@ return [
'csv_column_tags-comma' => 'Tags (comma separated)',
'csv_column_tags-space' => 'Tags (space separated)',
'csv_specifix_RabobankDescription' => 'Select this when you\'re importing Rabobank CSV export files.',
'csv_specifix_AbnAmroDescription' => 'Select this when you\'re importing ABN AMRO CSV export files.',
'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.',
'csv_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',

View File

@@ -257,6 +257,7 @@ return [
'csv_column_account-id' => 'Betaalrekening (ID gelijk aan Firefly)',
'csv_column_account-name' => 'Betaalrekeningnaam',
'csv_column_amount' => 'Bedrag',
'csv_column_amount-comma-separated' => 'Bedrag (komma as decimaalscheidingsteken)',
'csv_column_bill-id' => 'Contract (ID gelijk aan Firefly)',
'csv_column_bill-name' => 'Contractnaam',
'csv_column_budget-id' => 'Budget (ID gelijk aan Firefly)',
@@ -280,6 +281,7 @@ return [
'csv_column_tags-comma' => 'Tags (kommagescheiden)',
'csv_column_tags-space' => 'Tags (spatiegescheiden)',
'csv_specifix_RabobankDescription' => 'Vink dit aan als je Rabobank bestanden importeert.',
'csv_specifix_AbnAmroDescription' => 'Vink dit aan als je ABN AMRO CSV bestanden importeert.',
'csv_specifix_Dummy' => 'Dit vinkje doet niks (dummy).',
'csv_import_account_help' => 'Als jouw CSV bestand geen referenties bevat naar jouw rekening(en), geef dan hier aan om welke rekening het gaat.',
'csv_delimiter_help' => 'Kies het veldscheidingsteken dat in het invoerbestand is gebruikt. Bij twijfel is de komma de veiligste optie.',