diff --git a/weboob/backends/bnporc/backend.py b/weboob/backends/bnporc/backend.py index 035ce517..e4680889 100644 --- a/weboob/backends/bnporc/backend.py +++ b/weboob/backends/bnporc/backend.py @@ -16,7 +16,7 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -from weboob.capabilities.bank import ICapBank, AccountNotFound +from weboob.capabilities.bank import ICapBank, AccountNotFound, Account from weboob.tools.backend import BaseBackend from weboob.tools.value import ValuesDict, Value @@ -67,16 +67,33 @@ class BNPorcBackend(BaseBackend, ICapBank): except ValueError: raise AccountNotFound() else: - account = self.browser.get_account(_id) + with self.browser: + account = self.browser.get_account(_id) if account: return account else: raise AccountNotFound() def iter_history(self, account): - for history in self.browser.get_history(account): - yield history + with self.browser: + for history in self.browser.get_history(account): + yield history def iter_operations(self, account): - for coming in self.browser.get_coming_operations(account): - yield coming + with self.browser: + for coming in self.browser.get_coming_operations(account): + yield coming + + def transfer(self, account, to, amount, reason=None): + if isinstance(account, Account): + account = account.id + + try: + account = long(account) + to = long(to) + amount = float(amount) + except ValueError: + raise AccountNotFound() + + with self.browser: + return self.browser.transfer(account, to, amount, reason) diff --git a/weboob/backends/bnporc/browser.py b/weboob/backends/bnporc/browser.py index 6c8701cc..7f2574f8 100644 --- a/weboob/backends/bnporc/browser.py +++ b/weboob/backends/bnporc/browser.py @@ -16,9 +16,11 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +from datetime import datetime from logging import warning from weboob.tools.browser import BaseBrowser, BrowserIncorrectPassword +from weboob.capabilities.bank import TransferError, Transfer from weboob.backends.bnporc import pages from .errors import PasswordExpired @@ -35,6 +37,9 @@ class BNPorc(BaseBrowser): '.*Action=SAF_CHM.*': pages.ChangePasswordPage, '.*NS_AVEET.*': pages.AccountComing, '.*NS_AVEDP.*': pages.AccountPrelevement, + '.*NS_VIRDF.*': pages.TransferPage, + '.*NS_VIRDC.*': pages.TransferConfirmPage, + '.*/NS_VIRDA\?stp=(?P\d+).*': pages.TransferCompletePage, '.*Action=DSP_VGLOBALE.*': pages.LoginPage, '.*type=homeconnex.*': pages.LoginPage, '.*layout=HomeConnexion.*': pages.ConfirmPage, @@ -120,3 +125,19 @@ class BNPorc(BaseBrowser): if not self.is_on_page(pages.AccountComing) or self.page.account.id != account.id: self.location('/NS_AVEET?ch4=%s' % account.link_id) return self.page.get_operations() + + def transfer(self, from_id, to_id, amount, reason=None): + if not self.is_on_page(pages.TransferPage): + self.location('/NS_VIRDF') + + self.page.transfer(from_id, to_id, amount, reason) + + if not self.is_on_page(pages.TransferCompletePage): + raise TransferError('An error occured during transfer') + + transfer = Transfer(self.page.get_id()) + transfer.amount = amount + transfer.origin = from_id + transfer.recipient = to_id + transfer.date = datetime.now() + return transfer diff --git a/weboob/backends/bnporc/pages/__init__.py b/weboob/backends/bnporc/pages/__init__.py index ab862814..dbb29483 100644 --- a/weboob/backends/bnporc/pages/__init__.py +++ b/weboob/backends/bnporc/pages/__init__.py @@ -19,9 +19,11 @@ from .accounts_list import AccountsList from .account_coming import AccountComing from .account_history import AccountHistory +from .transfer import TransferPage, TransferConfirmPage, TransferCompletePage from .login import LoginPage, ConfirmPage, ChangePasswordPage class AccountPrelevement(AccountsList): pass __all__ = ['AccountsList', 'AccountComing', 'AccountHistory', 'LoginPage', - 'ConfirmPage', 'AccountPrelevement', 'ChangePasswordPage'] + 'ConfirmPage', 'AccountPrelevement', 'ChangePasswordPage', + 'TransferPage', 'TransferConfirmPage', 'TransferCompletePage'] diff --git a/weboob/backends/bnporc/pages/transfer.py b/weboob/backends/bnporc/pages/transfer.py new file mode 100644 index 00000000..d4425794 --- /dev/null +++ b/weboob/backends/bnporc/pages/transfer.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2010 Romain Bignon +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import re + +from weboob.tools.browser import BasePage +from weboob.capabilities.bank import TransferError + + +__all__ = ['TransferPage', 'TransferConfirmPage', 'TransferCompletePage'] + + +class TransferPage(BasePage): + def transfer(self, from_id, to_id, amount, reason): + self.browser.select_form(nr=0) + from_found = False + to_found = False + for table in self.document.getiterator('table'): + if table.attrib.get('cellspacing') == '2': + for tr in table.cssselect('tr.hdoc1, tr.hdotc1'): + tds = tr.findall('td') + id = long(tds[1].text.replace(u'\xa0', u'')) + if id == from_id: + if tds[4].find('input') is None: + raise TransferError("Unable to make a transfer from %s" % from_id) + self.browser['C1'] = [tds[4].find('input').attrib['value']] + from_found = True + elif id == to_id: + if tds[5].find('input') is None: + raise TransferError("Unable to make a transfer to %s" % from_id) + self.browser['C2'] = [tds[5].find('input').attrib['value']] + to_found = True + + if not from_found: + raise TransferError('Account %s not found' % from_id) + + if not to_found: + raise TransferError('Recipient %s not found' % to_id) + + self.browser['T6'] = str(amount).replace('.', ',') + if reason: + self.browser['T5'] = reason + self.browser.submit() + +class TransferConfirmPage(BasePage): + def on_loaded(self): + for td in self.document.getroot().cssselect('td#size2'): + raise TransferError(td.text.strip()) + + for a in self.document.getiterator('a'): + m = re.match('/NSFR\?Action=VIRDA&stp=(\d+)', a.attrib['href']) + if m: + self.browser.location('/NS_VIRDA?stp=%s' % m.group(1)) + return + +class TransferCompletePage(BasePage): + def get_id(self): + return self.group_dict['id']