From d552e432674791d776eaba297b6e244a5783ee45 Mon Sep 17 00:00:00 2001 From: Florent Date: Fri, 22 Feb 2013 14:40:20 +0100 Subject: [PATCH] Get transaction history on the new site --- modules/ing/browser.py | 32 +++++++++++--------- modules/ing/pages/accounts_list.py | 47 ++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/modules/ing/browser.py b/modules/ing/browser.py index 842af179..e579415e 100644 --- a/modules/ing/browser.py +++ b/modules/ing/browser.py @@ -16,6 +16,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with weboob. If not, see . +import urllib import hashlib from weboob.tools.browser import BaseBrowser, BrowserIncorrectPassword @@ -33,7 +34,7 @@ class Ing(BaseBrowser): PROTOCOL = 'https' DEBUG_HTTP = False #DEBUG_HTTP = True - ENCODING = None # refer to the HTML encoding + ENCODING = "utf-8" PAGES = {'.*pages/index.jsf.*': AccountsList, '.*displayLogin.jsf.*': LoginPage, '.*accountDetail.jsf.*': AccountHistory, @@ -48,10 +49,11 @@ class Ing(BaseBrowser): CERTHASH = "fba557b387cccc3d71ba038f9ef1de4d71541d7954744c79f6a7ff5f3cd4dc12" loginpage = '/public/displayLogin.jsf' - accountspage = '/general?command=displayTRAccountSummary' + accountspage = '/protected/pages/index.jsf' transferpage = '/protected/pages/cc/transfer/transferManagement.jsf' dotransferpage = '/general?command=DisplayDoTransferCommand' valtransferpage = '/protected/pages/cc/transfer/create/transferCreateValidation.jsf' + where = None def __init__(self, *args, **kwargs): self.birthday = kwargs.pop('birthday', None) @@ -81,7 +83,7 @@ class Ing(BaseBrowser): def get_accounts_list(self): if not self.is_on_page(AccountsList): self.location(self.accountspage) - + self.where = "start" return self.page.get_list() def get_account(self, id): @@ -105,17 +107,19 @@ class Ing(BaseBrowser): def get_history(self, account): if not isinstance(account, Account): account = self.get_account(account) - # The first and the second letter of the label are the account type - if account.label[0:2] == "CC": - self.location('/protected/pages/cc/accountDetail.jsf?account=%s' - % int(account._index)) - elif account.label[0:2] == "LA" or account.label[0:3] == "LEO": - # we want "displayTRHistoriqueLA" but this fucking page - # is not directly available... - self.location('/general?command=goToAccount&account=%d&zone=COMPTE' - % int(account._index)) - else: - raise NotImplementedError() + if self.where != "start": + self.location(self.accountspage) + data = {"AJAX:EVENTS_COUNT": 1, + "AJAXREQUEST": "_viewRoot", + "ajaxSingle": "index:setAccount", + "autoScroll": "", + "index": "index", + "index:setAccount": "index:setAccount", + "javax.faces.ViewState": account._jid, + "cptnbr": account._id + } + self.location(self.accountspage, urllib.urlencode(data)) + self.where = "history" while 1: hashlist = [] for transaction in self.page.get_transactions(): diff --git a/modules/ing/pages/accounts_list.py b/modules/ing/pages/accounts_list.py index 23f93f19..0f91a923 100644 --- a/modules/ing/pages/accounts_list.py +++ b/modules/ing/pages/accounts_list.py @@ -19,9 +19,11 @@ from decimal import Decimal +from datetime import date import re +import hashlib -from weboob.capabilities.bank import Account, Currency +from weboob.capabilities.bank import Account, Currency, Transaction from weboob.capabilities.base import NotAvailable from weboob.tools.browser import BasePage, BrowserUnavailable from weboob.tools.capabilities.bank.transactions import FrenchTransaction @@ -29,17 +31,29 @@ from weboob.tools.capabilities.bank.transactions import FrenchTransaction __all__ = ['AccountsList'] +class Transaction(FrenchTransaction): + PATTERNS = [(re.compile(u'^retrait dab (?P
\d{2})/(?P\d{2})/(?P\d{4}) (?P.*)'), FrenchTransaction.TYPE_WITHDRAWAL), + (re.compile(u'^carte (?P
\d{2})/(?P\d{2})/(?P\d{4}) (?P.*)'), Transaction.TYPE_CARD), + (re.compile(u'^virement ((sepa emis vers|emis vers|recu|emis)?) (?P.*)'), Transaction.TYPE_TRANSFER), + (re.compile(u'^prelevement (?P.*)'), Transaction.TYPE_ORDER), + ] + class AccountsList(BasePage): def on_loaded(self): pass - + + monthvalue = {u'janv.': '1', u'févr.': '2', u'mars.': '3', u'avri.': '4', + u'mai.': '5', u'juin.': '6', u'juil.': '7', u'août.': '8', + u'sept.': '9', u'octo.': '10', u'nove.': '11', u'déce.': '12', + } def get_list(self): # TODO: no idea abount how proxy account are displayed for a in self.document.xpath('//a[@class="mainclic"]'): account = Account() account.currency = Currency.CUR_EUR account.id = unicode(a.find('span[@class="account-number"]').text) + account._id = account.id account.label = unicode(a.find('span[@class="title"]').text) balance = a.find('span[@class="solde"]/label').text account.balance = Decimal(FrenchTransaction.clean_amount(balance)) @@ -50,4 +64,33 @@ class AccountsList(BasePage): account.id = "LA-" + account.id elif "Orange" in account.label: account.id = "LEO-" + account.id + jid = self.document.find('//input[@name="javax.faces.ViewState"]') + account._jid = jid.attrib['value'] yield account + + def get_transactions(self): + for table in self.document.xpath('//table[@cellpadding="0"]'): + try: + textdate = table.find('.//td[@class="elmt tdate"]').text_content() + except AttributeError: + continue + frenchmonth = textdate.split(' ')[1] + month = self.monthvalue[frenchmonth] + textdate = textdate.replace(' ', '') + textdate = textdate.replace(frenchmonth, '/%s/' %month) + # We use lower for compatibility with old website + textraw = table.find('.//td[@class="elmt lbl"]').text_content().strip().lower() + # The id will be rewrite + op = Transaction(1) + amount = op.clean_amount(table.xpath('.//td[starts-with(@class, "elmt amount")]')[0].text_content()) + id = hashlib.md5(textdate + textraw.encode('utf-8') + amount.encode('utf-8')).hexdigest() + op.id = id + op.parse(date = date(*reversed([int(x) for x in textdate.split('/')])), + raw = textraw) + # force the use of website category + #op.category = unicode(tr.find('td[@class="op_type"]').text) + op.amount = Decimal(amount) + yield op + + def islast(self): + return True