diff --git a/modules/banquepopulaire/pages.py b/modules/banquepopulaire/pages.py index 4be05a4a..56a21324 100644 --- a/modules/banquepopulaire/pages.py +++ b/modules/banquepopulaire/pages.py @@ -72,15 +72,24 @@ class AccountsPage(BasePage): account_type = self.ACCOUNT_TYPES.get(div.text.strip(), Account.TYPE_UNKNOWN) for tr in div.getnext().xpath('.//tbody/tr'): + if not 'id' in tr.attrib: + continue + args = dict(parse_qsl(tr.attrib['id'])) tds = tr.findall('td') + if len(tds) < 4 or not 'identifiant' in args: + self.logger.warning('Unable to parse an account') + continue + account = Account() account.id = args['identifiant'] account.label = u' '.join([u''.join([txt.strip() for txt in tds[1].itertext()]), u''.join([txt.strip() for txt in tds[2].itertext()])]).strip() account.type = account_type - account.balance = Decimal(FrenchTransaction.clean_amount(u''.join([txt.strip() for txt in tds[3].itertext()]))) + balance = u''.join([txt.strip() for txt in tds[3].itertext()]) + account.balance = Decimal(FrenchTransaction.clean_amount(balance)) + account.currency = account.get_currency(balance) account._params = params.copy() account._params['dialogActionPerformed'] = 'SOLDE' account._params['attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split('_', 1)[1] diff --git a/modules/bnporc/pages/accounts_list.py b/modules/bnporc/pages/accounts_list.py index 5f664b1a..3141754e 100644 --- a/modules/bnporc/pages/accounts_list.py +++ b/modules/bnporc/pages/accounts_list.py @@ -21,6 +21,7 @@ import re from decimal import Decimal +from weboob.tools.capabilities.bank.transactions import FrenchTransaction from weboob.capabilities.bank import Account from weboob.capabilities.base import NotAvailable from weboob.tools.browser import BasePage, BrokenPageError, BrowserPasswordExpired @@ -69,6 +70,7 @@ class AccountsList(BasePage): account.label = u''+a.text.strip() tds = tr.findall('td') + account.currency = account.get_currency(tds[3].find('a').text) account.balance = self._parse_amount(tds[3].find('a')) if tds[4].find('a') is not None: account.coming = self._parse_amount(tds[4].find('a')) @@ -78,7 +80,7 @@ class AccountsList(BasePage): return account def _parse_amount(self, elem): - return Decimal(elem.text.replace('.', '').replace(',', '.').strip(u' \t\u20ac\xa0€\n\r')) + return Decimal(FrenchTransaction.clean_amount(elem.text)) def get_list(self): l = [] diff --git a/modules/boursorama/pages/accounts_list.py b/modules/boursorama/pages/accounts_list.py index 951c06a6..7dc4956e 100644 --- a/modules/boursorama/pages/accounts_list.py +++ b/modules/boursorama/pages/accounts_list.py @@ -24,6 +24,7 @@ from decimal import Decimal from weboob.capabilities.bank import Account from weboob.tools.browser import BasePage from weboob.tools.misc import to_unicode +from weboob.tools.capabilities.bank.transactions import FrenchTransaction class AccountsList(BasePage): @@ -31,7 +32,6 @@ class AccountsList(BasePage): pass def get_list(self): - l = [] for div in self.document.getiterator('div'): if div.attrib.get('id', '') == 'synthese-list': for tr in div.getiterator('tr'): @@ -57,7 +57,8 @@ class AccountsList(BasePage): balance = td.text else: balance = span.text - balance = balance.strip(u' \n\t€+').replace(',', '.').replace(' ', '') + account.currency = account.get_currency(balance) + balance = FrenchTransaction.clean_amount(balance) if balance != "": account.balance = Decimal(balance) else: @@ -66,6 +67,4 @@ class AccountsList(BasePage): else: # because of some weird useless if account.id is not None: - l.append(account) - - return l + yield account diff --git a/modules/bp/pages/accountlist.py b/modules/bp/pages/accountlist.py index 8a538bf7..6f68d04d 100644 --- a/modules/bp/pages/accountlist.py +++ b/modules/bp/pages/accountlist.py @@ -23,6 +23,7 @@ from decimal import Decimal from weboob.capabilities.bank import Account, AccountNotFound from weboob.tools.browser import BasePage from weboob.tools.misc import to_unicode +from weboob.tools.capabilities.bank.transactions import FrenchTransaction __all__ = ['AccountList'] @@ -63,7 +64,8 @@ class AccountList(BasePage): tmp_balance = tmp[0].text account.id = tmp_id - account.balance = Decimal(''.join(tmp_balance.replace('.','').replace(',','.').split())) + account.currency = account.get_currency(tmp_balance) + account.balance = Decimal(FrenchTransaction.clean_amount(tmp_balance)) self.account_list.append(account) def get_account(self, id): diff --git a/modules/bred/pages.py b/modules/bred/pages.py index 58ac41a7..f5c340cc 100644 --- a/modules/bred/pages.py +++ b/modules/bred/pages.py @@ -84,7 +84,7 @@ class AccountsPage(BredBasePage): continue try: - amount = sum([Decimal(txt.strip(' EUR').replace(' ', '').replace(',', '.')) for txt in cols[-1].itertext() if len(txt.strip()) > 0]) + amount = sum([Decimal(FrenchTransaction.clean_amount(txt)) for txt in cols[-1].itertext() if len(txt.strip()) > 0]) except InvalidOperation: continue @@ -117,6 +117,7 @@ class AccountsPage(BredBasePage): account.id = u'%s.%s' % (args['numero_compte'], args['numero_poste']) account.label = to_unicode(a.attrib.get('alt', a.text.strip())) account.balance = amount + account.currency = [account.get_currency(txt) for txt in cols[-1].itertext() if len(txt.strip()) > 0][0] account._card_links = [] accounts.append(account) diff --git a/modules/caissedepargne/pages.py b/modules/caissedepargne/pages.py index 4d71d694..794d7a1e 100644 --- a/modules/caissedepargne/pages.py +++ b/modules/caissedepargne/pages.py @@ -110,7 +110,8 @@ class IndexPage(BasePage): account.label = unicode(a.text.strip()) account.type = account_type amount = u''.join([txt.strip() for txt in tds[-1].itertext()]) - account.balance = Decimal(FrenchTransaction.clean_amount(amount.rstrip(' EUR'))) + account.balance = Decimal(FrenchTransaction.clean_amount(amount)) + account.currency = account.get_currency(amount) yield account def go_history(self, id): diff --git a/modules/cic/pages.py b/modules/cic/pages.py index 0574eb24..db852d7c 100644 --- a/modules/cic/pages.py +++ b/modules/cic/pages.py @@ -69,7 +69,8 @@ class AccountsPage(BasePage): continue for i in (2,1): - balance = FrenchTransaction.clean_amount(tr.getchildren()[i].text.strip(' EUR')) + balance = FrenchTransaction.clean_amount(tr.getchildren()[i].text) + currency = Account.get_currency(tr.getchildren()[i].text) if len(balance) > 0: break balance = Decimal(balance) @@ -90,6 +91,7 @@ class AccountsPage(BasePage): account._card_links = [] account.balance = balance + account.currency = currency accounts[account.id] = account diff --git a/modules/cragr/pages/accounts_list.py b/modules/cragr/pages/accounts_list.py index 1d13ba17..fed8e838 100644 --- a/modules/cragr/pages/accounts_list.py +++ b/modules/cragr/pages/accounts_list.py @@ -114,6 +114,7 @@ class AccountsList(CragrBasePage): account.label = required_tokens['account_name'] account.id = required_tokens['account_number'] account.balance = FrenchTransaction.clean_amount(required_tokens['account_amount']) + account.currency = account.get_currency(required_tokens['account_amount']) # we found almost all required information to create an account object self.logger.debug('Found account %s with number %s and balance = %.2f' % (account.label, account.id, account.balance)) # we may have found the owner name too diff --git a/modules/creditcooperatif/pages.py b/modules/creditcooperatif/pages.py index cf221ed8..c6f4f772 100644 --- a/modules/creditcooperatif/pages.py +++ b/modules/creditcooperatif/pages.py @@ -72,6 +72,7 @@ class AccountsPage(BasePage): account.balance = Decimal(FrenchTransaction.clean_amount(tds[self.CPT_ROW_BALANCE].find("a").text)) account.coming = Decimal(FrenchTransaction.clean_amount( tds[self.CPT_ROW_ENCOURS].find("a").text)) + account.currency = account.get_currency(tds[self.CPT_ROW_BALANCE].find("a").text) yield account return diff --git a/modules/creditmutuel/pages.py b/modules/creditmutuel/pages.py index 59b0734c..3a533a07 100644 --- a/modules/creditmutuel/pages.py +++ b/modules/creditmutuel/pages.py @@ -69,7 +69,8 @@ class AccountsPage(BasePage): continue for i in (2,1): - balance = FrenchTransaction.clean_amount(tr.getchildren()[i].text.strip(' EUR')) + balance = FrenchTransaction.clean_amount(tr.getchildren()[i].text) + currency = Account.get_currency(tr.getchildren()[i].text) if len(balance) > 0: break balance = Decimal(balance) @@ -90,6 +91,7 @@ class AccountsPage(BasePage): account._card_links = [] account.balance = balance + account.currency = currency accounts[account.id] = account diff --git a/modules/fortuneo/pages/accounts_list.py b/modules/fortuneo/pages/accounts_list.py index 1b8f1221..e61a8d5c 100644 --- a/modules/fortuneo/pages/accounts_list.py +++ b/modules/fortuneo/pages/accounts_list.py @@ -22,13 +22,31 @@ import re import datetime from weboob.capabilities.bank import Account -from weboob.tools.capabilities.bank.transactions import Transaction from weboob.tools.browser import BasePage#, BrokenPageError from weboob.capabilities import NotAvailable +from weboob.tools.capabilities.bank.transactions import FrenchTransaction __all__ = ['AccountsList', 'AccountHistoryPage'] + +class Transaction(FrenchTransaction): + PATTERNS = [(re.compile(u'^(?PCHEQUE)(?P.*)'), FrenchTransaction.TYPE_CHECK), + (re.compile('^(?PFACTURE CARTE) DU (?P
\d{2})(?P\d{2})(?P\d{2}) (?P.*?)( CA?R?T?E? ?\d*X*\d*)?$'), + FrenchTransaction.TYPE_CARD), + (re.compile('^(?P(PRELEVEMENT|TELEREGLEMENT|TIP)) (?P.*)'), + FrenchTransaction.TYPE_ORDER), + (re.compile('^(?PECHEANCEPRET)(?P.*)'), FrenchTransaction.TYPE_LOAN_PAYMENT), + (re.compile('^(?PRETRAIT DAB) (?P
\d{2})/(?P\d{2})/(?P\d{2})( (?P\d+)H(?P\d+))? (?P.*)'), + FrenchTransaction.TYPE_WITHDRAWAL), + (re.compile('^(?PVIR(EMEN)?T? ((RECU|FAVEUR) TIERS|SEPA RECU)?)( /FRM)?(?P.*)'), + FrenchTransaction.TYPE_TRANSFER), + (re.compile('^(?PREMBOURST)(?P.*)'), FrenchTransaction.TYPE_PAYBACK), + (re.compile('^(?PCOMMISSIONS)(?P.*)'), FrenchTransaction.TYPE_BANK), + (re.compile('^(?P(?PREMUNERATION).*)'), FrenchTransaction.TYPE_BANK), + (re.compile('^(?PREMISE CHEQUES)(?P.*)'), FrenchTransaction.TYPE_DEPOSIT), + ] + class AccountHistoryPage(BasePage): def get_operations(self, _id): """history, see http://docs.weboob.org/api/capabilities/bank.html?highlight=transaction#weboob.capabilities.bank.Transaction""" @@ -42,23 +60,23 @@ class AccountHistoryPage(BasePage): for i in range(len(tables)): operation = Transaction(len(operations)) + operation.type = 0 + operation.category = NotAvailable date_oper = tables[i].xpath("./td[2]/text()")[0] date_val = tables[i].xpath("./td[3]/text()")[0] label = tables[i].xpath("./td[4]/text()")[0] - operation.label = operation.raw = unicode(label.strip()) amount = tables[i].xpath("./td[5]/text() | ./td[6]/text()") - operation.date = datetime.datetime.strptime(date_val, "%d/%m/%Y") + + operation.parse(date=date_val, raw=label) operation.rdate = datetime.datetime.strptime(date_oper,"%d/%m/%Y") - operation.type = 0 if amount[1] == u'\xa0': - amount = amount[0].replace(u"\xa0", "").replace(",", ".").strip() + amount = amount[0] else: - amount = amount[1].replace(u"\xa0", "").replace(",", ".").strip() - operation.amount = Decimal(amount) + amount = amount[1] - operation.category = NotAvailable + operation.set_amount(amount) operations.append(operation) @@ -75,7 +93,8 @@ class AccountsList(BasePage): account.id = cpt.xpath("./span[1]/text()")[0].replace(u"\xa0", "").replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xb0", '').replace(" ", "").replace('N', '') # account balance - account.balance = Decimal(cpt.xpath("./span[2]/text()")[0].replace("+", "").replace(u"\xa0", "").replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(" ", "")) + account.balance = Decimal(Transaction.clean_amount(cpt.xpath("./span[2]/text()")[0])) + account.currency = account.get_currency(cpt.xpath("./span[2]/text()")[0]) # account coming TODO #mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]/a[@class='lien_synthese_encours']/span/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "") diff --git a/modules/hsbc/pages/accounts.py b/modules/hsbc/pages/accounts.py index 91e331e5..57f165d2 100644 --- a/modules/hsbc/pages/accounts.py +++ b/modules/hsbc/pages/accounts.py @@ -53,7 +53,8 @@ class AccountsListPage(BasePage): tag = tds[2].find('font') if tag is None: tag = tds[2] - account.balance = Decimal(tag.text.replace('.','').replace(',','.').replace(' ', '').strip(u' \t\u20ac\xa0€\n\r')) + account.balance = Decimal(FrenchTransaction.clean_amount(tag.text)) + account.currency = account.get_currency(tag.text) account.coming = NotAvailable yield account diff --git a/modules/ing/pages/accounts_list.py b/modules/ing/pages/accounts_list.py index 138be836..6391aaaa 100644 --- a/modules/ing/pages/accounts_list.py +++ b/modules/ing/pages/accounts_list.py @@ -24,6 +24,7 @@ import re from weboob.capabilities.bank import Account from weboob.capabilities.base import NotAvailable from weboob.tools.browser import BasePage +from weboob.tools.capabilities.bank.transactions import FrenchTransaction __all__ = ['AccountsList'] @@ -47,7 +48,7 @@ class AccountsList(BasePage): linkbis = self.document.xpath(urltofind).pop() if linkbis.text == link.text: linkbis = self.document.xpath(urltofind)[1] - account.balance = Decimal(linkbis.text.replace('.', '').\ - replace(' ', '').replace(',', '.')) + account.balance = Decimal(FrenchTransaction.clean_amount(linkbis.text)) + account.currency = account.get_currency(linkbis.text) account.coming = NotAvailable yield account diff --git a/modules/lcl/pages.py b/modules/lcl/pages.py index 3a2bc2b3..b4938c5e 100644 --- a/modules/lcl/pages.py +++ b/modules/lcl/pages.py @@ -168,10 +168,11 @@ class AccountsPage(BasePage): if not div.text.strip(): div = div.find('div') account.label=u''+div.text.strip() - balance=a.text.replace(u"\u00A0",'').replace(' ','').replace('.','').replace('+','').replace(',','.').strip() + balance = FrenchTransaction.clean_amount(a.text) if '-' in balance: balance='-'+balance.replace('-', '') account.balance=Decimal(balance) + account.currency = account.get_currency(a.text) self.logger.debug('%s Type: %s' % (account.label, account._type)) l.append(account) if link.startswith('/outil/UWCB/UWCBEncours'): @@ -181,7 +182,7 @@ class AccountsPage(BasePage): account = l[-1] - coming = a.text.replace(u"\u00A0",'').replace(' ','').replace('.','').replace('+','').replace(',','.').strip() + coming = FrenchTransaction.clean_amount(a.text) if '-' in coming: coming = '-'+coming.replace('-', '') if not account.coming: diff --git a/modules/societegenerale/pages/accounts_list.py b/modules/societegenerale/pages/accounts_list.py index 168d27bc..f42ceb2b 100644 --- a/modules/societegenerale/pages/accounts_list.py +++ b/modules/societegenerale/pages/accounts_list.py @@ -64,7 +64,8 @@ class AccountsList(BasePage): elif td.attrib.get('headers', '') == 'Solde': balance = td.find('div').text if balance != None: - balance = balance.replace(u'\xa0','').replace(',','.') + account.currency = account.get_currency(balance) + balance = FrenchTransaction.clean_amount(balance) account.balance = Decimal(balance) else: account.balance = Decimal(0) diff --git a/weboob/capabilities/bank.py b/weboob/capabilities/bank.py index 022e148d..df8803b3 100644 --- a/weboob/capabilities/bank.py +++ b/weboob/capabilities/bank.py @@ -18,6 +18,7 @@ # along with weboob. If not, see . +import re from datetime import date, datetime from .base import CapBaseObject, Field, StringField, DateField, DecimalField, IntField, UserError @@ -40,6 +41,25 @@ class TransferError(UserError): A transfer has failed. """ +class Currency: + CUR_UNKNOWN = 0 + CUR_EUR = 1 + CUR_CHF = 2 + CUR_USD = 3 + + TXT2CUR = {u'€': CUR_EUR, + u'EUR': CUR_EUR, + u'CHF': CUR_CHF, + u'$': CUR_USD, + u'USD': CUR_USD, + } + + @classmethod + def get_currency(klass, text): + text = re.sub(u'[^A-Za-z€]', '', text) + return klass.TXT2CUR.get(text, klass.CUR_UNKNOWN) + + class Recipient(CapBaseObject): """ Recipient of a transfer. @@ -50,7 +70,7 @@ class Recipient(CapBaseObject): def __init__(self): CapBaseObject.__init__(self, 0) -class Account(Recipient): +class Account(Recipient, Currency): """ Bank account. @@ -68,6 +88,7 @@ class Account(Recipient): type = IntField('Type of account', default=TYPE_UNKNOWN) balance = DecimalField('Balance on this bank account') coming = DecimalField('Coming balance') + currency = IntField('Currency', default=Currency.CUR_UNKNOWN) def __repr__(self): return u"" % (self.id, self.label) diff --git a/weboob/tools/capabilities/bank/transactions.py b/weboob/tools/capabilities/bank/transactions.py index b1f97b00..192fbb1e 100644 --- a/weboob/tools/capabilities/bank/transactions.py +++ b/weboob/tools/capabilities/bank/transactions.py @@ -20,6 +20,7 @@ from decimal import Decimal import datetime +import re from weboob.capabilities.bank import Transaction from weboob.capabilities import NotAvailable @@ -40,8 +41,8 @@ class FrenchTransaction(Transaction): """ Clean a string containing an amount. """ - return text.replace(' ', '').replace('.','').replace(u'\xa0', '') \ - .replace(',','.').strip(u' \t\u20ac\xa0\x80€\n\rEUR') + text = text.replace('.','').replace(',','.') + return re.sub(u'[^\d\-\.]', '', text) def set_amount(self, credit='', debit=''): """