diff --git a/modules/bnporc/backend.py b/modules/bnporc/backend.py
index ef0c177c..22be42ca 100644
--- a/modules/bnporc/backend.py
+++ b/modules/bnporc/backend.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright(C) 2010-2011 Romain Bignon
+# Copyright(C) 2010-2012 Romain Bignon
#
# This file is part of weboob.
#
@@ -40,7 +40,7 @@ class BNPorcBackend(BaseBackend, ICapBank):
DESCRIPTION = 'BNP Paribas French bank website'
CONFIG = BackendConfig(ValueBackendPassword('login', label='Account ID', masked=False),
ValueBackendPassword('password', label='Password', regexp='^(\d{6}|)$'),
- ValueBackendPassword('rotating_password',
+ ValueBackendPassword('rotating_password', default='',
label='Password to set when the allowed uses are exhausted (6 digits)',
regexp='^(\d{6}|)$'))
BROWSER = BNPorc
@@ -76,13 +76,11 @@ class BNPorcBackend(BaseBackend, ICapBank):
def iter_history(self, account):
with self.browser:
- for history in self.browser.get_history(account.id):
- yield history
+ return self.browser.iter_history(account.id)
def iter_operations(self, account):
with self.browser:
- for coming in self.browser.get_coming_operations(account.id):
- yield coming
+ return self.browser.iter_coming_operations(account.id)
def iter_transfer_recipients(self, ignored):
for account in self.browser.get_transfer_accounts().itervalues():
diff --git a/modules/bnporc/browser.py b/modules/bnporc/browser.py
index 94edc507..04c599d0 100644
--- a/modules/bnporc/browser.py
+++ b/modules/bnporc/browser.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright(C) 2009-2011 Romain Bignon
+# Copyright(C) 2009-2012 Romain Bignon
#
# This file is part of weboob.
#
@@ -129,16 +129,41 @@ class BNPorc(BaseBrowser):
return None
- def get_history(self, id):
- self.location('/banque/portail/particulier/FicheA?contractId=%d&pageId=releveoperations&_eventId=changeOperationsPerPage&operationsPerPage=200' % int(id))
- return self.page.get_operations()
+ #def get_history(self, id):
+ # data = {'contactId': int(id),
+ # 'pageId': 'releveoperations',
+ # '_eventId': 'pastOperations',
+ # 'operationsPerPage': 200,
+ # 'groupId': -2
+ # }
+ # self.location('/banque/portail/particulier/FicheA#pageId=releveoperations', urllib.urlencode(data))
+ # return self.page.get_operations()
- def get_coming_operations(self, id):
+ #def get_coming_operations(self, id):
+ # if not self.is_on_page(AccountsList):
+ # self.location('/NSFR?Action=DSP_VGLOBALE')
+ # execution = self.page.get_execution_id()
+
+ # data = {'externalIAId': 'IAStatements',
+ # 'contactId': int(id),
+ # 'pastOrPendingOperations': 2,
+ # 'pageId': 'mouvementsavenir',
+ # 'execution': execution,
+ # }
+ # self.location('/banque/portail/particulier/FicheA#pageId=mouvementsavenir', urllib.urlencode(data))
+ # return self.page.get_operations()
+
+
+ def iter_history(self, id):
+ self.location('/banque/portail/particulier/FicheA?contractId=%d&pageId=releveoperations&_eventId=changeOperationsPerPage&operationsPerPage=200' % int(id))
+ return self.page.iter_operations()
+
+ def iter_coming_operations(self, id):
if not self.is_on_page(AccountsList):
self.location('/NSFR?Action=DSP_VGLOBALE')
execution = self.page.get_execution_id()
self.location('/banque/portail/particulier/FicheA?externalIAId=IAStatements&contractId=%d&pastOrPendingOperations=2&pageId=mouvementsavenir&execution=%s' % (int(id), execution))
- return self.page.get_operations()
+ return self.page.iter_operations()
@check_expired_password
def get_transfer_accounts(self):
diff --git a/modules/bnporc/pages/__init__.py b/modules/bnporc/pages/__init__.py
index 1e5cecaf..d30ae986 100644
--- a/modules/bnporc/pages/__init__.py
+++ b/modules/bnporc/pages/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright(C) 2009-2011 Romain Bignon
+# Copyright(C) 2009-2012 Romain Bignon
#
# This file is part of weboob.
#
@@ -19,8 +19,7 @@
from .accounts_list import AccountsList
-from .account_coming import AccountComing
-from .account_history import AccountHistory
+from .transactions import AccountHistory, AccountComing
from .transfer import TransferPage, TransferConfirmPage, TransferCompletePage
from .login import LoginPage, ConfirmPage, ChangePasswordPage, MessagePage
diff --git a/modules/bnporc/pages/account_coming.py b/modules/bnporc/pages/account_coming.py
deleted file mode 100644
index 17fcd6d8..00000000
--- a/modules/bnporc/pages/account_coming.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright(C) 2009-2011 Romain Bignon
-#
-# This file is part of weboob.
-#
-# weboob is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# weboob is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with weboob. If not, see .
-
-
-import re
-from datetime import date
-
-from weboob.tools.browser import BasePage
-from weboob.capabilities.bank import Operation
-
-
-__all__ = ['AccountComing']
-
-
-class AccountComing(BasePage):
- LABEL_PATTERNS = [('^FACTURE CARTE DU (?P
\d{2})(?P\d{2})(?P\d{2}) (?P.*)',
- u'CB %(yy)s-%(mm)s-%(dd)s: %(text)s'),
- ('^PRELEVEMENT(?P.*)', 'Order: %(text)s'),
- ('^ECHEANCEPRET(?P.*)', u'Loan payment n°%(text)s'),
- ]
-
- def on_loaded(self):
- self.operations = []
-
- for tr in self.document.xpath('//table[@id="tableauOperations"]//tr'):
- if 'typeop' in tr.attrib:
- tds = tr.findall('td')
- if len(tds) != 3:
- continue
- d = tr.attrib['dateop']
- d = date(int(d[4:8]), int(d[2:4]), int(d[0:2]))
- label = tds[1].text or u''
- label = label.replace(u'\xa0', u'')
- for child in tds[1].getchildren():
- if child.text: label += child.text
- if child.tail: label += child.tail
- label = label.strip()
-
- for pattern, text in self.LABEL_PATTERNS:
- m = re.match(pattern, label)
- if m:
- label = text % m.groupdict()
-
- amount = tds[2].text.replace('.','').replace(',','.').strip(u' \t\u20ac\xa0€\n\r')
-
- operation = Operation(len(self.operations))
- operation.date = d
- operation.label = label
- operation.amount = float(amount)
- self.operations.append(operation)
-
- def get_operations(self):
- return self.operations
diff --git a/modules/bnporc/pages/account_history.py b/modules/bnporc/pages/account_history.py
deleted file mode 100644
index affc9e43..00000000
--- a/modules/bnporc/pages/account_history.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright(C) 2009-2011 Romain Bignon
-#
-# This file is part of weboob.
-#
-# weboob is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# weboob is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with weboob. If not, see .
-
-
-import re
-from datetime import date
-
-from weboob.tools.browser import BasePage
-from weboob.capabilities.bank import Operation
-from weboob.capabilities.base import NotAvailable
-
-
-__all__ = ['AccountHistory']
-
-
-class AccountHistory(BasePage):
- LABEL_PATTERNS = [(u'^CHEQUEN°(?P.*)', u'CHEQUE', u'N°%(no)s')]
-
- def on_loaded(self):
- self.operations = []
-
- 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 = Operation(id)
- op.label = tr.findall('td')[2].text.replace(u'\xa0', u'').strip()
- op.date = date(*reversed([int(x) for x in tr.findall('td')[1].text.split('/')]))
-
- op.category = NotAvailable
- for pattern, _cat, _lab in self.LABEL_PATTERNS:
- m = re.match(pattern, op.label)
- if m:
- op.category = _cat % m.groupdict()
- op.label = _lab % m.groupdict()
- break
- else:
- if ' ' in op.label:
- op.category, useless, op.label = [part.strip() for part in op.label.partition(' ')]
-
- debit = tr.xpath('.//td[@class="debit"]')[0].text.replace('.','').replace(',','.').strip(u' \t\u20ac\xa0€\n\r')
- credit = tr.xpath('.//td[@class="credit"]')[0].text.replace('.','').replace(',','.').strip(u' \t\u20ac\xa0€\n\r')
- if len(debit) > 0:
- op.amount = - float(debit)
- else:
- op.amount = float(credit)
-
- self.operations.append(op)
-
- def get_operations(self):
- return self.operations
diff --git a/modules/bnporc/pages/transactions.py b/modules/bnporc/pages/transactions.py
new file mode 100644
index 00000000..3da96564
--- /dev/null
+++ b/modules/bnporc/pages/transactions.py
@@ -0,0 +1,111 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2009-2012 Romain Bignon
+#
+# This file is part of weboob.
+#
+# weboob is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# weboob is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with weboob. If not, see .
+
+
+import re
+from datetime import date
+
+from weboob.tools.browser import BasePage
+from weboob.capabilities.bank import Transaction
+from weboob.capabilities.base import NotAvailable
+
+
+__all__ = ['AccountHistory', 'AccountComing']
+
+
+class TransactionsBasePage(BasePage):
+ LABEL_PATTERNS = [(re.compile(u'^CHEQUEN°(?P.*)'),
+ Transaction.TYPE_CHECK, u'N°%(no)s'),
+ (re.compile('^FACTURE CARTE DU (?P\d{2})(?P\d{2})(?P\d{2}) (?P.*)'),
+ Transaction.TYPE_CARD, u'20%(yy)s-%(mm)s-%(dd)s: %(text)s'),
+ (re.compile('^(PRELEVEMENT|TELEREGLEMENT) (?P.*)'),
+ Transaction.TYPE_ORDER, '%(text)s'),
+ (re.compile('^ECHEANCEPRET(?P.*)'),
+ Transaction.TYPE_LOAN_PAYMENT, u'n°%(text)s'),
+ (re.compile('^RETRAIT DAB (?P\d{2})/(?P\d{2})/(?P\d{2}) (?P\d+)H(?P\d+) (?P.*)'),
+ Transaction.TYPE_WITHDRAWAL, u'20%(yy)s-%(mm)s-%(dd)s %(HH)s:%(MM)s: %(text)s'),
+ (re.compile('^VIREMENT (?P.*)'),
+ Transaction.TYPE_TRANSFER, u'%(text)s'),
+ (re.compile('^REMBOURST (?P.*)'),
+ Transaction.TYPE_PAYBACK, '%(text)s'),
+ (re.compile('^COMMISSIONS (?P.*)'),
+ Transaction.TYPE_BANK, '%(text)s'),
+ ]
+
+ def parse_text(self, op):
+ op.category = NotAvailable
+ if ' ' in op.text:
+ op.category, useless, op.label = [part.strip() for part in op.label.partition(' ')]
+ else:
+ op.label = op.text
+
+ for pattern, _type, _label in self.LABEL_PATTERNS:
+ m = pattern.match(op.text)
+ if m:
+ op.type = _type
+ op.label = (_label % m.groupdict()).strip()
+ return
+
+class AccountHistory(TransactionsBasePage):
+ 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.text = tr.findall('td')[2].text.replace(u'\xa0', u'').strip()
+ op.date = date(*reversed([int(x) for x in tr.findall('td')[1].text.split('/')]))
+
+ self.parse_text(op)
+
+ debit = tr.xpath('.//td[@class="debit"]')[0].text.replace('.','').replace(',','.').strip(u' \t\u20ac\xa0€\n\r')
+ credit = tr.xpath('.//td[@class="credit"]')[0].text.replace('.','').replace(',','.').strip(u' \t\u20ac\xa0€\n\r')
+ if len(debit) > 0:
+ op.amount = - float(debit)
+ else:
+ op.amount = float(credit)
+
+ yield op
+
+class AccountComing(TransactionsBasePage):
+ def iter_operations(self):
+ i = 0
+ for tr in self.document.xpath('//table[@id="tableauOperations"]//tr'):
+ if 'typeop' in tr.attrib:
+ tds = tr.findall('td')
+ if len(tds) != 3:
+ continue
+ d = tr.attrib['dateop']
+ d = date(int(d[4:8]), int(d[2:4]), int(d[0:2]))
+ text = tds[1].text or u''
+ text = text.replace(u'\xa0', u'')
+ for child in tds[1].getchildren():
+ if child.text: text += child.text
+ if child.tail: text += child.tail
+
+ amount = tds[2].text.replace('.','').replace(',','.').strip(u' \t\u20ac\xa0€\n\r')
+
+ i += 1
+ operation = Transaction(i)
+ operation.date = d
+ operation.text = text.strip()
+ self.parse_text(operation)
+ operation.amount = float(amount)
+ yield operation