Commit b006d47b authored by Romain Bignon's avatar Romain Bignon

Update of modules

parent 6fdd8b37
......@@ -30,7 +30,7 @@ from import (
from weboob.capabilities.messages import CapMessages, Thread
from import CapContact
from weboob.capabilities.profile import CapProfile
from weboob.capabilities.base import find_object
from weboob.capabilities.base import find_object, strict_find_object
from import Module, BackendConfig
from import ValueBackendPassword, Value, ValueBool
......@@ -119,7 +119,9 @@ class BNPorcModule(Module, CapBankWealth, CapBankTransferAddRecipient, CapMessag
account = find_object(self.iter_accounts(), id=transfer.account_id, error=AccountNotFound)
recipient = find_object(self.iter_transfer_recipients(, id=transfer.recipient_id, error=RecipientNotFound)
recipient = strict_find_object(self.iter_transfer_recipients(, iban=transfer.recipient_iban)
if not recipient:
recipient = strict_find_object(self.iter_transfer_recipients(, id=transfer.recipient_id, error=RecipientNotFound)
# quantize to show 2 decimals.
......@@ -130,6 +132,17 @@ class BNPorcModule(Module, CapBankWealth, CapBankTransferAddRecipient, CapMessag
def execute_transfer(self, transfer, **params):
return self.browser.execute_transfer(transfer)
def transfer_check_recipient_id(self, old, new):
# external recipient id can change, check the iban in recipient id
iban ='([A-Z]{2}[A-Z\d]+)', old)
if iban:
# external recipients id
iban =
return iban in new
# iternal recipients id
return old == new
def iter_contacts(self):
if not hasattr(self.browser, 'get_advisor'):
raise NotImplementedError()
......@@ -327,11 +327,18 @@ class BNPParibasBrowser(JsonBrowserMixin, LoginBrowser):
except TransferError:
# avoid recipient with same iban
seen = set()
for recipient in
yield recipient
if recipient.iban not in seen:
yield recipient
for recipient in self.recipients.go(data=JSON({'type': 'TOUS'})).iter_recipients():
yield recipient
if recipient.iban not in seen:
yield recipient
def new_recipient(self, recipient, **params):
......@@ -389,7 +389,7 @@ class RecipientsPage(BNPPage):
class item(MyRecipient):
# For the moment, only yield ready to transfer on recipients.
condition = lambda self: Dict('libelleStatut')(self.el) in [u'Activé', u'Temporisé']
condition = lambda self: Dict('libelleStatut')(self.el) in [u'Activé', u'Temporisé', u'En attente']
obj_id = Dict('idBeneficiaire')
obj_label = Dict('nomBeneficiaire')
......@@ -29,7 +29,7 @@ from import Advisor
from weboob.capabilities.profile import Person
from weboob.browser.elements import ListElement, ItemElement, method, TableElement
from weboob.browser.pages import LoggedPage, RawPage, PartialHTMLPage, HTMLPage
from weboob.browser.filters.html import Link, TableCell
from weboob.browser.filters.html import Link, TableCell, Attr
from weboob.browser.filters.standard import CleanText, CleanDecimal, Regexp, Env, Field, Currency, Async, Date, Format
from weboob.exceptions import BrowserUnavailable
from import urljoin, unicode
......@@ -57,6 +57,8 @@ class item_account_generic(ItemElement):
def obj_url(self):
url = Link(u'./a', default=NotAvailable)(self)
if not url:
url = Regexp(Attr(u'.//span', 'onclick', default=''), r'\'(https.*)\'', default=NotAvailable)(self)
if url:
if 'CreditRenouvelable' in url:
url = Link(u'.//a[contains(text(), "espace de gestion crédit renouvelable")]')(self.el)
......@@ -563,6 +563,10 @@ class CragrAPI(LoginBrowser):
def iter_transfer_recipients(self, account, transfer_space_info=None):
if account.type in (account.TYPE_CARD, account.TYPE_LOAN, account.TYPE_LIFE_INSURANCE,
# avoid to call `get_account_transfer_space_info()` several time
if transfer_space_info:
space, operation, referer = transfer_space_info
......@@ -574,12 +578,16 @@ class CragrAPI(LoginBrowser):
if not
for index, internal_rcpt in enumerate(
internal_rcpt._index = index
yield internal_rcpt
# can't use 'ignore_duplicate' in DictElement because we need the 'index' to do transfer
seen = set()
for index, internal_rcpt in enumerate(
internal_rcpt._index = index
if internal_rcpt._is_recipient and (internal_rcpt.iban not in seen):
yield internal_rcpt
for index, external_rcpt in enumerate(
external_rcpt._index = index
if external_rcpt.iban not in seen:
......@@ -27,7 +27,7 @@ from import (
Account, Recipient, Transfer, TransferBankError,
from weboob.browser.filters.standard import (
CleanDecimal, Env, Date, CleanText,
CleanDecimal, Date, CleanText,
from weboob.browser.filters.json import Dict
......@@ -59,10 +59,12 @@ class RecipientsPage(LoggedPage, JsonPage):
class iter_internal_recipient(DictElement):
def store(self, obj):
return obj
class item(ItemElement):
def condition(self):
return Dict('recipientOfTransfert', default=None)(self) and \
Env('account_id')(self) != Dict('accountNumber', default=None)(self)
return Dict('accountNumber', default=None)(self)
klass = Recipient
......@@ -71,6 +73,7 @@ class RecipientsPage(LoggedPage, JsonPage):
obj_iban = Dict('ibanCode')
obj_category = 'Interne'
obj_enabled_at =
obj__is_recipient = Dict('recipientOfTransfert', default=False)
class iter_external_recipient(DictElement):
......@@ -460,6 +460,9 @@ class Cragr(LoginBrowser, StatesMixin):
date_guesser = LinearDateGuesser(date_max_bump=timedelta(2))
date_guesser = LinearDateGuesser()
if self.predica_redirect.is_here():
self.logger.warning('Predica transactions are not handled.')
while True:
assert self.transactions.is_here()
......@@ -165,11 +165,12 @@ class CreditDuNordBrowser(LoginBrowser):
self.location(account._link, data=account._args)
if and
elif account.type in (Account.TYPE_LIFE_INSURANCE, Account.TYPE_CAPITALISATION):
self.location(account._link, data=account._args)
self.location(account._link.replace("_attente", "_detail_contrat_rep"), data=account._args)
return []
......@@ -179,8 +179,8 @@ class LabelsPage(LoggedPage, JsonPage):
for element in Dict('submenu')(key):
if Lower(CleanText(Dict('label')))(element) in synthesis_labels:
synthesis_label = CleanText(Dict('link'))(element).split("/")[-1]
if CleanText(Dict('label'))(element).lower() in loan_labels:
loan_label = Lower(CleanText(Dict('link')))(element).split("/")[-1]
if Lower(CleanText(Dict('label')))(element) in loan_labels:
loan_label = CleanText(Dict('link'))(element).split("/")[-1]
return (synthesis_label, loan_label)
......@@ -687,9 +687,9 @@ class TransactionsPage(LoggedPage, CDNBasePage):
return "Sous-total" not in Field('label')(self)
class get_deposit_investment(TableElement):
class get_li_investments(TableElement):
item_xpath = '//table[@class="datas"]//tr[position()>1]'
head_xpath = '//table[@class="datas"]//tr[@class="entete"]/td/b'
head_xpath = '//table[@class="datas"]//tr[@class="entete"]/td/*'
col_label = u'Libellé'
col_quantity = u'Quantité'
......@@ -726,7 +726,7 @@ class TransactionsPage(LoggedPage, CDNBasePage):
def fill_diff_currency(self, account):
valuation_diff = CleanText(u'//td[span[contains(text(), "dont +/- value : ")]]//b', default=None)(self.doc)
account.balance = CleanDecimal.French(Regexp(CleanText('//table[@class="v1-formbloc"]//td[@class="v1-labels"]/b[contains(text(), "Estimation du contrat")]/ancestor::td/following-sibling::td[1]'), r'^(.+) EUR'))(self.doc)
account.balance = CleanDecimal.French(Regexp(CleanText('//table[@class="v1-formbloc"]//td[@class="v1-labels"]//b[contains(text(), "Estimation du contrat")]/ancestor::td/following-sibling::td[1]'), r'^(.+) EUR'))(self.doc)
# NC == Non communiqué
if valuation_diff and "NC" not in valuation_diff:
account.valuation_diff = MyDecimal().filter(valuation_diff)
......@@ -177,8 +177,16 @@ class SocieteGenerale(LoginBrowser, StatesMixin):
account_ibans =
# get accounts coming
if not
# return in old pages to get accounts
self.accounts_main_page.go(params={'NoRedirect': True})
for acc in
yield acc
# get accounts coming
account_comings =
......@@ -211,6 +219,9 @@ class SocieteGenerale(LoginBrowser, StatesMixin):
if account.type == Account.TYPE_PEA and not ('Espèces' in account.label or 'ESPECE' in account.label):
if not account._internal_id:
raise BrowserUnavailable()
if account.type in (account.TYPE_LIFE_INSURANCE, account.TYPE_PERP, ):
# request to get json is not available yet, old request to get html response
self.account_details_page.go(params={'idprest': account._prestation_id})
......@@ -254,6 +265,9 @@ class SocieteGenerale(LoginBrowser, StatesMixin):
if not account._internal_id:
raise BrowserUnavailable()
internal_id = account._internal_id
if account.type == account.TYPE_CARD:
internal_id = account.parent._internal_id
......@@ -59,13 +59,15 @@ class JsonBasePage(LoggedPage, JsonPage):
if action and 'BLOCAGE' in action:
raise ActionNeeded()
if 'le service est momentanement indisponible' in reason:
# TODO: iter account on old website
# can't access new website
if ('le service est momentanement indisponible' in reason and
Dict('commun/origine')(self.doc) != 'cbo'):
raise BrowserUnavailable()
assert 'pas encore géré' in reason, 'Error %s is not handled yet' % reason
self.browser.logger.warning('This page is not handled yet by SG')
conditions = (
'pas encore géré' in reason, # this page is not handled by SG api website
'le service est momentanement indisponible' in reason, # can't access new website
assert any(conditions), 'Error %s is not handled yet' % reason
class AccountsMainPage(LoggedPage, HTMLPage):
......@@ -77,6 +79,36 @@ class AccountsMainPage(LoggedPage, HTMLPage):
if 'Vous ne disposez pas de compte consultable' in error_msg:
raise NoAccountsException(error_msg)
class iter_accounts(TableElement):
"""iter account on old website"""
head_xpath = '//table[@class="LGNTableA ListePrestation"]//tr[@class="LGNTableHead"]/th'
item_xpath = '//table[@class="LGNTableA ListePrestation"]//tr[has-class("LGNTableRow")]'
col_id = 'Numéro de Compte'
col_type = 'Type de Compte'
col_label = 'Libellé'
col_balance = 'Solde'
class item(ItemElement):
klass = Account
obj_id = obj_number = CleanText(TableCell('id'), replace=[(' ', '')])
obj_label = CleanText('.//span[@class="TypeCompte"]')
obj_balance = MyDecimal(TableCell('balance'))
obj_currency = Currency(CleanText(TableCell('balance')))
obj__internal_id = None
def obj_type(self):
for acc_type in self.TYPES:
if acc_type in Field('label')(self).upper():
return self.TYPES[acc_type]
return Account.TYPE_UNKNOWN
class AccountDetailsPage(LoggedPage, HTMLPage):
......@@ -155,6 +187,14 @@ class AccountsPage(JsonBasePage):
return True
class AccountsSynthesesPage(JsonBasePage):
def is_new_website_available(self):
if not Dict('commun/raison')(self.doc):
return True
elif not 'le service est momentanement indisponible' in Dict('commun/raison')(self.doc):
return True
self.logger.warning("SG new website is not available yet for this user")
return False
def get_account_comings(self):
account_comings = {}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment