a-fas / mt940js

Swift MT940 bank statement javascript parser
Apache License 2.0
32 stars 17 forks source link

Cannot read property '1' of null #13

Closed nickidk4 closed 5 years ago

nickidk4 commented 5 years ago

I have a swift that fails in _detectDetailStructure(transaction) with the error Cannot read property '1' of null

Error happens in this line: parser.js:343 .map(m => [ m[1].replace(stripPrefixRe, ''), m[2] ]) // remove prefix symbols from tag

I don't know how to fix this, and have included swift below. Hope you can recreate the same error ::)

parser.js:313

_detectDetailStructure(transaction) {
  const details = transaction.details.replace(/\n/g, '').trim();
  const prefix = details.charAt();

  // check first symbol is known separator
  let tagRe;
  if (!prefix) return;
  else if (prefix === '/') {                // assume /XXX/ fields
    tagRe = '\\/[0-9A-Z]{2,4}\\/';
  } else if ('>?'.includes(prefix)) {  // assume >DD fields
    tagRe = `\\${prefix}\\d{2}`;
  } else return; // known separator not found

  const rule = {
    detect: new RegExp(`^${tagRe}`),
    split: new RegExp(`(?=${tagRe})`),
    item: new RegExp(`^(${tagRe})(.*)`),
  };
  const stripPrefixRe = new RegExp(`\\${prefix}`, 'g');

  if (!rule.detect.test(details)) return; // string must start with tag

  const matches = details.split(rule.split);
  if (matches.length > 0 && matches[0].length === 0) matches.shift(); // remove empty match at start
  if (matches.length === 0) return; // no matches found

  const parsedStruc = matches
    .map(m => m.match(rule.item)) // supposed to match groups 1 and 2
    .map(m => [m[1].replace(stripPrefixRe, ''), m[2]]) // remove prefix symbols from tag
    .reduce((struc, m) => Object.assign(struc, { [m[0]]: m[1] }), {});

  return parsedStruc;
}

Edited swift

{1:F01XXXXXX22AXXX7083687496}{2:O9402150181012XXXXXXFFGXXX56494055261810130500N}{3:{108:E940181012H77XXT}}{4:
:20:100924006010
:25:50070010/92400601000
:28C:00201/001
:60F:D181011EUR64495,89
:61:181012C29553,63NTRFP5463911 240 1//03MT181012327305
:86: /XXXX//100924006010 XXXXXXXXXXXXX XXXXXXXX XXXXXX XX (XXXX) 
 /XXXX/XX XXXXXX XXXXX XXXX X.X.25 XXXX XXXXX, XXXXXX XXXXX 
 /XXXX/XXXXXXXXXXX XXX XXX: 03MT181012327305  
XXXX XXX: P5463911 240 1   M CA O/XXXXXX2L            
/XXX/XXXX/CHASGB2L         /6231400604                
BIC:XXXXXX2L                     
:61:181012C44330,45NTRFP5463916 240 1//03MT181012327356
:86: /XXXX//100924006010 XXXXXXXXXXXXX XXXXXXXX XXXXXX XX (XXXX) 
 /XXXX/XX XXXXXX XXXXX XXXX X.X.25 XXXX XXXXX, XXXXXX XXXXX 
 /XXXX/XXXXXXXXXXX XXX XXX: 03MT181012327356  
XXXX XXX: P5463916 240 1   M CA O/XXXXXX2L            
/ACC/INST/CHASGB2L         /6231400604                
BIC:XXXXXX2L                     
:61:181012C509705,83NTRF7288-1607516//03MT181012180608
:86: /XXXX//100924006010 XXXXXXXXXXXXX XXXXXXXX XXXXXX XX (XXXX) 
 /XXXX/XXXXXX XXXX XX (XXXX), XXXXXXX XXXXXX 00020 XXXXXXXX X
 /XXXX/XXXXXXXXXXX XXX XXX: 03MT181012180608  
XXXX XXX: 7288-1607516     M CA O/12NXXXXXXXXXXX171533
BIC:XXXXXXXXXXX                     
:61:181012C850000,00NTRF181012671//03MT181012182288
:86: /XXXX//100924006010 XXXXXXXXXXXXX XXXXXXXX XXXXXX XX (XXXX) 
 /XXXX/XXXXXXXXXXXXX XXXXXXXX XXXXXX XX (XXXX) (XXXXXX: XXX X
 /XXXX/XXXXXXXXXXX XXX XXX: 03MT181012182288  
XXXX XXX: 181012671        M CA O/XXXXXX22            
BIC:XXXXXX22                     
:62M:C181012EUR1369094,02
-}{5:{CHK:761XXXX7A283}{DLM:}{CAC:VALIDATION SUCCESS}}
a-fas commented 5 years ago

Could you give another example. Seems this is obfuscated too much. e.g. the 3rd tag 61 has "X" in place of Debit/credit marker. And the total of transactions does not match the whole statement turnover. Sorry I just don't have time for deciphering of over-edited examples ;)

The best if you can give an example which can be copy pasted to a text file and then check with cli (node cli.js <path to file>) and it gives the error you mention

nickidk4 commented 5 years ago

Hey a-fas, is there any way I can send a less obfuscated version to you directly instead of posting it here online? :)

