diff options
-rw-r--r-- | transaction_details.py | 87 | ||||
-rwxr-xr-x | transfers.py | 9 |
2 files changed, 95 insertions, 1 deletions
diff --git a/transaction_details.py b/transaction_details.py new file mode 100644 index 0000000..a7ecf6c --- /dev/null +++ b/transaction_details.py @@ -0,0 +1,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
\ No newline at end of file diff --git a/transfers.py b/transfers.py index c14055f..3580ce8 100755 --- a/transfers.py +++ b/transfers.py @@ -7,6 +7,7 @@ import logging from fints.client import FinTS3PinTanClient import peewee as p from slixmpp import ClientXMPP +import transaction_details logging.basicConfig(level=logging.INFO) @@ -28,6 +29,12 @@ class Transaction(p.Model): sepa_amount_str = p.CharField() sepa_transaction_details = p.CharField() + def format_message(self): + details = transaction_details.parse_transaction_details(self.sepa_transaction_details) + return "{accountnumber} {details[Buchungstext]}: {amount_str} {details[Verwendungszweck]}".format( + entry_date=self.sepa_entry_date, accountnumber=self.accountnumber, amount_str=self.sepa_amount_str, + details=details) + class Meta: database = db indexes = ((('accountnumber', 'sepa_entry_date', 'sepa_transaction_details'), True),) @@ -79,7 +86,7 @@ cl = ClientXMPP(config['jabber']['jid'], config['jabber']['password']) def session_start(event): cl.send_presence() for t in new_transactions: - message = "{} {} {}".format(t.accountnumber, t.sepa_amount_str, t.sepa_transaction_details) + message = t.format_message() cl.send_message(config['jabber']['recipient'], message, mtype='chat') logging.info("Sent info %s", message) cl.disconnect() |