diff --git a/modules/apivie/browser.py b/modules/apivie/browser.py index 700960a631741c2095610f8f99b5085c66b39484..6d5b6efc1a6cc8652f4d7c4b4b1973be8e9e8053 100644 --- a/modules/apivie/browser.py +++ b/modules/apivie/browser.py @@ -17,6 +17,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with this weboob module. If not, see . +# flake8: compatible + from __future__ import unicode_literals from urllib3.exceptions import ReadTimeoutError @@ -27,7 +29,7 @@ from weboob.browser.exceptions import ClientError from .pages import ( - LoginPage, WrongpassPage, AccountsPage, + LoginPage, WrongpassPage, HomePage, AccountsPage, InvestmentPage, HistoryPage, InfoPage, ) @@ -42,16 +44,17 @@ class ApivieBrowser(LoginBrowser): LoginPage ) wrongpass = URL(r'/accueil.*saveLastPath=false', WrongpassPage) - info = URL(r'/coordonnees', InfoPage) - accounts = URL(r'/accueil-connect', AccountsPage) + info = URL(r'/coordonnees', r'/accueil-connect', InfoPage) + home = URL(r'/contrats-cosy3', HomePage) + accounts = URL(r'https://(?P.*)/interne/contrat/', AccountsPage) investments = URL(r'https://(?P.*)/contrat/(?P\d+)$', InvestmentPage) history = URL(r'https://(?P.*)/contrat/(?P\d+)/mouvements', HistoryPage) - def __init__(self, website, *args, **kwargs): super(ApivieBrowser, self).__init__(*args, **kwargs) self.BASEURL = 'https://%s' % website self.APIURL = 'hub.apivie.fr' + self.client_number = '' def do_login(self): if not self.login.is_here(): @@ -69,14 +72,15 @@ def do_login(self): if self.wrongpass.is_here(): raise BrowserIncorrectPassword() + # Accounts, Investments & Transactions are scraped on the Apivie API (https://hub.apivie.fr). + # The API is unstable and we get various errors, hence the @retry decorators. + @need_login + @retry(BrowserUnavailable, tries=3) def iter_accounts(self): - self.accounts.go() + self.accounts.go(api_url=self.APIURL) return self.page.iter_accounts() - # Investments & Transactions are scraped on the Apivie API (https://hub.apivie.fr). - # The API is unstable and we get various errors, hence the @retry decorators. - @need_login @retry(BrowserUnavailable, tries=3) def iter_investment(self, account): diff --git a/modules/apivie/module.py b/modules/apivie/module.py index 4e7a98ab45747e616de596eac2f776c81084e400..058cc2633005180a570966d25d2e3a391ef71c89 100644 --- a/modules/apivie/module.py +++ b/modules/apivie/module.py @@ -17,6 +17,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with this weboob module. If not, see . +# flake8: compatible + from __future__ import unicode_literals from weboob.capabilities.wealth import CapBankWealth diff --git a/modules/apivie/pages.py b/modules/apivie/pages.py index eb969551a80c6da50afe2aa850e74d6987533e7d..ba64eb93be1a20f31269e9756d3d22a6875e2472 100644 --- a/modules/apivie/pages.py +++ b/modules/apivie/pages.py @@ -17,19 +17,20 @@ # You should have received a copy of the GNU Lesser General Public License # along with this weboob module. If not, see . +# flake8: compatible + from __future__ import unicode_literals from weboob.capabilities.base import NotAvailable, empty from weboob.capabilities.bank import Account from weboob.capabilities.wealth import Investment from weboob.tools.capabilities.bank.transactions import FrenchTransaction -from weboob.browser.elements import TableElement, ItemElement, DictElement, method +from weboob.browser.elements import ItemElement, DictElement, method from weboob.browser.pages import LoggedPage, HTMLPage, JsonPage from weboob.browser.filters.standard import ( - CleanText, CleanDecimal, Date, Currency, + CleanText, CleanDecimal, Date, Field, MapIn, Eval, Lower, ) -from weboob.browser.filters.html import TableCell from weboob.browser.filters.json import Dict from weboob.tools.capabilities.bank.investments import IsinCode, IsinType @@ -37,6 +38,7 @@ class LoginPage(HTMLPage): def login(self, username, password): form = self.get_form(nr=0) + form['_58_redirect'] = '/accueil-connect' form['_58_login'] = username.encode('utf-8') form['_58_password'] = password.encode('utf-8') form.submit() @@ -51,34 +53,33 @@ def get_error_message(self): return CleanText('//span[@class="ui-messages-fatal-detail"]')(self.doc) +class HomePage(LoggedPage, HTMLPage): + pass + + ACCOUNT_TYPES = { 'apivie': Account.TYPE_LIFE_INSURANCE, 'liberalys vie': Account.TYPE_LIFE_INSURANCE, 'linxea zen': Account.TYPE_LIFE_INSURANCE, 'frontière efficiente': Account.TYPE_LIFE_INSURANCE, 'cristalliance vie': Account.TYPE_LIFE_INSURANCE, + 'article 82': Account.TYPE_LIFE_INSURANCE, 'liberalys retraite': Account.TYPE_PER, 'perp': Account.TYPE_PERP, } -class AccountsPage(LoggedPage, HTMLPage): +class AccountsPage(LoggedPage, JsonPage): @method - class iter_accounts(TableElement): - item_xpath = '//table[@summary="informations contrat"]/tbody/tr' - head_xpath = '//table[@summary="informations contrat"]/thead/tr/th' - - col_id = 'N° du contrat' - col_label = 'Produit' - col_balance = 'Valorisation' + class iter_accounts(DictElement): class item(ItemElement): klass = Account - obj_id = obj_number = CleanText(TableCell('id')) - obj_label = CleanText(TableCell('label')) - obj_balance = CleanDecimal.French(TableCell('balance')) - obj_currency = Currency(TableCell('balance')) + obj_id = obj_number = CleanText(Dict('contratId')) + obj_label = CleanText(Dict('produit')) + obj_balance = CleanDecimal.SI(Dict('encours')) + obj_currency = 'EUR' obj_type = MapIn(Lower(Field('label')), ACCOUNT_TYPES, Account.TYPE_UNKNOWN) @@ -102,13 +103,13 @@ def obj_portfolio_share(self): share = CleanDecimal.SI(Dict('repartition'), default=NotAvailable)(self) if empty(share): return NotAvailable - return Eval(lambda x: x/100, share)(self) + return Eval(lambda x: x / 100, share)(self) def obj_diff_ratio(self): diff_ratio = CleanDecimal.SI(Dict('performance', default=None), default=NotAvailable)(self) if empty(diff_ratio): return NotAvailable - return Eval(lambda x: x/100, diff_ratio)(self) + return Eval(lambda x: x / 100, diff_ratio)(self) def obj_srri(self): srri = CleanDecimal.SI(Dict('risque'), default=NotAvailable)(self)