support currencies

This commit is contained in:
Romain Bignon 2012-12-06 12:18:26 +01:00
commit d91dad2b2b
17 changed files with 95 additions and 30 deletions

View file

@ -72,15 +72,24 @@ class AccountsPage(BasePage):
account_type = self.ACCOUNT_TYPES.get(div.text.strip(), Account.TYPE_UNKNOWN) account_type = self.ACCOUNT_TYPES.get(div.text.strip(), Account.TYPE_UNKNOWN)
for tr in div.getnext().xpath('.//tbody/tr'): for tr in div.getnext().xpath('.//tbody/tr'):
if not 'id' in tr.attrib:
continue
args = dict(parse_qsl(tr.attrib['id'])) args = dict(parse_qsl(tr.attrib['id']))
tds = tr.findall('td') 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 = Account()
account.id = args['identifiant'] account.id = args['identifiant']
account.label = u' '.join([u''.join([txt.strip() for txt in tds[1].itertext()]), 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() u''.join([txt.strip() for txt in tds[2].itertext()])]).strip()
account.type = account_type 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 = params.copy()
account._params['dialogActionPerformed'] = 'SOLDE' account._params['dialogActionPerformed'] = 'SOLDE'
account._params['attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split('_', 1)[1] account._params['attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split('_', 1)[1]

View file

@ -21,6 +21,7 @@
import re import re
from decimal import Decimal from decimal import Decimal
from weboob.tools.capabilities.bank.transactions import FrenchTransaction
from weboob.capabilities.bank import Account from weboob.capabilities.bank import Account
from weboob.capabilities.base import NotAvailable from weboob.capabilities.base import NotAvailable
from weboob.tools.browser import BasePage, BrokenPageError, BrowserPasswordExpired from weboob.tools.browser import BasePage, BrokenPageError, BrowserPasswordExpired
@ -69,6 +70,7 @@ class AccountsList(BasePage):
account.label = u''+a.text.strip() account.label = u''+a.text.strip()
tds = tr.findall('td') tds = tr.findall('td')
account.currency = account.get_currency(tds[3].find('a').text)
account.balance = self._parse_amount(tds[3].find('a')) account.balance = self._parse_amount(tds[3].find('a'))
if tds[4].find('a') is not None: if tds[4].find('a') is not None:
account.coming = self._parse_amount(tds[4].find('a')) account.coming = self._parse_amount(tds[4].find('a'))
@ -78,7 +80,7 @@ class AccountsList(BasePage):
return account return account
def _parse_amount(self, elem): 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): def get_list(self):
l = [] l = []

View file

@ -24,6 +24,7 @@ from decimal import Decimal
from weboob.capabilities.bank import Account from weboob.capabilities.bank import Account
from weboob.tools.browser import BasePage from weboob.tools.browser import BasePage
from weboob.tools.misc import to_unicode from weboob.tools.misc import to_unicode
from weboob.tools.capabilities.bank.transactions import FrenchTransaction
class AccountsList(BasePage): class AccountsList(BasePage):
@ -31,7 +32,6 @@ class AccountsList(BasePage):
pass pass
def get_list(self): def get_list(self):
l = []
for div in self.document.getiterator('div'): for div in self.document.getiterator('div'):
if div.attrib.get('id', '') == 'synthese-list': if div.attrib.get('id', '') == 'synthese-list':
for tr in div.getiterator('tr'): for tr in div.getiterator('tr'):
@ -57,7 +57,8 @@ class AccountsList(BasePage):
balance = td.text balance = td.text
else: else:
balance = span.text balance = span.text
balance = balance.strip(u' \n\t€+').replace(',', '.').replace(' ', '') account.currency = account.get_currency(balance)
balance = FrenchTransaction.clean_amount(balance)
if balance != "": if balance != "":
account.balance = Decimal(balance) account.balance = Decimal(balance)
else: else:
@ -66,6 +67,4 @@ class AccountsList(BasePage):
else: else:
# because of some weird useless <tr> # because of some weird useless <tr>
if account.id is not None: if account.id is not None:
l.append(account) yield account
return l

View file

