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
99
|
#!/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 = p.DecimalField()
sepa_transaction_details = p.CharField()
sepa_status = p.CharField()
sepa_currency = p.CharField()
def format_message(self):
details = transaction_details.parse_transaction_details(self.sepa_transaction_details)
return '{transaction[accountnumber]} {details[Buchungstext]}: {transaction[sepa_amount]} ' \
'{transaction[sepa_currency]} {details[Auftraggeber Name]} {details[Verwendungszweck]}'.format(
transaction=self._data, 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:
filter_pred = {
'accountnumber': config['bank']['accountnumber'],
'sepa_entry_date': datetime.date.fromordinal(t.data['entry_date'].toordinal()),
'sepa_transaction_details': t.data['transaction_details'],
}
data = {'sepa_amount': t.data['amount'].amount, 'sepa_status': t.data['status'],
'sepa_currency': t.data['currency']}
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()
|