support display of history and coming transactions

This commit is contained in:
Romain Bignon 2012-04-09 11:21:28 +02:00
commit 10dc63e4fa
4 changed files with 116 additions and 16 deletions

View file

@ -51,7 +51,6 @@ class SocieteGeneraleBackend(BaseBackend, ICapBank):
yield account
def get_account(self, _id):
print _id
if not _id.isdigit():
raise AccountNotFound()
with self.browser:
@ -60,3 +59,15 @@ class SocieteGeneraleBackend(BaseBackend, ICapBank):
return account
else:
raise AccountNotFound()
def iter_history(self, account):
with self.browser:
for tr in self.browser.iter_history(account._link_id):
if not tr._coming:
yield tr
def iter_coming(self, account):
with self.browser:
for tr in self.browser.iter_history(account._link_id):
if tr._coming:
yield tr

View file

@ -19,7 +19,9 @@
from weboob.tools.browser import BaseBrowser, BrowserIncorrectPassword
from .pages import LoginPage, AccountsList, BadLoginPage
from .pages.accounts_list import AccountsList, AccountHistory
from .pages.login import LoginPage, BadLoginPage
__all__ = ['SocieteGenerale']
@ -34,7 +36,7 @@ class SocieteGenerale(BaseBrowser):
'https://particuliers.societegenerale.fr/.*': LoginPage,
'https://.*.societegenerale.fr//acces/authlgn.html': BadLoginPage,
'.*restitution/cns_listeprestation.html': AccountsList,
# '.*restitution/cns_detailCav.html.*': AccountHistory,
'.*restitution/cns_detailCav.html.*': AccountHistory,
}
def __init__(self, *args, **kwargs):
@ -79,12 +81,11 @@ class SocieteGenerale(BaseBrowser):
return None
def get_history(self, account):
raise NotImplementedError()
def iter_history(self, url):
self.location(url)
#if not self.is_on_page(AccountHistory) or self.page.account.id != account.id:
# self.location(account._link_id)
#return self.page.get_operations()
assert self.is_on_page(AccountHistory)
#self.location(self.page.get_part_url())
def transfer(self, from_id, to_id, amount, reason=None):
raise NotImplementedError()
#assert self.is_on_page(AccountHistoryPart)
return self.page.iter_transactions()

View file

@ -18,14 +18,12 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
from .accounts_list import AccountsList
from .accounts_list import AccountsList, AccountHistory
from .login import LoginPage, BadLoginPage
class AccountPrelevement(AccountsList):
pass
__all__ = ['LoginPage',
'BadLoginPage',
'AccountsList',
'AccountHistory',
]

View file

@ -18,11 +18,19 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
from urlparse import parse_qs, urlparse
from lxml.etree import XML
from cStringIO import StringIO
from decimal import Decimal
import re
from weboob.capabilities.bank import Account
from weboob.tools.browser import BasePage
from weboob.tools.capabilities.bank.transactions import FrenchTransaction
from weboob.tools.browser import BasePage, BrokenPageError
__all__ = ['AccountsList', 'AccountHistory']
class AccountsList(BasePage):
LINKID_REGEXP = re.compile(".*ch4=(\w+).*")
@ -38,7 +46,7 @@ class AccountsList(BasePage):
for td in tr.getiterator('td'):
if td.attrib.get('headers', '') == 'TypeCompte':
a = td.find('a')
account.label = a.find("span").text
account.label = unicode(a.find("span").text)
account._link_id = a.get('href', '')
elif td.attrib.get('headers', '') == 'NumeroCompte':
@ -60,3 +68,85 @@ class AccountsList(BasePage):
l.append(account)
return l
class Transaction(FrenchTransaction):
PATTERNS = [(re.compile(r'^CARTE \w+ RETRAIT DAB.* (?P<dd>\d{2})/(?P<mm>\d{2}) (?P<HH>\d+)H(?P<MM>\d+) (?P<text>.*)'),
FrenchTransaction.TYPE_WITHDRAWAL),
(re.compile(r'^(?P<category>CARTE) \w+ (?P<dd>\d{2})/(?P<mm>\d{2}) (?P<text>.*)'),
FrenchTransaction.TYPE_CARD),
(re.compile(r'^(?P<category>(COTISATION|PRELEVEMENT|TELEREGLEMENT|TIP)) (?P<text>.*)'),
FrenchTransaction.TYPE_ORDER),
(re.compile(r'^(?P<category>VIR(EMEN)?T? \w+) (?P<text>.*)'),
FrenchTransaction.TYPE_TRANSFER),
(re.compile(r'^(CHEQUE) (?P<text>.*)'), FrenchTransaction.TYPE_CHECK),
(re.compile(r'^(FRAIS) (?P<text>.*)'), FrenchTransaction.TYPE_BANK),
(re.compile(r'^(?P<category>ECHEANCEPRET)(?P<text>.*)'),
FrenchTransaction.TYPE_LOAN_PAYMENT),
(re.compile(r'^(?P<category>REMISE CHEQUES)(?P<text>.*)'),
FrenchTransaction.TYPE_DEPOSIT),
]
class AccountHistory(BasePage):
def get_part_url(self):
for script in self.document.getiterator('script'):
if script.text is None:
continue
m = re.search('var listeEcrCavXmlUrl="(.*)";', script.text)
if m:
return m.group(1)
raise BrokenPageError('Unable to find link to history part')
def iter_transactions(self):
url = self.get_part_url()
while 1:
d = XML(self.browser.readurl(url))
el = d.xpath('//dataBody')[0]
s = StringIO(el.text)
doc = self.browser.get_document(s)
for tr in self._iter_transactions(doc):
yield tr
el = d.xpath('//dataHeader')[0]
if int(el.find('suite').text) != 1:
return
url = urlparse(url)
p = parse_qs(url.query)
url = self.browser.buildurl(url.path, n10_nrowcolor=0,
operationNumberPG=el.find('operationNumber').text,
operationTypePG=el.find('operationType').text,
pageNumberPG=el.find('pageNumber').text,
sign=p['sign'][0],
src=p['src'][0])
def _iter_transactions(self, doc):
for i, tr in enumerate(self.parser.select(doc.getroot(), 'tr')):
t = Transaction(i)
t.parse(date=tr.xpath('./td[@headers="Date"]')[0].text,
raw=tr.attrib['title'].strip())
t.set_amount(*reversed([el.text for el in tr.xpath('./td[@class="right"]')]))
t._coming = tr.xpath('./td[@headers="AVenir"]')[0].text
yield t
class _AccountHistory(BasePage):
def iter_operations(self):
for tr in self.document.xpath('//table[@id="tableCompte"]//tr'):
if len(tr.xpath('td[@class="debit"]')) == 0:
continue
id = tr.find('td').find('input').attrib['value']
op = Transaction(id)
op.parse(date=tr.findall('td')[1].text,
raw=tr.findall('td')[2].text.replace(u'\xa0', u''))
debit = tr.xpath('.//td[@class="debit"]')[0].text
credit = tr.xpath('.//td[@class="credit"]')[0].text
op.set_amount(credit, debit)
yield op