Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Currently the following engines are included:
- KBS ([here](./src/Parser/Banking/Mt940/Engine/Kbs.php))
- ZETB ([here](./src/Parser/Banking/Mt940/Engine/Zetb.php))
- KONTIST ([here](./src/Parser/Banking/Mt940/Engine/Kontist.php))
- FINOM ([here](./src/Parser/Banking/Mt940/Engine/Fnom.php))
- a default `UNKNOWN`-engine ([here](./src/Parser/Banking/Mt940/Engine/Unknown.php))

### Custom engines
Expand Down
1 change: 1 addition & 0 deletions src/Parser/Banking/Mt940/Engine.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ abstract class Engine
1100 => Engine\Kbs::class,
1200 => Engine\Zetb::class,
1300 => Engine\Kontist::class,
1400 => Engine\Fnom::class,
];

/**
Expand Down
119 changes: 119 additions & 0 deletions src/Parser/Banking/Mt940/Engine/Fnom.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php

namespace Kingsquare\Parser\Banking\Mt940\Engine;

use Kingsquare\Banking\Statement;
use Kingsquare\Banking\Hsbc\HsbcTransaction;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this doesnt belong here?

use Kingsquare\Banking\Transaction;
use Kingsquare\Parser\Banking\Mt940\Engine;

/**
* @author bart (infinwebs.be)
* @license http://opensource.org/licenses/MIT MIT
*/
class Fnom extends Engine
{

/**
* returns the name of the bank.
*
* @return string
*/
protected function parseStatementBank()
{
return 'FINOM';
}

protected function parseStatementAccount(): string
{
$data = $this->getCurrentStatementData();
if (preg_match('/:25:FNOM([^:\r\n]+)/', $data, $results) && $results[1] !== '') {
$account = trim(preg_replace('/EUR\s*$/i', '', trim($results[1])));
return trim($account);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its already trimmed :)

}

return parent::parseStatementAccount();
}

protected function parseTransactionPrice(): float
{
$data = $this->getCurrentTransactionData();
if (preg_match('/^:61:.*?(DR|CR)([\d,\.]+)N/i', $data, $results) && isset($results[2])) {
return $this->sanitizePrice($results[2]);
}

return parent::parseTransactionPrice();
}

protected function parseTransactionDebitCredit(): string
{
$data = $this->getCurrentTransactionData();
if (preg_match('/^:61:.*?(DR|CR)/i', $data, $results) && $results[1] !== '') {
$letter = strtoupper($results[1]) === 'DR' ? 'D' : 'C';

return $this->sanitizeDebitCredit($letter);
}

return parent::parseTransactionDebitCredit();
}

protected function parseTransactionAccount(): string
{
$data = $this->getCurrentTransactionData();
if (preg_match('/\?31([A-Z]{2}[0-9]{2}[A-Z0-9]{1,34})/i', $data, $results) && $results[1] !== '') {
return $this->sanitizeAccount($results[1]);
}

return parent::parseTransactionAccount();
}

protected function parseTransactionAccountName(): string
{
$data = $this->getCurrentTransactionData();
if (preg_match('/\?32([^?\r\n]+)/', $data, $results) && $results[1] !== '') {
return $this->sanitizeAccountName(trim($results[1]));
}

return parent::parseTransactionAccountName();
}

protected function parseTransactionDescription(): string
{
$parent = parent::parseTransactionDescription();
$data = $this->getCurrentTransactionData();
if (preg_match('/\?00([^?]+)/', $data, $results) && $results[1] !== '') {
$label = trim($results[1]);
if ($label !== '') {
return $this->sanitizeDescription($label);
}
}

return $parent;
}

/**
* Overloaded
*
* @return array
*/
protected function parseStatementData()
{
$results = preg_split(
'/(^:20:|^-X{,3}$|\Z)/m',
$this->getRawData(),
-1,
PREG_SPLIT_NO_EMPTY
);
return $results;
}

