def parse_record(self, line):
     """Parse given transaction line and return StatementLine object
     """
     if (self.statement.account_id == None):
         self.statement.account_id = line[0].replace(" ", "")
     stmtline = super(BelfiusParser, self).parse_record(line)
     stmtline.trntype = 'DEBIT' if stmtline.amount < 0 else 'CREDIT'
     stmtline.bank_account_to = BankAccount(line[12],
                                            line[4].replace(" ", ""))
     return stmtline
Exemple #2
0
    def parse_record(self, line):
        """Parse given transaction line and return StatementLine object
        """
        self.statement.account_id = line[0].replace(" ", "")
        #self.statement.account_to =  line[5].replace(" ", "")

        stmtline = super(NewBParser, self).parse_record(line)
        stmtline.id = generate_transaction_id(stmtline)
        stmtline.trntype = 'DEBIT' if stmtline.amount < 0 else 'CREDIT'
        stmtline.bank_account_to = BankAccount(None, line[5].replace(" ", ""))

        return stmtline
Exemple #3
0
    def parse_transaction(
            self, line: List[Optional[str]]) -> Optional[StatementLine]:
        # line[2] contains the account number
        if self.statement.account_id:
            assert self.statement.account_id == line[2],\
                "Only one account is allowed; previous account: {}, \
this line's account: {}"                        .format(self.statement.account_id, line[2])
        else:
            self.statement.account_id = line[2]

        assert line[5] in ['Af', 'Bij']

        if line[5] == 'Af':
            amount: Optional[str] = line[self.mappings['amount']]
            line[self.mappings['amount']] =\
                '-' + (amount if isinstance(amount, str) else '')

        if line[self.mappings['bank_account_to']]:
            line[self.mappings['payee']] =\
                "{} ({})".format(line[self.mappings['payee']],
                                 line[self.mappings['bank_account_to']])
        else:
            line[self.mappings['memo']] =\
                "{}, {}".format(line[self.mappings['payee']],
                                line[self.mappings['memo']])
            line[self.mappings['payee']] = None

        # Python 3 needed
        stmt_line: StatementLine = super().parse_record(line)

        # Remove zero-value notifications
        if stmt_line.amount == 0:
            return None

        # Determine some fields not in the self.mappings
        # A hack but needed to use the adjust method
        stmt_line.__class__ = StatementLine
        stmt_line.adjust(self.unique_id_set)

        if stmt_line.amount < 0:
            stmt_line.trntype = "DEBIT"
        else:
            stmt_line.trntype = "CREDIT"

        if stmt_line.bank_account_to:
            stmt_line.bank_account_to = \
                BankAccount(bank_id=None,
                            acct_id=stmt_line.bank_account_to)
        return stmt_line
    def test_ofxWriter(self):

        # Create sample statement:
        statement = Statement("BID", "ACCID", "LTL")
        statement.lines.append(StatementLine(
            "1", datetime(2012, 2, 12), "Sample 1", 15.4))
        line = StatementLine("2", datetime(2012, 2, 12), "Sample 2", 25.0)
        line.payee = ''
        line.bank_account_to = BankAccount("SNORAS", "LT1232")
        line.bank_account_to.branch_id = "VNO"
        statement.lines.append(line)

        # Create writer:
        writer = ofx.OfxWriter(statement)

        # Set the generation time so it is always predictable
        writer.genTime = datetime(2012, 3, 3, 0, 0, 0)

        assert prettyPrint(writer.toxml()) == SIMPLE_OFX
Exemple #5
0
    def parse_record(self, transaction: Transaction) -> StatementLine:
        """Parse given transaction line and return StatementLine object
        """
        logger.debug('transaction:\n' + pformat(transaction, indent=4))
        stmt_line = None

        # Use str() to prevent rounding errors
        bank_account_to = transaction.data.get('customer_reference')
        amount = Decimal(str(transaction.data['amount'].amount))
        memo = transaction.data['transaction_details']
        memo = memo.replace("\n", '')
        memo = memo.replace(transaction.data['customer_reference'], '', 1)
        memo = memo.replace(transaction.data['extra_details'], '', 1).strip()
        memo = memo if memo != '' else 'UNKNOWN'
        payee = None
        if transaction.data['customer_reference'] != ''\
           and transaction.data['extra_details'] != '':
            payee = "{1} ({0})".format(transaction.data['customer_reference'],
                                       transaction.data['extra_details'])

        date = transaction.data['date']

        # Remove zero-value notifications
        if amount != 0:
            stmt_line = StatementLine(date=date, memo=memo, amount=amount)
            stmt_line.id = \
                generate_unique_transaction_id(stmt_line, self.unique_id_set)
            m = re.match(r'([0-9a-f]+)(-\d+)?$', stmt_line.id)
            assert m, "Id should match hexadecimal digits, \
optionally followed by a minus and a counter: '{}'".format(stmt_line.id)
            if m.group(2):
                counter = int(m.group(2)[1:])
                # include counter so the memo gets unique
                stmt_line.memo = stmt_line.memo + ' #' + str(counter + 1)

            stmt_line.payee = payee
            if bank_account_to:
                stmt_line.bank_account_to = \
                    BankAccount(bank_id=None,
                                acct_id=bank_account_to)

        return stmt_line