nickidk4 commented 5 years ago

I updated the swift message in previous post, and it seems to be able to throw expected error. Hope you can look into this :)

a-fas commented 5 years ago

This should be something with 86 field structure ... Can you post here a couple of 86 tags from the above statement. You can obfuscate the data but keep the tags ! e.g this one

:86: /XXXX//100924006010 XXXXXXXXXXXXX XXXXXXXX XXXXXX XX (XXXX) 
 /XXXX/XXXXXXXXXXXXX XXXXXXXX XXXXXX XX (XXXX) (XXXXXX: XXX X
 /XXXX/XXXXXXXXXXX XXX XXX: 03MT181012182288  
XXXX XXX: 181012671        M CA O/XXXXXX22            
BIC:XXXXXX22 

Keep the values in /xxxx/ and all other which look like meta data, e.g. very strange that some parts look like XXX: - they are supposed to be tags ? but the structure must be in /xxxx/ ... probably they are not supposed to be parseable in standard.

So please give some samples of those, but try to pad only sensitive info keeping the meta data

nickidk4 commented 5 years ago

I tried making a less obfuscated version of one of the above tags, so you can see the structure. Will try pasting more examples that fails.

:86: /XXXX//100924006010 XXXXXXXXXXXXX XXXXXXXX XXXXXX AB (PUBL) 
 /ORDP/XXXXXXXXXXXXX XXXXXXXX BANKEN AB (PUBL) (FORMER: SXB A
 /REMI/XXXXXXXXXXX OUR REF: 03MT181012182288  
YOUR REF: 181012671        M CA O/XXXXDK22            
BIC:XXXXDK22  

These transactions fail too

:61:181024C7020,26NTRFP6363103 240 1//03MT181024144353
:86: /XXXX//100924006010 XXXXXXXXXXXXX XXXXXXXX XXXXXX AB (PUBL) 
 /ORDP/XX XXXXXX XXXXX XXXX N.A.25 XXXX XXXXX, CANARY WHARF 
 /REMI/UBERWEISUNG OUR REF: 03MT181024144353  
YOUR REF: P6363103 240 1   M CA O/XXXXGB2L            
/ACC/INST/XXXXGB2L         /6231400604                
BIC:XXXXGB2L   
:61:180924C6966,40NTRFP2917104 240 1//03MT180924148962
:86: /XXXX//100924006010 XXXXXXXXXXXXX XXXXXXXX XXXXXX AB (PUBL) 
 /ORDP/XX XXXXXX XXXXX BANK N.A.25 XXXX XXXXX, XXXXXX XXXXX 
 /REMI/XXXXXXXXXXX OUR REF: 03MT180924148962  
YOUR REF: P2917104 240 1   M CA O/XXXXGB2L            
/ACC/INST/CHASGB2L         /6231400604                
BIC:XXXXGB2L 
nickidk4 commented 5 years ago

I don't really know what the function _detectDetailStructure(transaction) does, but I tried returning transaction imediately as first line in function, and I get no errors, and it looks like i get the tag 86 field returned as I require. So maybe this is the solution for me? :)

a-fas commented 5 years ago

it tries to find the structure tags and parse them ... your first example actually works for me (hmm??) but the second does not, let's focus on it

/XXXX//100924006010 XXXXXXXXXXXXX XXXXXXXX XXXXXX AB (PUBL)
 /ORDP/XX XXXXXX XXXXX XXXX N.A.25 XXXX XXXXX, CANARY WHARF
 /REMI/UBERWEISUNG OUR REF: 03MT181024144353
YOUR REF: P6363103 240 1   M CA O/XXXXGB2L
/ACC/INST/XXXXGB2L         /6231400604
BIC:XXXXGB2L

So the issue is in this part /ACC/INST/. Both are identified as internal structure tags, but the first one is incomplete. So there is some bug with regex. But now I have a question: do I understand correctly that the real tag is ACC ? And the rest INST/XXXXGB2L /6231400604\nBIC:XXXXGB2L is actually it's content ? At least that is how I would understand it from spec perspective

nickidk4 commented 5 years ago

I don't really know. I'm no swift expert :D

I don't need to destructure tag 86, I only need to save everything in tag 86 in a database. So this is why returning transactions immediately works fine for me.

I thought tag 86 was just additional content and could be 6 lines at 65 chars each with no restrictions.

a-fas commented 5 years ago

I see, well this a subject for a feature :) I added a constructor param no86Structure so you can disable structure parsing. See the commit above. pls check the latest master. But I'll publish later, I want to fix the issue with that tag first, at least in my understanding

a-fas commented 5 years ago

should be fixed now in master, pls try, if OK, I'll publish

nickidk4 commented 5 years ago

Works great!

a-fas commented 5 years ago

published 1.3.1 :)