/**
* Overloaded: Is applicable if first line starts with :20:AI.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the comment doesn't match the actual code

*
* {@inheritdoc}
*/
public static function isApplicable($string)
{
return strpos($string, ':25:FNOM') !== false;
}
}
30 changes: 30 additions & 0 deletions test/Parser/Banking/Mt940/Engine/Fnom/ParseTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Kingsquare\Parser\Banking\Mt940\Engine\Fnom;

use Kingsquare\Parser\Banking\Mt940\Engine\Fnom;

/**
*
*/
class ParseTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Fnom
*/
private $engine;

protected function setUp()
{
$this->engine = new Fnom();
$this->engine->loadString(file_get_contents(__DIR__ . '/sample'));
}

public function testParseStatementBank()

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd really like to see a full test suite covering all the various overloaded methods to ensure the correct parsing of the statements themselves.

{
$method = new \ReflectionMethod($this->engine, 'parseStatementBank');
$method->setAccessible(true);
$this->assertEquals('FINOM', $method->invoke($this->engine));
}

}
33 changes: 33 additions & 0 deletions test/Parser/Banking/Mt940/Engine/Fnom/sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
:20:2603108b057bdce1
:21:NONREF
:25:FNOMNL22/XXXXXXXXXXEUR
:28C:0
:60F:C260203EUR4429,19
:61:2602280228DR185,23NTRFNONREF
:86:166?00SEPA-Gutschrift?30?31?32Company A
:61:2602270227DR42,23NTRFNONREF
:86:166?00SEPA-Gutschrift?30GEBABEBBXXX?31BE00XXXXXXXXXXXX?32Company B?60+++111/1234/98765+++
:61:2602270227DR121,00NTRFNONREF
:86:166?00SEPA-Gutschrift?30KREDBEBBXXX?31BE00XXXXXXXXXXXX?32Company C?60F000001
:61:2602270227DR181,50NTRFNONREF
:86:166?00SEPA-Gutschrift?30NICABEBBXXX?31BE00XXXXXXXXXXXX?32Company D?60F000002
:61:2602260226CR378,11NTRFNONREF
:86:166?00SEPA-Gutschrift?30KREDBEBB?31BE00XXXXXXXXXXXX?32Company E?6078071842939 TROP PAYE STATUT SOCIAL
:61:2602240224DR65,35NDDTNONREF
:86:105?00Lastschrift ?30BBRUBEBB?31BE00XXXXXXXXXXXX?32Company F?60BE00XXXXXXXXXXXX
:61:2602170217DR79,88NDDTNONREF
:86:105?00Lastschrift ?30BBRUBEBB?31BE00XXXXXXXXXXXX?32Company F?60BE00XXXXXXXXXXXX
:61:2602160216DR871,20NTRFNONREF
:86:166?00SEPA-Gutschrift?30GEBABEBBXXX?31BE00XXXXXXXXXXXX?32Company G?60Facture 2026/001
:61:2602120212DR382,90NTRFNONREF
:86:166?00SEPA-Gutschrift?30?31?32Company H
:61:2602100210DR134,95NDDTNONREF
:86:105?00Lastschrift ?30BBRUBEBB?31BE00XXXXXXXXXXXX?32Company F?60BE00XXXXXXXXXXXX
:61:2602090209CR4446,75NTRFNONREF
:86:166?00SEPA-Gutschrift?30ARSPBE22?31BE00XXXXXXXXXXXX?32Company I?60Acompte travaux 50pc
:61:2602050205DR21,00NDDTNONREF
:86:105?00Lastschrift ?30FNOMNL22?31NL00XXXXXXXXXXXX?32Company J?60Monthly fee for Basic plan.
:61:2602030203DR70,01NDDTNONREF
:86:105?00Lastschrift ?30BBRUBEBB?31BE00XXXXXXXXXXXX?32Company F?60BE00XXXXXXXXXXXX
:62F:C260228EUR7098,80
-