Exemple #6
0
    def test_ofxWriter(self) -> None:

        # Create sample statement:
        statement = Statement("BID", "ACCID", "LTL")
        statement.lines.append(
            StatementLine("1", datetime(2012, 2, 12), "Sample 1",
                          Decimal("15.4")))
        line = StatementLine("2", datetime(2012, 2, 12), "Sample 2",
                             Decimal("25.0"))
        line.payee = ""
        line.bank_account_to = BankAccount("SNORAS", "LT1232")
        line.bank_account_to.branch_id = "VNO"
        line.currency = Currency("USD")
        line.orig_currency = Currency("EUR", Decimal("3.4543"))
        statement.lines.append(line)

        # Create writer:
        writer = ofx.OfxWriter(statement)

        # Set the generation time so it is always predictable
        writer.genTime = datetime(2012, 3, 3, 0, 0, 0)

        assert prettyPrint(writer.toxml()) == SIMPLE_OFX
 def parse_value(self, value, field):
     if field == "bank_account_to":
         return BankAccount("", value)
     else:
         return super().parse_value(value, field)
 def parse_value(self, value, field):
     value = value.strip() if value else value
     if field == "bank_account_to":
         return BankAccount("", value)
     else:
         return super().parse_value(value, field)
    def parse_record(self, line: List[str]) -> Optional[StatementLine]:
        """Parse given transaction line and return StatementLine object
        """

        try:
            logger.debug('header count: %d; line #%d: %s', len(self.header),
                         self.cur_record, line)

            # First record(s) must be the header
            if len(self.header) >= 1:
                # Remove it since it need not be checked anymore
                hdr = self.header.pop(0)
                line = list(filter(None, line))
                logger.debug('header: %s', hdr)
                assert line == hdr,\
                    "Expected: {}\ngot: {}".format(hdr, line)
                return None

            # line[self.ACCOUNT] contains the account number
            if self.statement.account_id:
                assert self.statement.account_id == \
                    line[self.ACCOUNT],\
                    "Only one account is allowed; previous account: {}, \
this line's account: {}"                        .format(self.statement.account_id,
                                line[self.ACCOUNT])
            else:
                self.statement.account_id = line[self.ACCOUNT]

            assert line[self.CD] in ['D', 'C'],\
                "Element {} is not D/C in line {}".format(self.CD, str(line))

            if line[self.CD] == 'D':
                line[self.mappings['amount']] =\
                    '-' + line[self.mappings['amount']]

            if line[self.mappings['bank_account_to']]:
                line[self.mappings['payee']] =\
                    "{} ({})".format(line[self.mappings['payee']],
                                     line[self.mappings['bank_account_to']])

            # Python 3 needed
            stmt_line: StatementLine = super().parse_record(line)

            # Remove zero-value notifications
            if stmt_line.amount == 0:
                return None

            # Determine some fields not in the self.mappings
            # A hack but needed to use the adjust method
            stmt_line.__class__ = StatementLine
            stmt_line.adjust(self.unique_id_set)

            if stmt_line.amount < 0:
                stmt_line.trntype = "DEBIT"
            else:
                stmt_line.trntype = "CREDIT"

            if stmt_line.bank_account_to:
                stmt_line.bank_account_to = \
                    BankAccount(bank_id=None,
                                acct_id=stmt_line.bank_account_to)
        except Exception as e:
            raise ParseError(self.cur_record, str(e))

        return stmt_line
Exemple #10
0
    def parse_record(self, line):
        """Parse given transaction line and return StatementLine object
        """
        self.line_nr += 1
        if line[0] == HEADER_START:
            return None
        elif len(line) != LINELENGTH:
            raise ParseError(
                self.line_nr, 'Wrong number of fields in line! ' + 'Found ' +
                str(len(line)) + ' fields ' + 'but should be ' +
                str(LINELENGTH) + '!')

        # Check the account id. Each line should be for the same account!
        if self.statement.account_id:
            if line[0] != self.statement.account_id:
                raise ParseError(
                    self.line_nr, 'AccountID does not match on all lines! ' +
                    'Line has ' + line[0] + ' but file ' + 'started with ' +
                    self.statement.account_id)
        else:
            self.statement.account_id = line[0]

        # Check the currency. Each line should be for the same currency!
        if self.statement.currency:
            if line[3] != self.statement.currency:
                raise ParseError(
                    self.line_nr, 'Currency does not match on all lines! ' +
                    'Line has ' + line[3] + ' but file ' + 'started with ' +
                    self.statement.currency)
        else:
            self.statement.currency = line[3]

        stmt_ln = super(KbcBeParser, self).parse_record(line)

        if line[12] != None and line[12] != '':
            stmt_ln.bank_account_to = BankAccount('', line[12])
        elif line[6].startswith('AUTOMATISCH SPAREN'):
            payee_match = re.match(
                'AUTOMATISCH SPAREN\s+\d\d\-\d\d\s+(?:NAAR|VAN) (\w\w\d\d(?: \d{4}){3})',
                line[6])
            if payee_match == None:
                raise ParseError(
                    self.line_nr,
                    'Cannot parse savings info. (' + line[6] + ')')
            stmt_ln.bank_account_to = BankAccount('', payee_match.group(1))

        if stmt_ln.payee == None or stmt_ln.payee == '':
            if line[6].startswith('BETALING AANKOPEN VIA '):
                payee_match = re.match(
                    'BETALING AANKOPEN VIA (?:.+), (.+) MET KBC\-(?:BANK|DEBET)KAART',
                    line[6])
                if payee_match == None:
                    raise ParseError(
                        self.line_nr,
                        'Cannot parse maestro/bancontact transaction info. (' +
                        line[6] + ')')
                stmt_ln.payee = payee_match.group(1)
            elif line[6].startswith('AUTOMATISCH SPAREN'):
                payee_match = re.match(
                    'AUTOMATISCH SPAREN\s+\d\d\-\d\d\s+(?:NAAR|VAN) (\w\w\d\d(?: \d{4}){3})',
                    line[6])
                if payee_match == None:
                    raise ParseError(
                        self.line_nr,
                        'Cannot parse savings info. (' + line[6] + ')')
                stmt_ln.payee = payee_match.group(1)

        return stmt_ln