summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--transaction_details.py87
-rwxr-xr-xtransfers.py9
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()