summaryrefslogtreecommitdiff
path: root/transfers.py
blob: fbf72b6d0e017280d48eee94ca2af0c18a2d1a5b (plain)
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
88
89
90
91
92
93
94
95
96
97
98
#!/usr/bin/python3
import configparser
import argparse
import datetime
import logging

from fints.client import FinTS3PinTanClient
import peewee as p
from slixmpp import ClientXMPP
import transaction_details

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()
    sepa_entry_date = p.DateField()
    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[Auftraggeber Name]} {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),)


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_statement(account, last_transaction_date, datetime.date.today())

new_transactions = []
for t in transactions:
    y, m, d, *_ = t.data['entry_date'].timetuple()
    entry_date = datetime.date(y, m, d)
    filter_pred = {
        'accountnumber': config['bank']['accountnumber'],
        'sepa_entry_date': entry_date,
        'sepa_transaction_details': t.data['transaction_details'],
    }
    data = {'sepa_amount_str': str(t.data['amount'])}
    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:
    cl = ClientXMPP(config['jabber']['jid'], config['jabber']['password'])


    def session_start(event):
        for t in new_transactions:
            message = t.format_message()
            cl.send_message(config['jabber']['recipient'], message, mtype='chat')
            logging.info("Sent info %s", message)
        cl.disconnect()


    cl.add_event_handler('session_start', session_start)
    cl.add_event_handler('killed', lambda *_: cl.loop.stop())
    cl.connect()
    cl.process()