Commit 93fe9b90 authored by Sylvie Ye's avatar Sylvie Ye Committed by Romain Bignon

[sgpe] retrieve market accounts and invests

parent 6e50faae
......@@ -26,7 +26,7 @@ from weboob.browser.browsers import LoginBrowser, need_login, StatesMixin
from weboob.browser.url import URL
from weboob.browser.exceptions import ClientError
from weboob.exceptions import BrowserIncorrectPassword, ActionNeeded, NoAccountsException
from weboob.capabilities.base import find_object
from weboob.capabilities.base import find_object, NotAvailable
from weboob.capabilities.bank import (
AccountNotFound, RecipientNotFound, AddRecipientStep, AddRecipientBankError,
Recipient, TransferBankError, AccountOwnerType,
......@@ -36,7 +36,7 @@ from weboob.tools.value import Value
from .pages import (
LoginPage, CardsPage, CardHistoryPage, IncorrectLoginPage,
ProfileProPage, ProfileEntPage, ChangePassPage, SubscriptionPage, InscriptionPage,
ErrorPage, UselessPage,
ErrorPage, UselessPage, MainPage, MarketAccountPage, MarketInvestmentPage,
)
from .json_pages import (
AccountsJsonPage, BalancesJsonPage, HistoryJsonPage, BankStatementPage,
......@@ -107,6 +107,10 @@ class SGPEBrowser(LoginBrowser):
@need_login
def get_cb_operations(self, account):
if account.type in (account.TYPE_MARKET, ):
# market account transactions are in checking account
return
self.location('/Pgn/NavigationServlet?PageID=Cartes&MenuID=%sOPF&Classeur=1&NumeroPage=1&Rib=%s&Devise=%s' % (self.MENUID, account.id, account.currency))
if self.inscription_page.is_here():
......@@ -132,6 +136,8 @@ class SGEnterpriseBrowser(SGPEBrowser):
MENUID = 'BANREL'
CERTHASH = '2231d5ddb97d2950d5e6fc4d986c23be4cd231c31ad530942343a8fdcc44bb99'
main_page = URL('/icd-web/syd-front/index-comptes.html', MainPage)
accounts = URL('/icd/syd-front/data/syd-comptes-accederDepuisMenu.json', AccountsJsonPage)
intraday_accounts = URL('/icd/syd-front/data/syd-intraday-accederDepuisMenu.json', AccountsJsonPage)
......@@ -142,6 +148,13 @@ class SGEnterpriseBrowser(SGPEBrowser):
'/icd/syd-front/data/syd-intraday-chargerDetail.json', HistoryJsonPage)
history_next = URL('/icd/syd-front/data/syd-comptes-chargerProchainLotEcriture.json', HistoryJsonPage)
market_investment = URL(r'/Pgn/NavigationServlet\?.*PageID=CompteTitreDetailFrame',
r'/Pgn/NavigationServlet\?.*PageID=CompteTitreDetail',
MarketInvestmentPage)
market_accounts = URL(r'/Pgn/NavigationServlet\?.*PageID=CompteTitreFrame',
r'/Pgn/NavigationServlet\?.*PageID=CompteTitre',
MarketAccountPage)
profile = URL('/gae/afficherModificationMesDonnees.html', ProfileEntPage)
subscription = URL(r'/Pgn/NavigationServlet\?MenuID=BANRELRIE&PageID=ReleveRIE&NumeroPage=1&Origine=Menu', SubscriptionPage)
......@@ -177,14 +190,37 @@ class SGEnterpriseBrowser(SGPEBrowser):
acc.owner_type = AccountOwnerType.ORGANIZATION
yield acc
# retrieve market accounts if exist
for market_account in self.iter_market_accounts():
yield market_account
@need_login
def iter_history(self, account):
if account.type in (account.TYPE_MARKET, ):
# market account transactions are in checking account
return
value = self.history.go(data={'cl500_compte': account._id, 'cl200_typeReleve': 'valeur'}).get_value()
for tr in self.history.go(data={'cl500_compte': account._id, 'cl200_typeReleve': value}).iter_history(value=value):
yield tr
for tr in self.location('/icd/syd-front/data/syd-intraday-chargerDetail.json', data={'cl500_compte': account._id}).page.iter_history():
yield tr
@need_login
def iter_market_accounts(self):
self.main_page.go()
# retrieve market accounts if exist
market_accounts_link = self.page.get_market_accounts_link()
# there are no examples of entreprise space with market accounts yet
assert not market_accounts_link, 'There are market accounts, retrieve them.'
return []
@need_login
def iter_investment(self, account):
# there are no examples of entreprise space with market accounts yet
return []
@need_login
def iter_subscription(self):
subscriber = self.get_profile()
......@@ -257,6 +293,39 @@ class SGProfessionalBrowser(SGEnterpriseBrowser, StatesMixin):
self.need_reload_state = None
super(SGProfessionalBrowser, self).load_state(state)
@need_login
def iter_market_accounts(self):
self.main_page.go()
# retrieve market accounts if exist
market_accounts_link = self.page.get_market_accounts_link()
if market_accounts_link is NotAvailable:
return []
assert market_accounts_link, 'Market accounts link xpath may have changed'
# need to be on market accounts page to get the accounts iframe
self.location(market_accounts_link)
market_accounts_list_link = self.page.get_table_iframe_link()
if market_accounts_list_link is NotAvailable:
return []
assert market_accounts_link, 'Market accounts iframe link xpath may have changed'
self.location(market_accounts_list_link)
return self.page.iter_market_accounts()
@need_login
def iter_investment(self, account):
if account.type not in (account.TYPE_MARKET, ):
return []
assert account._url_data, 'This account has no url to retrieve investments'
# need to be on market accounts investment page to get the invetment iframe
self.location('/Pgn/NavigationServlet?%s' % account._url_data)
invests_list_link = self.page.get_table_iframe_link()
assert invests_list_link, 'It seems that this market account has no investment'
self.location(invests_list_link)
return self.page.iter_investment()
def copy_recipient_obj(self, recipient):
rcpt = Recipient()
rcpt.id = recipient.iban
......
......@@ -24,15 +24,17 @@ import re
from io import BytesIO
from weboob.browser.pages import HTMLPage, LoggedPage
from weboob.browser.elements import ListElement, ItemElement, method
from weboob.browser.elements import ListElement, ItemElement, method, TableElement
from weboob.browser.filters.standard import (
CleanText, CleanDecimal, Date,
Env, Regexp, Field, Format,
Env, Regexp, Field, Format, TableCell,
)
from weboob.browser.filters.html import Attr
from weboob.browser.filters.html import Attr, Link
from weboob.tools.capabilities.bank.investments import is_isin_valid
from weboob.tools.capabilities.bank.transactions import FrenchTransaction
from weboob.capabilities.profile import Profile, Person
from weboob.capabilities.bill import Document, Subscription
from weboob.capabilities.bank import Account, Investment
from weboob.exceptions import ActionNeeded, BrowserIncorrectPassword, BrowserUnavailable
from weboob.tools.json import json
......@@ -269,3 +271,83 @@ class InscriptionPage(SGPEPage):
class UselessPage(LoggedPage, SGPEPage):
pass
class MainPage(LoggedPage, SGPEPage):
def get_market_accounts_link(self):
market_accounts_link = Link('//li/a[@title="Comptes titres"]', default=None)(self.doc)
if market_accounts_link:
return market_accounts_link
elif self.doc.xpath('//span[contains(text(), "Comptes titres") and contains(@title, "pas habilité à utiliser ce service")]'):
return NotAvailable
# return None when we don't know if there are market accounts or not
# it will be handled in `browser.py`
class MarketAccountPage(LoggedPage, SGPEPage):
def get_table_iframe_link(self):
if self.doc.xpath('//div[contains(text(), "Aucun compte-titres")]'):
return NotAvailable
return Attr('//iframe[@id="frameTableau"]', 'src')(self.doc)
@method
class iter_market_accounts(TableElement):
item_xpath = '//table[@id="tab-corps"]//tr'
head_xpath = '//table[@id="tab-entete"]//td'
col_id = 'COMPTE'
col_label = 'INTITULE'
col_balance = 'EVALUATION'
class item(ItemElement):
def condition(self):
# table with empty row filled by empty `td`
return Field('number')(self)
klass = Account
obj_id = Format('%s_TITRE', CleanText(TableCell('id'), replace=[(' ', '')]))
obj_number = CleanText(TableCell('id'), replace=[(' ', '')])
obj_label = CleanText(TableCell('label'))
obj_balance = CleanDecimal.French(CleanText(TableCell('balance')))
obj_type = Account.TYPE_MARKET
# all `a` balises have same `href`
obj__url_data = Regexp(Link('(.//a)[1]'), r"lienParent\('(.*)'\)", default=NotAvailable)
class MarketInvestmentPage(LoggedPage, SGPEPage):
def get_table_iframe_link(self):
return Attr('//iframe[@id="frameTableau"]', 'src')(self.doc)
@method
class iter_investment(TableElement):
item_xpath = '//table[@id="tab-corps"]//tr'
head_xpath = '//table[@id="tab-entete"]//td'
col_code = 'CODE'
col_label = 'VALEUR'
col_valuation = 'MONTANT'
col_quantity = 'QUANTITE'
col_unitvalue = 'COURS'
class item(ItemElement):
def condition(self):
# table with empty row filled by empty `td`
return Field('valuation')(self)
klass = Investment
obj_code_type = Investment.CODE_TYPE_ISIN
obj_label = CleanText(TableCell('label'))
obj_valuation = CleanDecimal.French(CleanText(TableCell('valuation')))
obj_quantity = CleanDecimal.French(CleanText(TableCell('quantity')))
obj_unitvalue = CleanDecimal.French(CleanText(TableCell('unitvalue')))
def obj_code(self):
code = CleanText(TableCell('code'))(self)
# there is no example of invests without valid ISIN code
# wait for it to retrieve them corretly
assert is_isin_valid(code), 'This code is not a valid ISIN, please check what invest is it.'
return code
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