Commit 0032eeb0 authored by Etienne Lachere's avatar Etienne Lachere Committed by Vincent A

[lcl] add account ownership

parent 95e921d1
......@@ -28,7 +28,10 @@ from weboob.exceptions import BrowserIncorrectPassword, BrowserUnavailable
from weboob.browser import LoginBrowser, URL, need_login, StatesMixin
from weboob.browser.exceptions import ServerError
from weboob.capabilities.base import NotAvailable
from import Account, AddRecipientBankError, AddRecipientStep, Recipient, AccountOwnerType
from import (
Account, AddRecipientBankError, AddRecipientStep, Recipient, AccountOwnerType,
from weboob.capabilities.base import find_object
from import create_french_liquidity
from import basestring, urlsplit, unicode
......@@ -268,13 +271,14 @@ class LCLBrowser(LoginBrowser, StatesMixin):
if self.login.is_here():
return self.get_accounts_list()
owner_name =' (.+)', self.get_profile().name).group(1).upper()
# retrieve life insurance accounts
if self.no_perm.is_here():
self.logger.warning('Life insurances are unavailable.')
# retrieve life insurances from popups
for a in
for a in
# retrieve life insurances from calie website
......@@ -312,7 +316,7 @@ class LCLBrowser(LoginBrowser, StatesMixin):
# retrieve accounts on main page
for a in
for a in
if not self.check_accounts(a):
......@@ -346,7 +350,7 @@ class LCLBrowser(LoginBrowser, StatesMixin):
if self.connexion_bourse():
for a in
for a in
# Disconnecting from bourse portal before returning account list
......@@ -357,7 +361,7 @@ class LCLBrowser(LoginBrowser, StatesMixin):
if self.no_perm.is_here():
self.logger.warning('Deposits are unavailable.')
for a in
for a in
# There is no id on the page listing the 'Compte à terme'
# So a form must be submitted to access the id of the contract
......@@ -390,11 +394,24 @@ class LCLBrowser(LoginBrowser, StatesMixin):
a._card_position = card_position
owner_name =' (.+)', self.get_profile().name).group(1).upper()
for account in self.accounts_list:
account.owner_type = self.owner_type
self.set_ownership(account, owner_name)
return iter(self.accounts_list)
def set_ownership(self, account, owner_name):
if not account.ownership:
if account.parent and account.parent.ownership:
account.ownership = account.parent.ownership
elif'(m|mr|me|mme|mlle|mle|ml)\.? (.*)\bou (m|mr|me|mme|mlle|mle|ml)\b(.*)', account.label, re.IGNORECASE):
account.ownership = AccountOwnership.CO_OWNER
elif all(n in account.label for n in owner_name.split()):
account.ownership = AccountOwnership.OWNER
account.ownership = AccountOwnership.ATTORNEY
def get_bourse_accounts_ids(self):
bourse_accounts_ids = []
for account in self.get_accounts_list():
......@@ -30,6 +30,7 @@ from datetime import datetime, timedelta
from weboob.capabilities.base import empty, find_object, NotAvailable
from import (
Account, Investment, Recipient, TransferError, TransferBankError, Transfer,
from weboob.capabilities.bill import Document, Subscription, DocumentTypes
from weboob.capabilities.profile import Person, ProfileMissing
......@@ -231,6 +232,15 @@ class ContractsChoicePage(ContractsPage):
class OwnedItemElement(ItemElement):
def get_ownership(self, owner):
if'(m|mr|me|mme|mlle|mle|ml)\.? (.*)\bou (m|mr|me|mme|mlle|mle|ml)\b(.*)', owner, re.IGNORECASE):
return AccountOwnership.CO_OWNER
elif all(n in owner for n in self.env['name'].split()):
return AccountOwnership.OWNER
return AccountOwnership.ATTORNEY
class AccountsPage(LoggedPage, HTMLPage):
def on_load(self):
warn = self.doc.xpath('//div[@id="attTxt"]')
......@@ -241,7 +251,7 @@ class AccountsPage(LoggedPage, HTMLPage):
return CleanText('//li[@id="nomClient"]/p')(self.doc)
class get_list(ListElement):
class get_accounts_list(ListElement):
# XXX Ugly Hack to replace account by second occurrence.
# LCL pro website sometimes display the same account twice and only second link is valid to fetch transactions.
......@@ -255,12 +265,19 @@ class AccountsPage(LoggedPage, HTMLPage):
item_xpath = '//tr[contains(@onclick, "redirect")]'
flush_at_end = True
class account(ItemElement):
class account(OwnedItemElement):
klass = Account
def condition(self):
return '/outil/UWLM/ListeMouvement' in self.el.attrib['onclick']
def load_details(self):
link_id = Field('_link_id')(self)
if link_id:
account_url = urljoin(, link_id)
return NotAvailable
'001': Account.TYPE_SAVINGS,
'004': Account.TYPE_CHECKING,
......@@ -290,6 +307,11 @@ class AccountsPage(LoggedPage, HTMLPage):
obj__market_link = None
obj_number = Field('id')
def obj_ownership(self):
async_page = Async('details').loaded_page(self)
owner = CleanText('//h5[contains(text(), "Titulaire")]')(async_page.doc)
return self.get_ownership(owner)
def get_deferred_cards(self):
trs = self.doc.xpath('//tr[contains(@onclick, "EncoursCB")]')
links = []
......@@ -340,6 +362,11 @@ class LoansPage(LoggedPage, HTMLPage):
has_type = CleanText('./ancestor::table[.//th[contains(text(), "Type")]]', default=None)(self)
return CleanText('./td[2]')(self) if has_type else CleanText('./ancestor::table/preceding-sibling::div[1]')(self).split(' - ')[0]
def obj_ownership(self):
if'(m|mr|me|mme|mlle|mle|ml)\.? (.*)\b(ou)? (m|mr|me|mme|mlle|mle|ml)\b(.*)', CleanText(TableCell('id'))(self), re.IGNORECASE):
return AccountOwnership.CO_OWNER
return AccountOwnership.OWNER
def parse(self, el):
label = Field('label')(self)
trs = self.xpath('//td[contains(text(), $label)]/ancestor::tr[1] | ./ancestor::table[1]/tbody/tr', label=label)
......@@ -668,10 +695,11 @@ class BoursePage(LoggedPage, HTMLPage):
head_xpath = '//table[has-class("tableau_comptes_details")]/thead/tr/th'
col_label = 'Comptes'
col_owner = re.compile('Titulaire')
col_titres = re.compile('Valorisation')
col_especes = re.compile('Solde espèces')
class item(ItemElement):
class item(OwnedItemElement):
klass = Account
load_details = Field('_market_link') & AsyncLoad
......@@ -708,6 +736,10 @@ class BoursePage(LoggedPage, HTMLPage):
return Account.TYPE_MARKET
def obj_ownership(self):
owner = CleanText(TableCell('owner'))(self)
return self.get_ownership(owner)
def get_logout_link(self):
return Link('//a[@class="link-underline" and contains(text(), "espace client")]')(self.doc)
......@@ -828,7 +860,7 @@ class AVPage(LoggedPage, HTMLPage):
class get_popup_life_insurance(ListElement):
item_xpath = '//table[@class]/tbody/tr'
class item(ItemElement):
class item(OwnedItemElement):
klass = Account
def condition(self):
......@@ -851,6 +883,10 @@ class AVPage(LoggedPage, HTMLPage):
obj__external_website = False
obj__is_calie_account = False
def obj_ownership(self):
owner = CleanText(Field('_owner'))(self)
return self.get_ownership(owner)
def obj_id(self):
_id = CleanText('.//td/@id')(self)
# in old code, we use _id, it seems that is not used anymore
......@@ -1418,7 +1454,7 @@ class DepositPage(LoggedPage, HTMLPage):
col_name = 'Nom du contrat'
col_balance = 'Capital investi'
class item(ItemElement):
class item(OwnedItemElement):
klass = Account
obj_type = Account.TYPE_DEPOSIT
......@@ -1431,5 +1467,9 @@ class DepositPage(LoggedPage, HTMLPage):
obj_id = None
obj__transfer_id = None
def obj_ownership(self):
owner = CleanText(TableCell('owner'))(self)
return self.get_ownership(owner)
def set_deposit_account_id(self, account): = CleanText('//td[contains(text(), "N° contrat")]/following::td[1]//b')(self.doc)
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