1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
# see https://github.com/raphaelm/python-fints/pull/8
# https://www.db-bankline.deutsche-bank.com/download/MT940_Deutschland_Structure2002.pdf
DETAIL_KEYS = {
'': 'Geschäftsvorfall-Code',
'00': 'Buchungstext',
'10': 'Primanota',
'20': 'Verwendungszweck',
'30': 'Auftraggeber BLZ',
'31': 'Auftraggeber Kontonummer',
'32': 'Auftraggeber Name',
'34': 'Rücklastschriften',
'35': 'Empfänger: Name',
'60': 'Zusätzl. Verwendungszweckangaben',
}
# https://www.hettwer-beratung.de/sepa-spezialwissen/sepa-technische-anforderungen/sepa-geschäftsvorfallcodes-gvc-mt-940/
VERWENDUNGSZWECK_KEYS = {
'': 'Verwendungszweck',
'IBAN': 'Auftraggeber IBAN',
'BIC': 'Auftraggeber BIC',
'EREF': 'End to End Referenz',
'MREF': 'Mandatsreferenz',
'CRED': 'Auftraggeber Creditor ID',
'PURP': 'Purpose Code',
'SVWZ': 'Verwendungszweck',
'MDAT': 'Mandatsdatum',
'ABWA': 'Abweichender Auftraggeber',
'ABWE': 'Abweichender Empfänger',
'SQTP': 'FRST / ONE / OFF /RECC',
'ORCR': 'SEPA Mandatsänderung: alte SEPA CI',
'ORMR': 'SEPA Mandatsänderung: alte SEPA Mandatsreferenz',
'DDAT': 'SEPA Settlement Tag für R- Message',
'KREF': 'Kundenreferenz',
'DEBT': 'Debtor Identifier bei SEPA Überweisung',
'COAM': 'Compensation Amount',
'OAMT': 'Original Amount',
}
def parse_transaction_details(details):
detail_str = ''.join(d.strip() for d in details.splitlines())
result = {}
for key, value in DETAIL_KEYS.items():
result[value] = None
for key, value in VERWENDUNGSZWECK_KEYS.items():
result[value] = None
pre_result = {}
segment = ''
segment_type = ''
for index, char in enumerate(detail_str):
if char != '?':
segment += char
continue
pre_result[segment_type] = segment if not segment_type else segment[2:]
segment_type = detail_str[index+1] + detail_str[index+2]
segment = ''
for key, value in pre_result.items():
if key in DETAIL_KEYS:
result[DETAIL_KEYS[key]] = value
else:
if key == '33':
result[DETAIL_KEYS['32']] += value
elif key.startswith('2'):
result[DETAIL_KEYS['20']] += value
else:
raise ValueError('Found Key ?{}, which is not documented'.format(key))
post_result = {}
segment_type = None
text = ''
for index, char in enumerate(result['Verwendungszweck']):
if char == '+' and result['Verwendungszweck'][index-4:index] in VERWENDUNGSZWECK_KEYS:
if segment_type:
post_result[segment_type] = text[:-4]
text = ''
else:
text = ''
segment_type = result['Verwendungszweck'][index-4:index]
else:
text += char
if segment_type:
post_result[segment_type] = text
else:
post_result[''] = text
for key, value in post_result.items():
result[VERWENDUNGSZWECK_KEYS[key]] = value
return result
|