@ -23,6 +23,7 @@ from decimal import Decimal
from weboob.capabilities.bank import Account, AccountNotFound from weboob.capabilities.bank import Account, AccountNotFound
from weboob.tools.browser import BasePage from weboob.tools.browser import BasePage
from weboob.tools.misc import to_unicode from weboob.tools.misc import to_unicode
from weboob.tools.capabilities.bank.transactions import FrenchTransaction
__all__ = ['AccountList'] __all__ = ['AccountList']
@ -63,7 +64,8 @@ class AccountList(BasePage):
tmp_balance = tmp[0].text tmp_balance = tmp[0].text
account.id = tmp_id 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) self.account_list.append(account)
def get_account(self, id): def get_account(self, id):

View file

@ -84,7 +84,7 @@ class AccountsPage(BredBasePage):
continue continue
try: 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: except InvalidOperation:
continue continue
@ -117,6 +117,7 @@ class AccountsPage(BredBasePage):
account.id = u'%s.%s' % (args['numero_compte'], args['numero_poste']) account.id = u'%s.%s' % (args['numero_compte'], args['numero_poste'])
account.label = to_unicode(a.attrib.get('alt', a.text.strip())) account.label = to_unicode(a.attrib.get('alt', a.text.strip()))
account.balance = amount account.balance = amount
account.currency = [account.get_currency(txt) for txt in cols[-1].itertext() if len(txt.strip()) > 0][0]
account._card_links = [] account._card_links = []
accounts.append(account) accounts.append(account)

View file

@ -110,7 +110,8 @@ class IndexPage(BasePage):
account.label = unicode(a.text.strip()) account.label = unicode(a.text.strip())
account.type = account_type account.type = account_type
amount = u''.join([txt.strip() for txt in tds[-1].itertext()]) 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 yield account
def go_history(self, id): def go_history(self, id):

View file

@ -69,7 +69,8 @@ class AccountsPage(BasePage):
continue continue
for i in (2,1): 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: if len(balance) > 0:
break break
balance = Decimal(balance) balance = Decimal(balance)
@ -90,6 +91,7 @@ class AccountsPage(BasePage):
account._card_links = [] account._card_links = []
account.balance = balance account.balance = balance
account.currency = currency
accounts[account.id] = account accounts[account.id] = account

View file

@ -114,6 +114,7 @@ class AccountsList(CragrBasePage):
account.label = required_tokens['account_name'] account.label = required_tokens['account_name']
account.id = required_tokens['account_number'] account.id = required_tokens['account_number']
account.balance = FrenchTransaction.clean_amount(required_tokens['account_amount']) 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 # 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)) 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 # we may have found the owner name too

View file

@ -72,6 +72,7 @@ class AccountsPage(BasePage):
account.balance = Decimal(FrenchTransaction.clean_amount(tds[self.CPT_ROW_BALANCE].find("a").text)) 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.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 yield account
return return

View file

@ -69,7 +69,8 @@ class AccountsPage(BasePage):
continue continue
for i in (2,1): 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: if len(balance) > 0:
break break
balance = Decimal(balance) balance = Decimal(balance)
@ -90,6 +91,7 @@ class AccountsPage(BasePage):
account._card_links = [] account._card_links = []
account.balance = balance account.balance = balance
account.currency = currency
accounts[account.id] = account accounts[account.id] = account

View file

