support deferred debit cards
This commit is contained in:
parent
a3d1c8daa5
commit
85c9554733
3 changed files with 86 additions and 46 deletions
|
|
@ -60,15 +60,12 @@ class SocieteGeneraleBackend(BaseBackend, ICapBank):
|
||||||
|
|
||||||
def iter_history(self, account):
|
def iter_history(self, account):
|
||||||
with self.browser:
|
with self.browser:
|
||||||
for tr in self.browser.iter_history(account._link_id):
|
for tr in self.browser.iter_history(account):
|
||||||
if not tr._coming:
|
if not tr._coming:
|
||||||
yield tr
|
yield tr
|
||||||
|
|
||||||
def iter_coming(self, account):
|
def iter_coming(self, account):
|
||||||
return iter([])
|
with self.browser:
|
||||||
|
for tr in self.browser.iter_history(account):
|
||||||
# XXX do not print coming operations, as their labels are really useless.
|
if tr._coming:
|
||||||
#with self.browser:
|
yield tr
|
||||||
# for tr in self.browser.iter_history(account._link_id):
|
|
||||||
# if tr._coming:
|
|
||||||
# yield tr
|
|
||||||
|
|
|
||||||
|
|
@ -99,12 +99,27 @@ class SocieteGenerale(BaseBrowser):
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def iter_history(self, url):
|
def iter_history(self, account):
|
||||||
self.location(url)
|
self.location(account._link_id)
|
||||||
|
|
||||||
if not self.is_on_page(AccountHistory):
|
if not self.is_on_page(AccountHistory):
|
||||||
# TODO: support other kind of accounts
|
# TODO: support other kind of accounts
|
||||||
self.logger.warning('This account is not supported')
|
self.logger.warning('This account is not supported')
|
||||||
raise NotImplementedError('This account is not supported')
|
raise NotImplementedError('This account is not supported')
|
||||||
|
|
||||||
return self.page.iter_transactions()
|
transactions = list(self.page.iter_transactions(coming=False))
|
||||||
|
|
||||||
|
for card_link in account._card_links:
|
||||||
|
self.location(card_link)
|
||||||
|
|
||||||
|
transactions += list(self.page.iter_transactions(coming=True))
|
||||||
|
|
||||||
|
def key(tr):
|
||||||
|
# Can't compare datetime and date, so cast them.
|
||||||
|
try:
|
||||||
|
return tr.rdate.date()
|
||||||
|
except AttributeError:
|
||||||
|
return tr.rdate
|
||||||
|
|
||||||
|
transactions.sort(key=key, reverse=True)
|
||||||
|
return iter(transactions)
|
||||||
|
|
|
||||||
|
|
@ -41,35 +41,44 @@ class AccountsList(BasePage):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_list(self):
|
def get_list(self):
|
||||||
|
accounts = []
|
||||||
for tr in self.document.getiterator('tr'):
|
for tr in self.document.getiterator('tr'):
|
||||||
if 'LGNTableRow' in tr.attrib.get('class', '').split():
|
if not 'LGNTableRow' in tr.attrib.get('class', '').split():
|
||||||
account = Account()
|
continue
|
||||||
for td in tr.getiterator('td'):
|
|
||||||
if td.attrib.get('headers', '') == 'TypeCompte':
|
|
||||||
a = td.find('a')
|
|
||||||
account.label = unicode(a.find("span").text)
|
|
||||||
account._link_id = a.get('href', '')
|
|
||||||
|
|
||||||
elif td.attrib.get('headers', '') == 'NumeroCompte':
|
account = Account()
|
||||||
id = td.text
|
for td in tr.getiterator('td'):
|
||||||
id = id.replace(u'\xa0','')
|
if td.attrib.get('headers', '') == 'TypeCompte':
|
||||||
account.id = id
|
a = td.find('a')
|
||||||
|
account.label = unicode(a.find("span").text)
|
||||||
|
account._link_id = a.get('href', '')
|
||||||
|
|
||||||
elif td.attrib.get('headers', '') == 'Libelle':
|
elif td.attrib.get('headers', '') == 'NumeroCompte':
|
||||||
pass
|
id = td.text
|
||||||
|
id = id.replace(u'\xa0','')
|
||||||
|
account.id = id
|
||||||
|
|
||||||
elif td.attrib.get('headers', '') == 'Solde':
|
elif td.attrib.get('headers', '') == 'Libelle':
|
||||||
balance = td.find('div').text
|
pass
|
||||||
if balance != None:
|
|
||||||
balance = balance.replace(u'\xa0','').replace(',','.')
|
|
||||||
account.balance = Decimal(balance)
|
|
||||||
else:
|
|
||||||
account.balance = Decimal(0)
|
|
||||||
|
|
||||||
if 'CARTE_CB' in account._link_id:
|
elif td.attrib.get('headers', '') == 'Solde':
|
||||||
continue
|
balance = td.find('div').text
|
||||||
|
if balance != None:
|
||||||
|
balance = balance.replace(u'\xa0','').replace(',','.')
|
||||||
|
account.balance = Decimal(balance)
|
||||||
|
else:
|
||||||
|
account.balance = Decimal(0)
|
||||||
|
|
||||||
yield account
|
if 'CARTE_' in account._link_id:
|
||||||
|
ac = accounts[0]
|
||||||
|
ac._card_links.append(account._link_id)
|
||||||
|
if not ac.coming:
|
||||||
|
ac.coming = Decimal('0.0')
|
||||||
|
ac.coming += account.balance
|
||||||
|
else:
|
||||||
|
account._card_links = []
|
||||||
|
accounts.append(account)
|
||||||
|
return iter(accounts)
|
||||||
|
|
||||||
class Transaction(FrenchTransaction):
|
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>.*)'),
|
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>.*)'),
|
||||||
|
|
@ -80,6 +89,8 @@ class Transaction(FrenchTransaction):
|
||||||
FrenchTransaction.TYPE_PAYBACK),
|
FrenchTransaction.TYPE_PAYBACK),
|
||||||
(re.compile(r'^(?P<category>CARTE) \w+ (?P<dd>\d{2})/(?P<mm>\d{2}) (?P<text>.*)'),
|
(re.compile(r'^(?P<category>CARTE) \w+ (?P<dd>\d{2})/(?P<mm>\d{2}) (?P<text>.*)'),
|
||||||
FrenchTransaction.TYPE_CARD),
|
FrenchTransaction.TYPE_CARD),
|
||||||
|
(re.compile(r'^(?P<dd>\d{2})(?P<mm>\d{2})/(?P<text>.*?)/?(-[\d,]+)?$'),
|
||||||
|
FrenchTransaction.TYPE_CARD),
|
||||||
(re.compile(r'^(?P<category>(COTISATION|PRELEVEMENT|TELEREGLEMENT|TIP)) (?P<text>.*)'),
|
(re.compile(r'^(?P<category>(COTISATION|PRELEVEMENT|TELEREGLEMENT|TIP)) (?P<text>.*)'),
|
||||||
FrenchTransaction.TYPE_ORDER),
|
FrenchTransaction.TYPE_ORDER),
|
||||||
(re.compile(r'^(?P<category>VIR(EMEN)?T? \w+) (?P<text>.*)'),
|
(re.compile(r'^(?P<category>VIR(EMEN)?T? \w+) (?P<text>.*)'),
|
||||||
|
|
@ -104,7 +115,7 @@ class AccountHistory(BasePage):
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def iter_transactions(self):
|
def iter_transactions(self, coming):
|
||||||
url = self.get_part_url()
|
url = self.get_part_url()
|
||||||
if url is None:
|
if url is None:
|
||||||
# There are no transactions in this kind of account
|
# There are no transactions in this kind of account
|
||||||
|
|
@ -121,7 +132,9 @@ class AccountHistory(BasePage):
|
||||||
s = StringIO(unicode(el.text).encode('iso-8859-1'))
|
s = StringIO(unicode(el.text).encode('iso-8859-1'))
|
||||||
doc = self.browser.get_document(s)
|
doc = self.browser.get_document(s)
|
||||||
|
|
||||||
for tr in self._iter_transactions(doc):
|
for tr in self._iter_transactions(doc, coming):
|
||||||
|
if not tr._coming:
|
||||||
|
coming = False
|
||||||
yield tr
|
yield tr
|
||||||
|
|
||||||
el = d.xpath('//dataHeader')[0]
|
el = d.xpath('//dataHeader')[0]
|
||||||
|
|
@ -134,16 +147,31 @@ class AccountHistory(BasePage):
|
||||||
operationNumberPG=el.find('operationNumber').text,
|
operationNumberPG=el.find('operationNumber').text,
|
||||||
operationTypePG=el.find('operationType').text,
|
operationTypePG=el.find('operationType').text,
|
||||||
pageNumberPG=el.find('pageNumber').text,
|
pageNumberPG=el.find('pageNumber').text,
|
||||||
idecrit=el.find('idecrit').text,
|
idecrit=el.find('idecrit').text or '',
|
||||||
sign=p['sign'][0],
|
sign=p['sign'][0],
|
||||||
src=p['src'][0])
|
src=p['src'][0])
|
||||||
|
|
||||||
|
|
||||||
def _iter_transactions(self, doc):
|
def _iter_transactions(self, doc, coming):
|
||||||
for i, tr in enumerate(self.parser.select(doc.getroot(), 'tr')):
|
for i, tr in enumerate(self.parser.select(doc.getroot(), 'tr')):
|
||||||
|
date = tr.xpath('./td[@headers="Date"]')[0].text.strip()
|
||||||
|
if date == '':
|
||||||
|
coming = False
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
raw = tr.attrib['title'].strip()
|
||||||
|
except KeyError:
|
||||||
|
raw = tr.xpath('./td[@headers="Libelle"]//text()')[0].strip()
|
||||||
t = Transaction(i)
|
t = Transaction(i)
|
||||||
t.parse(date=tr.xpath('./td[@headers="Date"]')[0].text,
|
t.parse(date=date, raw=raw)
|
||||||
raw=tr.attrib['title'].strip())
|
|
||||||
t.set_amount(*reversed([el.text for el in tr.xpath('./td[@class="right"]')]))
|
t.set_amount(*reversed([el.text for el in tr.xpath('./td[@class="right"]')]))
|
||||||
t._coming = tr.xpath('./td[@headers="AVenir"]')[0].find('img') is not None
|
try:
|
||||||
|
t._coming = tr.xpath('./td[@headers="AVenir"]')[0].find('img') is not None
|
||||||
|
except IndexError:
|
||||||
|
t._coming = coming
|
||||||
|
|
||||||
|
if t.label.startswith('DEBIT MENSUEL CARTE'):
|
||||||
|
continue
|
||||||
|
|
||||||
yield t
|
yield t
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue