File: dnbLV.py

package info (click to toggle)
ofxstatement-plugins 20161204
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 3,160 kB
  • ctags: 1,619
  • sloc: python: 4,374; xml: 292; makefile: 103
file content (102 lines) | stat: -rw-r--r-- 3,778 bytes parent folder | download | duplicates (2)
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
100
101
102
"""Parser implementation for DNB generated statement reports"""

import re
from xml.etree import ElementTree

from ofxstatement.parser import StatementParser
from ofxstatement.plugin import Plugin
from ofxstatement.statement import Statement, StatementLine

CARD_PURCHASE_RE = re.compile(r".* Pirkums - .*? - par (\d\d\/\d\d\/\d\d\d\d)", re.U | re.M)

class dnbLVStatementParser(StatementParser):
    date_format = "%Y-%m-%d"

    statement = None
    fin = None  # file input stream

    def __init__(self, fin):
        self.statement = Statement()
        self.fin = fin

    def split_records(self):
        xml = ElementTree.parse(self.fin)
        xml = xml.getroot()

        namespaces = {'ns': xml.tag[1:].partition("}")[0]}
        statement = xml.find('ns:Statement', namespaces=namespaces)

        period = statement.find('ns:Period', namespaces=namespaces)
        self.statement.start_date = self.parse_datetime(period.find('ns:StartDate', namespaces=namespaces).text)
        self.statement.end_date = self.parse_datetime(period.find('ns:EndDate', namespaces=namespaces).text)

        account = statement.find('ns:AccountSet', namespaces=namespaces)
        if not self.statement.account_id:
            self.statement.account_id = account.find('ns:AccNo', namespaces=namespaces).text

        transactions = account.find('ns:CcyStmt', namespaces=namespaces)
        self.statement.start_balance = self.parse_float(transactions.find('ns:OpenBal', namespaces=namespaces).text)

        all_transactions = transactions.findall('ns:TrxSet', namespaces=namespaces)

        return all_transactions

    def parse_record(self, line):
        # Namespace stuff
        namespaces = {'ns': line.tag[1:].partition("}")[0]}

        # Get all fields
        type_code = line.find('ns:TypeCode', namespaces=namespaces).text
        date = line.find('ns:BookDate', namespaces=namespaces).text
        c_or_d = line.find('ns:CorD', namespaces=namespaces).text
        amount = line.find('ns:AccAmt', namespaces=namespaces).text
        id = line.find('ns:BankRef', namespaces=namespaces).text
        note = line.find('ns:PmtInfo', namespaces=namespaces).text

        # Payee name
        payee_name = None
        payee = line.find('ns:CPartySet', namespaces=namespaces)
        if payee:
            payee_account = payee.find('ns:AccHolder', namespaces=namespaces)
            if payee_account:
                payee_name = payee_account.find('ns:Name', namespaces=namespaces).text

        # Create statement line
        stmt_line = StatementLine(id, self.parse_datetime(date), note, self.parse_float(amount))
        stmt_line.payee = payee_name

        # Credit & Debit stuff
        stmt_line.trntype = "DEP"
        if c_or_d == 'D':
            stmt_line.amount = -stmt_line.amount
            stmt_line.trntype = "DEBIT"

        # Various types
        if type_code == 'MEMD':
            stmt_line.trntype = "SRVCHG"
        elif type_code == 'OUTP':
            stmt_line.trntype = "PAYMENT"

        # Check if paid by card
        m = CARD_PURCHASE_RE.match(stmt_line.memo)
        if m:
            # this is an electronic purchase. extract some useful
            # information from memo field
            date = m.group(1).split('/')
            date = '%s-%s-%s' % (date[2], date[1], date[0])
            stmt_line.date_user = self.parse_datetime(date)

        #print(stmt_line)
        return stmt_line

    def parse_float(self, value):
        return value if isinstance(value, float) else float(value.replace(',', '.'))


class DnbLVPlugin(Plugin):
    """Latvian DNB CSV"""

    def get_parser(self, fin):
        parser = dnbLVStatementParser(fin)
        parser.statement.currency = self.settings.get('currency', 'EUR')
        return parser