@ -22,13 +22,31 @@ import re
import datetime import datetime
from weboob.capabilities.bank import Account from weboob.capabilities.bank import Account
from weboob.tools.capabilities.bank.transactions import Transaction
from weboob.tools.browser import BasePage#, BrokenPageError from weboob.tools.browser import BasePage#, BrokenPageError
from weboob.capabilities import NotAvailable from weboob.capabilities import NotAvailable
from weboob.tools.capabilities.bank.transactions import FrenchTransaction
__all__ = ['AccountsList', 'AccountHistoryPage'] __all__ = ['AccountsList', 'AccountHistoryPage']
class Transaction(FrenchTransaction):
PATTERNS = [(re.compile(u'^(?P<category>CHEQUE)(?P<text>.*)'), FrenchTransaction.TYPE_CHECK),
(re.compile('^(?P<category>FACTURE CARTE) DU (?P<dd>\d{2})(?P<mm>\d{2})(?P<yy>\d{2}) (?P<text>.*?)( CA?R?T?E? ?\d*X*\d*)?$'),
FrenchTransaction.TYPE_CARD),
(re.compile('^(?P<category>(PRELEVEMENT|TELEREGLEMENT|TIP)) (?P<text>.*)'),
FrenchTransaction.TYPE_ORDER),
(re.compile('^(?P<category>ECHEANCEPRET)(?P<text>.*)'), FrenchTransaction.TYPE_LOAN_PAYMENT),
(re.compile('^(?P<category>RETRAIT DAB) (?P<dd>\d{2})/(?P<mm>\d{2})/(?P<yy>\d{2})( (?P<HH>\d+)H(?P<MM>\d+))? (?P<text>.*)'),
FrenchTransaction.TYPE_WITHDRAWAL),
(re.compile('^(?P<category>VIR(EMEN)?T? ((RECU|FAVEUR) TIERS|SEPA RECU)?)( /FRM)?(?P<text>.*)'),
FrenchTransaction.TYPE_TRANSFER),
(re.compile('^(?P<category>REMBOURST)(?P<text>.*)'), FrenchTransaction.TYPE_PAYBACK),
(re.compile('^(?P<category>COMMISSIONS)(?P<text>.*)'), FrenchTransaction.TYPE_BANK),
(re.compile('^(?P<text>(?P<category>REMUNERATION).*)'), FrenchTransaction.TYPE_BANK),
(re.compile('^(?P<category>REMISE CHEQUES)(?P<text>.*)'), FrenchTransaction.TYPE_DEPOSIT),
]
class AccountHistoryPage(BasePage): class AccountHistoryPage(BasePage):
def get_operations(self, _id): def get_operations(self, _id):
"""history, see http://docs.weboob.org/api/capabilities/bank.html?highlight=transaction#weboob.capabilities.bank.Transaction""" """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)): for i in range(len(tables)):
operation = Transaction(len(operations)) operation = Transaction(len(operations))
operation.type = 0
operation.category = NotAvailable
date_oper = tables[i].xpath("./td[2]/text()")[0] date_oper = tables[i].xpath("./td[2]/text()")[0]
date_val = tables[i].xpath("./td[3]/text()")[0] date_val = tables[i].xpath("./td[3]/text()")[0]
label = tables[i].xpath("./td[4]/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()") 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.rdate = datetime.datetime.strptime(date_oper,"%d/%m/%Y")
operation.type = 0
if amount[1] == u'\xa0': if amount[1] == u'\xa0':
amount = amount[0].replace(u"\xa0", "").replace(",", ".").strip() amount = amount[0]
else: else:
amount = amount[1].replace(u"\xa0", "").replace(",", ".").strip() amount = amount[1]
operation.amount = Decimal(amount)
operation.category = NotAvailable operation.set_amount(amount)
operations.append(operation) 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.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
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 # 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", "") #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", "")

View file

@ -53,7 +53,8 @@ class AccountsListPage(BasePage):
tag = tds[2].find('font') tag = tds[2].find('font')
if tag is None: if tag is None:
tag = tds[2] 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 account.coming = NotAvailable
yield account yield account

View file

@ -24,6 +24,7 @@ import re
from weboob.capabilities.bank import Account from weboob.capabilities.bank import Account
from weboob.capabilities.base import NotAvailable from weboob.capabilities.base import NotAvailable
from weboob.tools.browser import BasePage from weboob.tools.browser import BasePage
from weboob.tools.capabilities.bank.transactions import FrenchTransaction
__all__ = ['AccountsList'] __all__ = ['AccountsList']
@ -47,7 +48,7 @@ class AccountsList(BasePage):
linkbis = self.document.xpath(urltofind).pop() linkbis = self.document.xpath(urltofind).pop()
if linkbis.text == link.text: if linkbis.text == link.text:
linkbis = self.document.xpath(urltofind)[1] linkbis = self.document.xpath(urltofind)[1]
account.balance = Decimal(linkbis.text.replace('.', '').\ account.balance = Decimal(FrenchTransaction.clean_amount(linkbis.text))
replace(' ', '').replace(',', '.')) account.currency = account.get_currency(linkbis.text)
account.coming = NotAvailable account.coming = NotAvailable
yield account yield account

View file

@ -168,10 +168,11 @@ class AccountsPage(BasePage):
if not div.text.strip(): if not div.text.strip():
div = div.find('div') div = div.find('div')
account.label=u''+div.text.strip() 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: if '-' in balance:
balance='-'+balance.replace('-', '') balance='-'+balance.replace('-', '')
account.balance=Decimal(balance) account.balance=Decimal(balance)
account.currency = account.get_currency(a.text)
self.logger.debug('%s Type: %s' % (account.label, account._type)) self.logger.debug('%s Type: %s' % (account.label, account._type))
l.append(account) l.append(account)
if link.startswith('/outil/UWCB/UWCBEncours'): if link.startswith('/outil/UWCB/UWCBEncours'):
@ -181,7 +182,7 @@ class AccountsPage(BasePage):
account = l[-1] account = l[-1]
coming = a.text.replace(u"\u00A0",'').replace(' ','').replace('.','').replace('+','').replace(',','.').strip() coming = FrenchTransaction.clean_amount(a.text)
if '-' in coming: if '-' in coming:
coming = '-'+coming.replace('-', '') coming = '-'+coming.replace('-', '')
if not account.coming: if not account.coming:

View file

@ -64,7 +64,8 @@ class AccountsList(BasePage):
elif td.attrib.get('headers', '') == 'Solde': elif td.attrib.get('headers', '') == 'Solde':
balance = td.find('div').text balance = td.find('div').text
if balance != None: if balance != None:
balance = balance.replace(u'\xa0','').replace(',','.') account.currency = account.get_currency(balance)
balance = FrenchTransaction.clean_amount(balance)
account.balance = Decimal(balance) account.balance = Decimal(balance)
else: else:
account.balance = Decimal(0) account.balance = Decimal(0)

View file

@ -18,6 +18,7 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>. # along with weboob. If not, see <http://www.gnu.org/licenses/>.
import re
from datetime import date, datetime from datetime import date, datetime
from .base import CapBaseObject, Field, StringField, DateField, DecimalField, IntField, UserError from .base import CapBaseObject, Field, StringField, DateField, DecimalField, IntField, UserError
@ -40,6 +41,25 @@ class TransferError(UserError):
A transfer has failed. 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): class Recipient(CapBaseObject):
""" """
Recipient of a transfer. Recipient of a transfer.
@ -50,7 +70,7 @@ class Recipient(CapBaseObject):
def __init__(self): def __init__(self):
CapBaseObject.__init__(self, 0) CapBaseObject.__init__(self, 0)
class Account(Recipient): class Account(Recipient, Currency):
""" """
Bank account. Bank account.
@ -68,6 +88,7 @@ class Account(Recipient):
type = IntField('Type of account', default=TYPE_UNKNOWN) type = IntField('Type of account', default=TYPE_UNKNOWN)
balance = DecimalField('Balance on this bank account') balance = DecimalField('Balance on this bank account')
coming = DecimalField('Coming balance') coming = DecimalField('Coming balance')
currency = IntField('Currency', default=Currency.CUR_UNKNOWN)
def __repr__(self): def __repr__(self):
return u"<Account id=%r label=%r>" % (self.id, self.label) return u"<Account id=%r label=%r>" % (self.id, self.label)

View file

@ -20,6 +20,7 @@
from decimal import Decimal from decimal import Decimal
import datetime import datetime
import re
from weboob.capabilities.bank import Transaction from weboob.capabilities.bank import Transaction
from weboob.capabilities import NotAvailable from weboob.capabilities import NotAvailable
@ -40,8 +41,8 @@ class FrenchTransaction(Transaction):
""" """
Clean a string containing an amount. Clean a string containing an amount.
""" """
return text.replace(' ', '').replace('.','').replace(u'\xa0', '') \ text = text.replace('.','').replace(',','.')
.replace(',','.').strip(u' \t\u20ac\xa0\x80\n\rEUR') return re.sub(u'[^\d\-\.]', '', text)
def set_amount(self, credit='', debit=''): def set_amount(self, credit='', debit=''):
""" """