|
@@ -1,5 +1,5 @@
|
1
|
1
|
# coding=utf-8
|
2
|
|
-"""Convert Bank statement CSV to Gnucash-acceptable format"""
|
|
2
|
+"""Convert Bank statement CSV to YNAB-acceptable format"""
|
3
|
3
|
|
4
|
4
|
from collections import namedtuple
|
5
|
5
|
|
|
@@ -36,19 +36,21 @@ class BaseTransaction(object):
|
36
|
36
|
pass
|
37
|
37
|
|
38
|
38
|
|
39
|
|
-class GCTransaction(object):
|
40
|
|
- """A Gnucash-acceptable transaction"""
|
|
39
|
+class YNABTransaction(object):
|
|
40
|
+ """A YNAB-acceptable transaction"""
|
41
|
41
|
|
42
|
|
- def __init__(self, date, deposit, withdrawal, description):
|
|
42
|
+ header = u'Date,Inflow,Outflow,Memo'
|
|
43
|
+
|
|
44
|
+ def __init__(self, date, deposit, withdrawal, memo):
|
43
|
45
|
self.date = date
|
44
|
46
|
self.deposit = deposit
|
45
|
47
|
self.withdrawal = withdrawal
|
46
|
|
- self.description = description
|
|
48
|
+ self.memo = memo
|
47
|
49
|
|
48
|
50
|
def __str__(self):
|
49
|
51
|
"""Naive CSV line printer"""
|
50
|
|
- values = [self.date, self.deposit, self.withdrawal, self.description]
|
51
|
|
- return ";".join(['"%s"' % v for v in values])
|
|
52
|
+ values = [self.date, self.deposit, self.withdrawal, self.memo]
|
|
53
|
+ return ",".join(['"%s"' % v for v in values])
|
52
|
54
|
|
53
|
55
|
|
54
|
56
|
class BaseTransactionParser(object):
|
|
@@ -73,13 +75,12 @@ class BaseTransactionParser(object):
|
73
|
75
|
lines_read += 1
|
74
|
76
|
self.state = self.advance(line, lineno=lines_read)
|
75
|
77
|
if self.is_open():
|
76
|
|
- self.transactions.append(self.parse_line(line).to_gc())
|
|
78
|
+ self.transactions.append(self.parse_line(line).to_ynab())
|
77
|
79
|
|
78
|
80
|
def format_csv(self):
|
79
|
|
- return "\n".join([
|
80
|
|
- unicode(t).encode('utf-8')
|
81
|
|
- for t in self.transactions
|
82
|
|
- ])
|
|
81
|
+ lines = [YNABTransaction.header.encode('utf-8')]
|
|
82
|
+ lines += [unicode(t).encode('utf-8') for t in self.transactions]
|
|
83
|
+ return "\n".join(lines)
|
83
|
84
|
|
84
|
85
|
|
85
|
86
|
class MbankTransaction(BaseTransaction):
|
|
@@ -163,13 +164,13 @@ class MbankTransaction(BaseTransaction):
|
163
|
164
|
num = num.replace(',', '.')
|
164
|
165
|
return float(num)
|
165
|
166
|
|
166
|
|
- def to_gc(self):
|
167
|
|
- """Convert to GCTransaction"""
|
168
|
|
- return GCTransaction(
|
|
167
|
+ def to_ynab(self):
|
|
168
|
+ """Convert to YNABTransaction"""
|
|
169
|
+ return YNABTransaction(
|
169
|
170
|
date=self.date_r,
|
170
|
171
|
deposit=self.amountd,
|
171
|
172
|
withdrawal=self.amountw,
|
172
|
|
- description=self._description()
|
|
173
|
+ memo=self._description()
|
173
|
174
|
)
|
174
|
175
|
|
175
|
176
|
|
|
@@ -260,13 +261,13 @@ class FioTransaction(BaseTransaction):
|
260
|
261
|
def _parse_currency(self, text):
|
261
|
262
|
return float(text)
|
262
|
263
|
|
263
|
|
- def to_gc(self):
|
264
|
|
- """Convert to GCTransaction"""
|
265
|
|
- return GCTransaction(
|
|
264
|
+ def to_ynab(self):
|
|
265
|
+ """Convert to YNABTransaction"""
|
|
266
|
+ return YNABTransaction(
|
266
|
267
|
date=self.date,
|
267
|
268
|
deposit=self.amountd,
|
268
|
269
|
withdrawal=self.amountw,
|
269
|
|
- description=self._description()
|
|
270
|
+ memo=self._description()
|
270
|
271
|
)
|
271
|
272
|
|
272
|
273
|
|
|
@@ -364,13 +365,13 @@ class RaifTransaction(BaseTransaction):
|
364
|
365
|
def _parse_currency(self, text):
|
365
|
366
|
return float(text.replace(',', '.').replace(' ', ''))
|
366
|
367
|
|
367
|
|
- def to_gc(self):
|
368
|
|
- """Convert to GCTransaction"""
|
369
|
|
- return GCTransaction(
|
|
368
|
+ def to_ynab(self):
|
|
369
|
+ """Convert to YNABTransaction"""
|
|
370
|
+ return YNABTransaction(
|
370
|
371
|
date=self.date,
|
371
|
372
|
deposit=self.amountd,
|
372
|
373
|
withdrawal=self.amountw,
|
373
|
|
- description=self._description()
|
|
374
|
+ memo=self._description()
|
374
|
375
|
)
|
375
|
376
|
|
376
|
377
|
|