Commit 91f1f22f authored by Quentin Defenouillere's avatar Quentin Defenouillere Committed by ntome

[ganassurances] Make this module standalone with former code from groupama

Groupama has shifted to the new website and is now a child of
ganpatrimoine, however ganassurances (a child of groupama) is still
using the old website, to I shifted all the code from groupama here so
ganassurances can still work correctly on the old website.
parent ddff30fa
# -*- coding: utf-8 -*-
# Copyright(C) 2012-2019 Budget Insight
# Copyright(C) 2012 Romain Bignon
# This file is part of a weboob module.
......@@ -17,19 +17,129 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this weboob module. If not, see <>.
import re
from weboob.browser import AbstractBrowser
from weboob.browser import LoginBrowser, URL, need_login
from weboob.exceptions import BrowserIncorrectPassword
from import Account
from weboob.capabilities.base import empty
from .pages import LoginPage, AccountsPage, TransactionsPage, AVAccountPage, AVHistoryPage, FormPage, IbanPage, AvJPage
__all__ = ['GanAssurancesBrowser']
class GanAssurancesBrowser(AbstractBrowser):
PARENT = 'groupama'
PARENT_ATTR = 'package.browser.GroupamaBrowser'
def __init__(self, website, *args, **kwargs):
class GanAssurancesBrowser(LoginBrowser):
login = URL(r'https://authentification.(?P<website>.*).fr/cas/login', LoginPage)
iban = URL(r'/wps/myportal/!ut/(.*)/\?paramNumCpt=(.*)', IbanPage)
accounts = URL(r'/wps/myportal/TableauDeBord', AccountsPage)
transactions = URL(r'/wps/myportal/!ut', TransactionsPage)
av_account_form = URL(r'/wps/myportal/assurancevie/', FormPage)
av_account = URL(r'',
r'/front/vie/epargne/contrat/(.*)', AVAccountPage)
av_history = URL(r'https://secure-rivage.(?P<website>.*).fr/contratVie.rivage.mesOperations.gsi', AVHistoryPage)
av_secondary = URL(r'/api/ecli/vie/contrats/(?P<id_contrat>.*)', AvJPage)
def __init__(self, *args, **kwargs):
super(GanAssurancesBrowser, self).__init__(*args, **kwargs)
self.BASEURL = 'https://%s' % website = re.findall('espaceclient.(.*?).fr', self.BASEURL)[0] = 'ganassurances'
self.domain = 'ganass'
def do_login(self):
login_url = '' % (, self.domain)
self.login.go(, params={'service': login_url}), self.password)
if self.login.is_here():
error_msg =
if error_msg and "LOGIN_ERREUR_MOT_PASSE_INVALIDE" in error_msg:
raise BrowserIncorrectPassword()
assert False, 'Unhandled error at login: %s' % error_msg
# For life asssurance accounts, to get balance we use the link from the account.
# And to get history (or other) we need to use the link again but the link works only once.
# So we get balance only for iter_account to not use the new link each time.
def get_accounts_list(self, balance=True, need_iban=False):
accounts = []
for account in
if account.type == Account.TYPE_LIFE_INSURANCE and balance:
assert empty(account.balance)
if self.av_account_form.is_here():
account.balance, account.currency =
# New page where some AV are stored
elif "front/vie/" in account._link:
link ='contrat\/(.+)-Groupama', account._link)
if link:
account.balance, account.currency =
if account.balance or not balance:
if account.type != Account.TYPE_LIFE_INSURANCE and need_iban:
if self.transactions.is_here() and
account.iban =
return accounts
def _get_history(self, account):
if "front/vie" in account._link:
return []
accounts = self.get_accounts_list(balance=False)
for a in accounts:
if ==
if a.type == Account.TYPE_LIFE_INSURANCE:
if not
self.logger.warning('history form not found for %s', account)
return []
assert self.transactions.is_here()
return []
# Duplicate line in case of arbitration because the site has only one line for the 2 transactions (debit and credit on the same line)
def get_history(self, account):
for tr in self._get_history(account):
yield tr
if getattr(tr, '_arbitration', False):
tr = tr.copy()
tr.amount = -tr.amount
yield tr
def get_coming(self, account):
if account.type == Account.TYPE_LIFE_INSURANCE:
return []
for a in self.get_accounts_list():
if ==
assert self.transactions.is_here()
link =
if link is not None:
assert self.transactions.is_here()
return []
def get_investment(self, account):
if account.type != Account.TYPE_LIFE_INSURANCE:
return []
for a in self.get_accounts_list(balance=False):
if ==
# There isn't any invest on AV having front/vie
# in theirs url
if "front/vie/" not in account._link:
if self.av_account.is_here():
return []
# -*- coding: utf-8 -*-
# Copyright(C) 2012-2013 Romain Bignon
# Copyright(C) 2012-2019 Romain Bignon
# This file is part of a weboob module.
......@@ -17,14 +17,13 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this weboob module. If not, see <>.
from __future__ import unicode_literals
from collections import OrderedDict
from __future__ import unicode_literals
from import CapBank
from import AbstractModule, BackendConfig
from import ValueBackendPassword, Value
from import CapBankWealth, AccountNotFound
from weboob.capabilities.base import find_object
from import Module, BackendConfig
from import Value, ValueBackendPassword
from .browser import GanAssurancesBrowser
......@@ -32,31 +31,36 @@ from .browser import GanAssurancesBrowser
__all__ = ['GanAssurancesModule']
class GanAssurancesModule(AbstractModule, CapBank):
class GanAssurancesModule(Module, CapBankWealth):
NAME = 'ganassurances'
MAINTAINER = 'Romain Bignon'
EMAIL = ''
VERSION = '1.6'
DESCRIPTION = 'Gan Assurances'
website_choices = OrderedDict([(k, '%s (%s)' % (v, k)) for k, v in sorted({
'': 'Groupama Banque',
'': 'Gan Assurances',
'': 'Gan Patrimoine',
}.items(), key=lambda k_v: (k_v[1], k_v[0]))])
CONFIG = BackendConfig(
Value('website', label='Banque', choices=website_choices, default=''),
ValueBackendPassword('login', label='Identifiant / N° Client ou Email ou Mobile', masked=False),
ValueBackendPassword('password', label='Mon mot de passe', regexp=r'^\d+$')
Value('login', label='Numéro client'),
ValueBackendPassword('password', label="Code d'accès")
PARENT = 'groupama'
BROWSER = GanAssurancesBrowser
def create_default_browser(self):
return self.create_browser(
def iter_accounts(self):
return self.browser.get_accounts_list(need_iban=True)
def get_account(self, _id):
return find_object(self.browser.get_accounts_list(need_iban=True), id=_id, error=AccountNotFound)
def iter_history(self, account):
return self.browser.get_history(account)
def iter_coming(self, account):
return self.browser.get_coming(account)
def iter_investment(self, account):
return self.browser.get_investment(account)
This diff is collapsed.
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