boursorama: support market investments

This commit is contained in:
Romain Bignon 2015-08-26 20:38:04 +02:00 committed by Romain Bignon
commit eab5e13189
4 changed files with 42 additions and 12 deletions

View file

@ -27,7 +27,8 @@ from weboob.deprecated.browser import StateBrowser, BrowserIncorrectPassword
from weboob.capabilities.bank import Account from weboob.capabilities.bank import Account
from .pages import (LoginPage, ProfilIncomplete, AccountsList, AccountHistory, CardHistory, from .pages import (LoginPage, ProfilIncomplete, AccountsList, AccountHistory, CardHistory,
UpdateInfoPage, AuthenticationPage, AccountInvestment, InvestmentDetail) UpdateInfoPage, AuthenticationPage, AccountLifeInsurance, AccountMarket,
InvestmentDetail)
__all__ = ['Boursorama'] __all__ = ['Boursorama']
@ -52,8 +53,9 @@ class Boursorama(StateBrowser):
r'.*/comptes/banque/cartes/mouvements.phtml.*': CardHistory, r'.*/comptes/banque/cartes/mouvements.phtml.*': CardHistory,
r'.*/comptes/epargne/mouvements.phtml.*': AccountHistory, r'.*/comptes/epargne/mouvements.phtml.*': AccountHistory,
r'.*/date_anniversaire.phtml.*': UpdateInfoPage, r'.*/date_anniversaire.phtml.*': UpdateInfoPage,
r'.*/detail.phtml.*': AccountInvestment, r'.*/detail.phtml.*': AccountLifeInsurance,
r'.*/opcvm.phtml.*': InvestmentDetail r'.*/opcvm.phtml.*': InvestmentDetail,
r'.*/positions_engagements.phtml.*': AccountMarket,
} }
__states__ = ('auth_token',) __states__ = ('auth_token',)
@ -146,7 +148,7 @@ class Boursorama(StateBrowser):
link = self.page.get_next_url() link = self.page.get_next_url()
def get_investment(self, account): def get_investment(self, account):
if account.type != Account.TYPE_LIFE_INSURANCE or not account._detail_url: if account.type not in (Account.TYPE_LIFE_INSURANCE, Account.TYPE_MARKET) or not account._detail_url:
raise NotImplementedError() raise NotImplementedError()
self.location(account._detail_url) self.location(account._detail_url)

View file

@ -24,7 +24,7 @@ from .card_history import CardHistory
from .accounts_list import AccountsList from .accounts_list import AccountsList
from .login import LoginPage, ProfilIncomplete, UpdateInfoPage from .login import LoginPage, ProfilIncomplete, UpdateInfoPage
from .two_authentication import AuthenticationPage from .two_authentication import AuthenticationPage
from .investment import AccountInvestment, InvestmentDetail from .investment import AccountMarket, AccountLifeInsurance, InvestmentDetail
class AccountPrelevement(AccountsList): class AccountPrelevement(AccountsList):
@ -37,6 +37,7 @@ __all__ = ['LoginPage',
'CardHistory', 'CardHistory',
'UpdateInfoPage', 'UpdateInfoPage',
'AuthenticationPage', 'AuthenticationPage',
'AccountInvestment', 'AccountMarket',
'AccountLifeInsurance',
'InvestmentDetail', 'InvestmentDetail',
] ]

View file

@ -28,17 +28,22 @@ from weboob.tools.capabilities.bank.transactions import FrenchTransaction
class AccountsList(Page): class AccountsList(Page):
def on_loaded(self): ACCOUNT_TYPES = {u'banque': Account.TYPE_CHECKING,
pass u'épargne': Account.TYPE_SAVINGS,
u'crédit': Account.TYPE_LOAN,
u'assurance vie': Account.TYPE_LIFE_INSURANCE,
u'bourse': Account.TYPE_MARKET,
}
def get_list(self): def get_list(self):
blocks = self.document.xpath('//div[@id="synthese-list"]//div[@class="block"]') blocks = self.document.xpath('//div[@id="synthese-list"]//div[@class="block"]')
for div in blocks: for div in blocks:
block_title = ''.join(div.xpath('.//span[@class="title"]//text()')).lower() block_title = ''.join(div.xpath('.//span[@class="title"]/a/text()')).lower().strip()
for tr in div.getiterator('tr'): for tr in div.getiterator('tr'):
account = Account() account = Account()
account.id = None account.id = None
account._link_id = None account._link_id = None
account.type = self.ACCOUNT_TYPES.get(block_title, Account.TYPE_UNKNOWN)
if 'assurance vie' in block_title: if 'assurance vie' in block_title:
# Life insurance accounts are investments # Life insurance accounts are investments
account.type = Account.TYPE_LIFE_INSURANCE account.type = Account.TYPE_LIFE_INSURANCE

View file

@ -25,6 +25,30 @@ from weboob.deprecated.browser import Page
from weboob.capabilities.bank import Investment from weboob.capabilities.bank import Investment
from weboob.browser.filters.standard import CleanDecimal from weboob.browser.filters.standard import CleanDecimal
Decimal = CleanDecimal(replace_dots=True).filter
class AccountMarket(Page):
def get_investment(self):
for tr in self.document.xpath('//table[@id="liste-positions-engagements"]/tbody/tr'):
cells = tr.xpath('./td')
if len(cells) < 6:
continue
inv = Investment()
inv.label = self.parser.tocleanstring(cells[0].xpath('.//a')[0])
isin_div = cells[0].xpath('.//div')
if len(isin_div) > 0:
inv.id = inv.code = self.parser.tocleanstring(isin_div[0])
inv.quantity = Decimal(cells[1])
inv.unitprice = Decimal(cells[2])
inv.unitvalue = Decimal(cells[3])
inv.valuation = Decimal(cells[4])
inv.diff = Decimal(cells[5])
inv._detail_url = None
yield inv
_el_to_string = XPath('string()') _el_to_string = XPath('string()')
@ -39,15 +63,13 @@ class IsinMixin(object):
return mobj.group(1) return mobj.group(1)
class AccountInvestment(IsinMixin, Page): class AccountLifeInsurance(IsinMixin, Page):
_re_isin = re.compile(r'isin=(\w+)') _re_isin = re.compile(r'isin=(\w+)')
_tr_list = XPath('//div[@id="content-gauche"]//table[@class="list"]/tbody/tr') _tr_list = XPath('//div[@id="content-gauche"]//table[@class="list"]/tbody/tr')
_td_list = XPath('./td') _td_list = XPath('./td')
_link = XPath('./td[1]/a/@href') _link = XPath('./td[1]/a/@href')
def get_investment(self): def get_investment(self):
Decimal = CleanDecimal(replace_dots=True).filter
for tr in self._tr_list(self.document): for tr in self._tr_list(self.document):
cells = list(el_to_string(td) for td in self._td_list(tr)) cells = list(el_to_string(td) for td in self._td_list(tr))
link = unicode(self._link(tr)[0]) link = unicode(self._link(tr)[0])