#!/usr/bin/python3 import configparser import argparse import datetime import logging from fints.client import FinTS3PinTanClient import peewee as p from playhouse.fields import PickledField from matrix_client.client import MatrixClient logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser() parser.add_argument('--config', nargs=1, required=True, help='Account .ini config file') parser.add_argument('--db', nargs=1, default='log.db', help='Database') parser.add_argument('--fetch-last', metavar='DAYS', default=None, type=int, help='Fetch all last DAYS') args = parser.parse_args() config = configparser.ConfigParser() config.read(args.config) db = p.SqliteDatabase(args.db) class Transaction(p.Model): created_date = p.DateField(default=datetime.date.today) accountnumber = p.CharField() identifier = p.CharField() sepa_entry_date = p.DateField() details = PickledField() def format_message_html(self): return """\ {accountnumber} {details[posting_text]}: {details[amount].amount} {details[amount].currency} {details[applicant_name]} {details[purpose]} {details[end_to_end_reference]} """.format(**self._data) class Meta: database = db indexes = ((('accountnumber', 'identifier'), True),) db.create_tables([Transaction], True) if args.fetch_last is None: # Look for last date of a saved transaction or fallback default timesamp last_transaction_date = Transaction \ .select(p.fn.max(Transaction.sepa_entry_date)) \ .where(Transaction.accountnumber == config['bank']['accountnumber']) \ .scalar(convert=True) or datetime.date.today() - datetime.timedelta(30) else: last_transaction_date = datetime.date.today() - datetime.timedelta(args.fetch_last) f = FinTS3PinTanClient(config['bank']['blz'], config['bank']['username'], config['bank']['password'], config['bank']['url']) accounts = f.get_sepa_accounts() account = list(filter(lambda a: a.accountnumber == config['bank']['accountnumber'], accounts))[0] logging.info("select transactions on account %s starting from %s", account.accountnumber, last_transaction_date) transactions = f.get_transactions(account, last_transaction_date, datetime.date.today()) new_transactions = [] for t in transactions: date = datetime.date.fromordinal(t.data['entry_date'].toordinal()), identifier = "{applicant_bin}-{applicant_iban}-{mydate}".format(mydate=date, **t.data) filter_pred = {'accountnumber': config['bank']['accountnumber'], 'identifier': identifier} data = {'details': t.data, 'sepa_entry_date': date} try: record = Transaction.get(**filter_pred) record.update(data) logging.info("Updated %s", record.id) except Transaction.DoesNotExist: data.update(filter_pred) record = Transaction.create(**data) new_transactions += [record] logging.info("Created %s", record.id) record.save() if len(new_transactions) > 0: client = MatrixClient(config['matrix']['host']) token = client.login(config['matrix']['user'], config['matrix']['pass']) room = client.join_room(config['matrix']['room']) for t in new_transactions: message = t.format_message_html() room.send_html(message) client.logout()