From 8b9073de127bc2f386f2011f2b75a3186395b1ae Mon Sep 17 00:00:00 2001 From: Romain Bignon Date: Sun, 9 Mar 2014 15:43:51 +0100 Subject: [PATCH] add specific filters for browser2 --- .../tools/capabilities/bank/transactions.py | 122 +++++++++++++++++- 1 file changed, 118 insertions(+), 4 deletions(-) diff --git a/weboob/tools/capabilities/bank/transactions.py b/weboob/tools/capabilities/bank/transactions.py index 5dff3930..dc04ce2f 100644 --- a/weboob/tools/capabilities/bank/transactions.py +++ b/weboob/tools/capabilities/bank/transactions.py @@ -18,15 +18,17 @@ # along with weboob. If not, see . -from decimal import Decimal +from decimal import Decimal, InvalidOperation import datetime import re -from weboob.capabilities.bank import Transaction +from weboob.capabilities.bank import Transaction, Account from weboob.capabilities import NotAvailable from weboob.tools.misc import to_unicode from weboob.tools.log import getLogger +from weboob.tools.browser2.filters import Filter, CleanText, CleanDecimal + __all__ = ['FrenchTransaction'] @@ -37,8 +39,8 @@ class FrenchTransaction(Transaction): """ PATTERNS = [] - def __init__(self, *args, **kwargs): - Transaction.__init__(self, *args, **kwargs) + def __init__(self, id='', *args, **kwargs): + Transaction.__init__(self, id, *args, **kwargs) self._logger = getLogger('FrenchTransaction') @classmethod @@ -163,3 +165,115 @@ class FrenchTransaction(Transaction): self._logger.warning('Unable to date in label %r: %s' % (self.raw, e)) return + + class Date(CleanText): + def __call__(self, item): + date = super(FrenchTransaction.Date, self).__call__(item) + item.obj.rdate = date + return date + + def filter(self, date): + date = super(FrenchTransaction.Date, self).filter(date) + if date is None: + return NotAvailable + + if not isinstance(date, (datetime.date, datetime.datetime)): + if date.isdigit() and len(date) == 8: + date = datetime.date(int(date[4:8]), int(date[2:4]), int(date[0:2])) + elif '/' in date: + date = datetime.date(*reversed(map(int, date.split('/')))) + if not isinstance(date, (datetime.date, datetime.datetime)): + date = NotAvailable + elif date.year < 100: + date = date.replace(year=2000 + date.year) + + return date + + @classmethod + def Raw(klass, *args, **kwargs): + patterns = klass.PATTERNS + class Filter(CleanText): + def __call__(self, item): + raw = super(Filter, self).__call__(item) + item.obj.category = NotAvailable + if ' ' in raw: + item.obj.category, useless, item.obj.label = [part.strip() for part in raw.partition(' ')] + else: + item.obj.label = raw + + for pattern, _type in patterns: + m = pattern.match(raw) + if m: + args = m.groupdict() + + def inargs(key): + """ + inner function to check if a key is in args, + and is not None. + """ + return args.get(key, None) is not None + + item.obj.type = _type + if inargs('text'): + item.obj.label = args['text'].strip() + if inargs('category'): + item.obj.category = args['category'].strip() + + # Set date from information in raw label. + if inargs('dd') and inargs('mm'): + dd = int(args['dd']) + mm = int(args['mm']) + + if inargs('yy'): + yy = int(args['yy']) + else: + d = item.obj.date + try: + d = d.replace(month=mm, day=dd) + except ValueError: + d = d.replace(year=d.year-1, month=mm, day=dd) + + yy = d.year + if d > item.obj.date: + yy -= 1 + + if yy < 100: + yy += 2000 + + try: + if inargs('HH') and inargs('MM'): + item.obj.rdate = datetime.datetime(yy, mm, dd, int(args['HH']), int(args['MM'])) + else: + item.obj.rdate = datetime.date(yy, mm, dd) + except ValueError as e: + self._logger.warning('Unable to date in label %r: %s' % (raw, e)) + + break + + return raw + def filter(self, text): + text = super(Filter, self).filter(text) + return to_unicode(text.replace(u'\n', u' ').strip()) + return Filter(*args, **kwargs) + + class Currency(CleanText): + def filter(self, text): + text = super(FrenchTransaction.Currency, self).filter(text) + return Account.get_currency(text) + + class Amount(Filter): + def __init__(self, credit, debit=None): + self.credit_selector = credit + self.debit_selector = debit + + def __call__(self, item): + if self.debit_selector: + try: + return - abs(CleanDecimal(self.debit_selector)(item)) + except InvalidOperation: + pass + + try: + return CleanDecimal(self.credit_selector)(item) + except InvalidOperation: + return Decimal('0')