Skip to content

Commit

Permalink
bankRef & splitTransactions (#39)
Browse files Browse the repository at this point in the history
added function body to method: bankRef & refactored splitTransactions() in AbstractParser.php
  • Loading branch information
twitnic authored Jun 3, 2021
1 parent 8b3af41 commit 9309715
Show file tree
Hide file tree
Showing 17 changed files with 359 additions and 124 deletions.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
},
{
"name": "powercloud GmbH / Dominic Richter",
"email": "d.richter@powercloud.de",
"homepage": "https://www.powercloud.de"
"email": "dominic.richter@power.cloud",
"homepage": "https://www.power.cloud"
}
],
"require": {
Expand Down
88 changes: 48 additions & 40 deletions lib/Jejik/MT940/Parser/AbstractParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,13 @@
*/
abstract class AbstractParser
{
// Properties {{{

/**
* Reference to the MT940 reader
*
* @var Reader
*/
protected $reader;

// }}}

/**
* Constructor
*
Expand Down Expand Up @@ -130,13 +126,14 @@ public function parse(string $text): array
*
* The contents may be several lines long (e.g. :86: descriptions)
*
* @param string $id The line ID (e.g. "20"). Can be a regular
* @param string $id The line ID (e.g. "20"). Can be a regular
* expression (e.g. "60F|60M")
* @param string $text The text to search
* @param int $offset The offset to start looking
* @param int $position Starting position of the found line
* @param int $length Length of the found line (before trimming),
* @param string $text The text to search
* @param int $offset The offset to start looking
* @param int|null $position Starting position of the found line
* @param int|null $length Length of the found line (before trimming),
* including EOL
* @return string|null
*/
protected function getLine(
string $id,
Expand Down Expand Up @@ -164,6 +161,40 @@ protected function getLine(
return null;
}

/**
* Get the contents of an MT940 line
*
* The contents may be several lines long (e.g. :86: descriptions)
*
* @param string $text The text to search
* @return string|null
*/
protected function getTransactionLines($text): ?array {

$amountLine = [];
$pcre = '/(?:^|\r\n)\:(?:61)\:(.+)(?::?$|\r\n\:[[:alnum:]]{2,3}\:)/Us';

if (preg_match_all($pcre, $text, $match)) {
$amountLine = $match;
}

$multiPurposeField = [];
$pcre = '/(?:^|\r\n)\:(?:86)\:(.+)(?:[\r\n])(?:\:(?:6[0-9]{1}[a-zA-Z]?)\:|(?:[\r\n]-))/Us';

if (preg_match_all($pcre, $text, $match)) {
$multiPurposeField = $match;
}

$count = count($amountLine[1]);
$result = [];
for ($i = 0; $i < $count; $i++) {
$result[$i][] = trim($amountLine[1][$i]);
$result[$i][] = trim(str_replace(':86:', '', $multiPurposeField[1][$i]));
}

return $result;
}

/**
* Split the text into separate statement chunks
*
Expand Down Expand Up @@ -195,35 +226,8 @@ protected function splitStatements(string $text): array
*/
protected function splitTransactions(string $text): array
{
$offset = 0;
$length = 0;
$position = 0;
$transactions = [];

while ($line = $this->getLine('61', $text, $offset, $offset, $length)) {
$offset += 4 + $length + 2;
$transaction = [$line];

// See if the next description line belongs to this transaction line.
// The description line should immediately follow the transaction line.
$description = [];
while ($line = $this->getLine('86', $text, $offset, $position, $length)) {
if ($position == $offset) {
$offset += 4 + $length + 2;
$description[] = $line;
} else {
break;
}
}

if ($description) {
$transaction[] = implode("\r\n", $description);
}

$transactions[] = $transaction;
}

return $transactions;
$transactionLines = $this->getTransactionLines($text);
return $transactionLines ?? [];
}

/**
Expand Down Expand Up @@ -329,7 +333,7 @@ protected function accountNumber(string $text): ?string
protected function accountCurrency($text): ?string
{
$accountNumber = $this->accountNumber($text);
if ($accountNumber == null) {
if ($accountNumber === null) {
return null;
}
// last 3 characters comprises its ISO currency code
Expand Down Expand Up @@ -534,7 +538,11 @@ protected function contraAccountName(array $lines): ?string
*/
protected function description(?string $description): ?string
{
return $description;
if ($description === null) {
return null;
}
//return implode('', array_map('trim', explode("\r\n", $description)));
return implode("\r\n", explode("\r\n", $description));
}

/**
Expand Down
39 changes: 23 additions & 16 deletions lib/Jejik/MT940/Parser/GermanBank.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
*/
abstract class GermanBank extends AbstractParser
{

protected const IDENTIFIER_EREF = 'EREF';
protected const IDENTIFIER_KREF = 'KREF';
protected const IDENTIFIER_MREF = 'MREF';
Expand Down Expand Up @@ -51,6 +50,7 @@ protected function gvc(array $lines): ?string

/**
* Parse code for provided transaction lines
* @todo: return code with leading N
*/
protected function code(array $lines): ?string
{
Expand Down Expand Up @@ -79,7 +79,6 @@ protected function code(array $lines): ?string
*/
protected function ref(array $lines): ?string
{
// get :61: line -- it is first in provided array [:61:,:86:,....]
$refLine = isset($lines[0]) ? $lines[0] : null;

// assure ref line
Expand All @@ -88,24 +87,37 @@ protected function ref(array $lines): ?string
}

// match it
preg_match('#(\d{6})(\d{4})?(R?(?:C|D))([0-9,]{1,15})N([a-zA-Z0-9]+)#', $refLine, $match);
preg_match("/(?'valuta'\d{6})(?'bookingdate'\d{4})?(?'debitcreditid'R?(?:C|D))(?'amount'[0-9,]{1,15})(?:\s*)(?'bookingkey'N[a-zA-Z0-9]{3})(?'reference'[a-zA-Z0-9+]+)(?:\/\/)*(?'bankref'[0-9a-zA-Z]{1,16})*/", $refLine, $match);

// assure match
if (!isset($match[5])) {
if (!isset($match['reference'])) {
return null;
}

// return
return substr($match[5], 3);
return $match['reference'];
}

/**
* Parse bankRef for provided transaction lines
*/
protected function bankRef(array $lines): ?string
{
// TODO search its proper explanation and implement it
return $this->ref($lines);
$refLine = isset($lines[0]) ? $lines[0] : null;

// assure ref line
if ($refLine == null) {
return null;
}

// match it
preg_match("/(?'valuta'\d{6})(?'bookingdate'\d{4})?(?'debitcreditid'R?(?:C|D))(?'amount'[0-9,]{1,15})(?:\s*)(?'bookingkey'N[a-zA-Z0-9]{3})(?'reference'[a-zA-Z0-9+]+)(?:\/\/)*(?'bankref'[0-9a-zA-Z]{1,16})*/", $refLine, $match);

// assure match
if (!isset($match['bankref'])) {
return null;
}

return $match['bankref'];
}

/**
Expand Down Expand Up @@ -227,7 +239,7 @@ protected function getSubfield(string $multiUseLine, string $identifier): ?strin
$subfields = [];

// check if leading value is an separator: '?20<text>' '?2X' '<identifier>' '<content>'
if (current($splitReferenceLine) != '?20') {
if (current($splitReferenceLine) !== '?20') {
// remove first element if no separator found
next($splitReferenceLine);
}
Expand Down Expand Up @@ -321,7 +333,7 @@ protected function accountHolder(array $lines): ?string

// TODO try to match names containing ? character
preg_match(
'#\?32((?:[a-zA-ZöäüÖÄÜß0-9\(\)\s,\-\./\+]+(?:\?[^\?33|34])?)+)#',
'#\?32((?:[a-zA-ZöäüÖÄÜß0-9\(\)\s,\-\./\+]+(?:\?[^\?33|34])?)+)#u',
$this->removeNewLinesFromLine($accHolderLine),
$match
);
Expand All @@ -333,7 +345,7 @@ protected function accountHolder(array $lines): ?string
// additional field ?33
/** @var string $accHolderLine */
preg_match(
'#\?33([a-zA-ZöäüÖÄÜß0-9\(\)\s,\-\./\+]+)#',
'#\?33([a-zA-ZöäüÖÄÜß0-9\(\)\s,\-\./\+]+)#u',
$this->removeNewLinesFromLine($accHolderLine),
$matchAdd
);
Expand Down Expand Up @@ -385,7 +397,6 @@ protected function mref(array $lines): ?string
// get :86: line -- it is second in provided array [:61:,:86:,....]
$mrefLine = isset($lines[1]) ? $lines[1] : null;

// pattern
$pattern = 'M(?:\?2[1-9])?R(?:\?2[1-9])?E(?:\?2[1-9])?F(?:\?2[1-9])?\+([a-zA-ZöäüÖÄÜß0-9\./?\+\-\s,]+)(C(?:\?2[1-9])?R(?:\?2[1-9])?E(?:\?2[1-9])?D|S(?:\?2[1-9])?V(?:\?2[1-9])?W(?:\?2[1-9])?Z)';

// match it
Expand All @@ -396,7 +407,6 @@ protected function mref(array $lines): ?string
return null;
}

// return
return preg_replace('#(\?\d{0,2})#', '', $match[1]);
}

Expand All @@ -408,7 +418,6 @@ protected function cred(array $lines): ?string
// get :86: line -- it is second in provided array [:61:,:86:,....]
$credLine = isset($lines[1]) ? $lines[1] : null;

// pattern
$pattern = 'C(?:\?2[1-9])?R(?:\?2[1-9])?E(?:\?2[1-9])?D(?:\?2[1-9])?\+([a-zA-ZöäüÖÄÜß0-9\./?\+\-\s,]+)S(?:\?2[1-9])?V(?:\?2[1-9])?W(?:\?2[1-9])?Z';

// match it
Expand All @@ -430,10 +439,8 @@ protected function svwz(array $lines): ?string
// get :86: line -- it is second in provided array [:61:,:86:,....]
$svwzLine = isset($lines[1]) ? $lines[1] : null;

// pattern
$pattern = "(S(?:\?2[1-9])?V(?:\?2[1-9])?W(?:\?2[1-9])?Z(?:\?2[1-9])?\+)(?:\?(?:2[1-9]))?(?'SVWZ'.*)(?:\?30)";

// match it
/** @var string $svwzLine */
preg_match("/{$pattern}/", $this->removeNewLinesFromLine($svwzLine), $match);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
:20:STARTUMS TA
:25:28020050/1426292700
:28C:172/1
:60F:C200904EUR0,
:61:2009040904C230,00N051NONREF
:86:166?00GUTSCHRIFT?100004772?20EREF+SCP 100 / 0082002528?21SVWZ+D 8
03020001000145464 +?221000145463 Manthey,August?30OLBODEH2XXX?31D
E59280200501422112100?32EWE VERTRIEB GmbH?35EWE VERTRIEB powerclo
ud
:65F:Dnullnull7414,3
:20:STARTUMS TA
:25:28020050/1426292700
:28C:172/1
:60F:C200904EUR0,
:61:2009040904C230,00N051NONREF
:86:166?00GUTSCHRIFT?100004772?20EREF+SCP 100 / 0082002528?21SVWZ+D 8
03020001000145464 +?221000145463 XXXXXXX,XXXXXX?30OLBODEH2XXX?31D
E59280200501000000000?32EWE VERTRIEB GmbH?35EWE VERTRIEB powerclo
ud
:65F:Dnullnull7414,3
10 changes: 10 additions & 0 deletions tests/Jejik/Tests/MT940/Fixture/document/bug-core-5401.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
:20:DEUTDEMMXXX
:25:DE19662800530622160900
:28C:00111/1
:60F:C210330EUR0,00
:61:2103310331C50,00 NTRFNONREF//2109025460313532
:86:166?00SEPA-GUTSCHRIFT?109075/611?20EREF+NOTPROVIDED SVWZ+VERTR?21
:KO:NR:401113172APRIL 2021?30DEUTDEDB237?31DE93230707000621787100
?32XXXXXXA MXXXXXX
:62F:C210331EUR0,00
-
28 changes: 14 additions & 14 deletions tests/Jejik/Tests/MT940/Fixture/document/deutschebank.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
:20:DEUTDEMMXXX
:25:20070000/0123456601
:28C:00143/1
:60F:C200605EUR0,00
:61:2006080608D12,35 NRTIKREF+//2016021783252833
/OCMT/EUR11,85//CHGS/EUR0,50/
:86:109?00SEPA-LASTSCHR. RETOURE CORE?109075/629?20EREF+A1.200080779.
400143254?21.4961336 KREF+SEPA-DA202006?2201221740-34972000-P1 MR
EF+2?230852HW2723821 CRED+DE41EON0?240000129793 OAMT+11,85 SVWZ+?
25SONSTIGE GRUENDE ENDABRECHN?26UNG NR. 500106875 ZU VERTRA?2740
0143254, KUNDENNUM MER 2?2802227779?30CSDBDE71XXX?31DE50712345600
200691329?32TESTER?33EL
:62F:C200608EUR0,00
-
:20:DEUTDEMMXXX
:25:20070000/0123456601
:28C:00143/1
:60F:C200605EUR0,00
:61:2006080608D12,35 NRTIKREF+//2016021783252833
/OCMT/EUR11,85//CHGS/EUR0,50/
:86:109?00SEPA-LASTSCHR. RETOURE CORE?109075/629?20EREF+A1.200080779.
400143254?21.4961336 KREF+SEPA-DA202006?2201221740-34972000-P1 MR
EF+2?230852HW2723821 CRED+DE41EON0?240000129793 OAMT+11,85 SVWZ+?
25SONSTIGE GRUENDE ENDABRECHN?26UNG NR. 500106875 ZU VERTRA?2740
0143254, KUNDENNUM MER 2?2802227779?30CSDBDE71XXX?31DE50712345600
200691329?32TESTER?33EL
:62F:C200608EUR0,00
-
30 changes: 15 additions & 15 deletions tests/Jejik/Tests/MT940/Fixture/document/lbbw.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
:20:LBBW
:21:NONREF
:25:12345678/1324357
:28C:1
:60F:C210120EUR0,00
:61:2102080208D0,01NCMZNONREF
:86:834?00KONTENPOOL?102?20BUCHUNG AUF KTO 7402050699?21BANKLEITZAHL
60050101?3060050101?3111111111
:61:2102080208C0,01NCOLKREF+//202102040007693
:86:171?00SEPA EINZUGSAUFTRAG?101?20KREF+SEPA-20210203175805-00?21154
800-P1?22SVWZ+E-MOBILITY ABRECHNUNG?23NR. 28 ZU VERTRAG 9433, KUN
?24DENNUMMER 11111?30SOLADEST600?31DE59600501010007907986?32NIC R
ICHTER
:62F:C210208EUR0,00
-
:20:LBBW
:21:NONREF
:25:12345678/1324357
:28C:1
:60F:C210120EUR0,00
:61:2102080208D0,01NCMZNONREF
:86:834?00KONTENPOOL?102?20BUCHUNG AUF KTO 7402050699?21BANKLEITZAHL
60050101?3060050101?3111111111
:61:2102080208C0,01NCOLKREF+//202102040007693
:86:171?00SEPA EINZUGSAUFTRAG?101?20KREF+SEPA-20210203175805-00?21154
800-P1?22SVWZ+E-MOBILITY ABRECHNUNG?23NR. 28 ZU VERTRAG 9433, KUN
?24DENNUMMER 11111?30SOLADEST600?31DE59600501010007907986?32NIC R
ICHTER
:62F:C210208EUR0,00
-
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
:20:STARTUMS MC
:25:28020050/1324354687
:28C:135/1
:60F:C180713EUR0,
:61:1807160716C104,50N051NONREF
:86:166?00GUTSCHRIFT?100004770?20WOHNBAU DIEPHOLZ GMBH?21EREF+NOTPROVIDED?22SVWZ+EWE,ENERGIEAUSWEIS RG.?23-NR. 1234567890 KD.-NR. 123?2477777?30AARBDE5W250?31DE99123456771234567888?32WOHNBAU DIEPHOLZ GMBH?35EWE VERTRIEB GMBH
:62F:C180716EUR0,
-
:20:STARTUMS MC
:25:28020050/1324354687
:28C:135/1
:60F:C180713EUR0,
:61:1807160716C104,50N051NONREF
:86:166?00GUTSCHRIFT?100004770?20WOHNBAU DIEPHOLZ GMBH?21EREF+NOTPROVIDED?22SVWZ+EWE,ENERGIEAUSWEIS RG.?23-NR. 1234567890 KD.-NR. 123?2477777?30AARBDE5W250?31DE99123456771234567888?32WOHNBAU DIEPHOLZ GMBH?35EWE VERTRIEB GMBH
:62F:C180716EUR0,
-
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
:20:STARTUMS TA
:25:DE19662800530622160900
:28C:172/1
:60F:C200904EUR0,
:61:2009040904C230,00N051NONREF
:86:166?00GUTSCHRIFT?100004772?20EREF+SCP 100 / 0082002528?21SVWZ+D 8
03020001000145464 +?221000145463 XXXXXXX,XXXXXX?30OLBODEH2XXX?31D
E59280200501000000000?32EWE VERTRIEB GmbH?35EWE VERTRIEB powerclo
ud
:65F:Dnullnull7414,3
Loading

0 comments on commit 9309715

Please sign in to comment.