Commit 461c08ff authored by Romain Bignon's avatar Romain Bignon

backport master modules fixes

parent 58368d91
Pipeline #1774 failed with stages
in 61 minutes and 9 seconds
......@@ -35,6 +35,11 @@ class CapBankTransferAddRecipient(CapBankTransfer, OLD.CapBankTransferAddRecipie
pass
class AddRecipientBankError(AddRecipientError):
code = 'bankMessage'
Account.TYPE_MORTGAGE = 17
Account.TYPE_CONSUMER_CREDIT = 18
Account.TYPE_REVOLVING_CREDIT = 19
......@@ -28,7 +28,7 @@ from weboob.browser.filters.standard import CleanText, Regexp, CleanDecimal, Dat
from weboob.browser.pages import HTMLPage, LoggedPage, pagination
from weboob.capabilities.bank import Account, Investment, Transaction
from weboob.capabilities.base import NotAvailable
from weboob.exceptions import BrowserUnavailable
from weboob.exceptions import BrowserUnavailable, ActionNeeded
class LoginPage(HTMLPage):
......@@ -51,6 +51,10 @@ class IndexPage(LoggedPage, HTMLPage):
def on_load(self):
HTMLPage.on_load(self)
msg = CleanText('//div[has-class("form-input-label")]', default='')(self.doc)
if "prendre connaissance des nouvelles conditions" in msg:
raise ActionNeeded(msg)
# website sometime crash
if self.doc.xpath(u'//div[@id="divError"]/span[contains(text(),"Une erreur est survenue")]'):
raise BrowserUnavailable()
......
......@@ -17,19 +17,20 @@
# You should have received a copy of the GNU Affero General Public License
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
from weboob.capabilities.calendar import BaseCalendarEvent, TRANSP, STATUS, CATEGORIES
from weboob.capabilities.collection import Collection
from weboob.capabilities.video import BaseVideo
from weboob.capabilities.image import Thumbnail
from weboob.capabilities.base import NotAvailable, NotLoaded, find_object
from weboob.capabilities.cinema import Movie, Person
from weboob.browser.browsers import APIBrowser
from weboob.browser.profiles import Android
from weboob.tools.compat import urlencode
import base64
import hashlib
from datetime import datetime, date, timedelta
import time
from datetime import date, datetime, timedelta
from weboob.browser.browsers import APIBrowser
from weboob.browser.profiles import Android
from weboob.capabilities.base import NotAvailable, NotLoaded, find_object
from weboob.capabilities.calendar import CATEGORIES, STATUS, TRANSP, BaseCalendarEvent
from weboob.capabilities.cinema import Movie, Person
from weboob.capabilities.collection import Collection
from weboob.capabilities.image import Thumbnail
from weboob.capabilities.video import BaseVideo
from weboob.tools.compat import unicode, urlencode
__all__ = ['AllocineBrowser']
......
......@@ -19,11 +19,12 @@
import re
from weboob.capabilities.base import UserError
from weboob.capabilities.calendar import CapCalendarEvent, CATEGORIES, BaseCalendarEvent
from weboob.capabilities.video import CapVideo, BaseVideo
from weboob.capabilities.collection import CapCollection, CollectionNotFound, Collection
from weboob.capabilities.cinema import CapCinema, Person, Movie
from weboob.capabilities.calendar import CATEGORIES, BaseCalendarEvent, CapCalendarEvent
from weboob.capabilities.cinema import CapCinema, Movie, Person
from weboob.capabilities.collection import CapCollection, Collection, CollectionNotFound
from weboob.capabilities.video import BaseVideo, CapVideo
from weboob.tools.backend import Module
from weboob.tools.compat import unicode
from .browser import AllocineBrowser
......
......@@ -41,7 +41,7 @@ class AmazonBrowser(LoginBrowser, StatesMixin):
L_SUBSCRIBER = 'Nom : (.*) Modifier E-mail'
login = URL(r'/ap/signin(.*)', LoginPage)
home = URL(r'/$', HomePage)
home = URL(r'/$', r'/\?language=\w+$', HomePage)
panel = URL('/gp/css/homepage.html/ref=nav_youraccount_ya', PanelPage)
subscriptions = URL(r'/ap/cnep(.*)', SubscriptionsPage)
documents = URL(r'/gp/your-account/order-history\?opt=ab&digitalOrders=1(.*)&orderFilter=year-(?P<year>.*)',
......@@ -170,7 +170,11 @@ class AmazonBrowser(LoginBrowser, StatesMixin):
def iter_subscription(self):
self.location(self.panel.go().get_sub_link())
if not self.subscriptions.is_here():
if self.home.is_here():
if self.page.get_login_link():
self.is_login()
self.location(self.page.get_panel_link())
elif not self.subscriptions.is_here():
self.is_login()
yield self.page.get_item()
......
......@@ -35,6 +35,9 @@ class HomePage(HTMLPage):
def get_login_link(self):
return self.doc.xpath('//a[./span[contains(., "%s")]]/@href' % self.browser.L_SIGNIN)[0]
def get_panel_link(self):
return Link('//a[contains(@href, "homepage.html") and has-class(@nav-link)]')(self.doc)
class PanelPage(LoggedPage, HTMLPage):
def get_sub_link(self):
......@@ -125,7 +128,7 @@ class DocumentsPage(LoggedPage, HTMLPage):
obj_id = Format('%s_%s', Env('subid'), Field('_simple_id'))
obj__pre_url = Format('/gp/shared-cs/ajax/invoice/invoice.html?orderId=%s&relatedRequestId=%s&isADriveSubscription=&isHFC=',
Field('_simple_id'), Env('request_id'))
obj_url = Async('details') & Link('//a[contains(@href, "download")]')
obj_url = Async('details') & Link('//a[contains(@href, "download")]|//a[contains(@href, "generated_invoices")]')
obj_format = 'pdf'
obj_label = Format('Facture %s', Field('_simple_id'))
obj_type = 'bill'
......
......@@ -18,18 +18,17 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
from weboob.capabilities.bank import AccountNotFound
from weboob.browser import LoginBrowser, URL, need_login
from weboob.exceptions import BrowserIncorrectPassword
from weboob.tools.compat import unquote
import json
import os
from subprocess import STDOUT, CalledProcessError, check_output
from tempfile import mkstemp
from subprocess import check_output, STDOUT, CalledProcessError
from .pages import SomePage, StatementsPage, StatementPage, SummaryPage, \
ActivityPage
from weboob.browser import URL, LoginBrowser, need_login
from weboob.capabilities.bank import AccountNotFound
from weboob.exceptions import BrowserIncorrectPassword
from weboob.tools.compat import unquote
from .pages import ActivityPage, SomePage, StatementPage, StatementsPage, SummaryPage
__all__ = ['AmazonStoreCard']
......@@ -66,24 +65,24 @@ class AmazonStoreCard(LoginBrowser):
'agent': self.session.headers['User-Agent']})
os.close(scrf)
os.close(cookf)
for i in xrange(self.MAX_RETRIES):
for i in range(self.MAX_RETRIES):
try:
check_output(["phantomjs", scrn], stderr=STDOUT)
break
except CalledProcessError as error:
pass
last_error = error
else:
raise error
raise last_error
with open(cookn) as cookf:
cookies = json.loads(cookf.read())
os.remove(scrn)
os.remove(cookn)
self.session.cookies.clear()
for c in cookies:
for k in ['expiry', 'expires', 'httponly']:
c.pop(k, None)
c['value'] = unquote(c['value'])
self.session.cookies.set(**c)
for k in ['expiry', 'expires', 'httponly']:
c.pop(k, None)
c['value'] = unquote(c['value'])
self.session.cookies.set(**c)
if not self.summary.go().logged:
raise BrowserIncorrectPassword()
......@@ -106,6 +105,7 @@ class AmazonStoreCard(LoginBrowser):
for t in s.iter_transactions():
yield t
LOGIN_JS = u'''\
var TIMEOUT = %(timeout)s*1000; // milliseconds
var page = require('webpage').create();
......
......@@ -19,12 +19,11 @@
from weboob.capabilities.bank import CapBank
from weboob.tools.backend import Module, BackendConfig
from weboob.tools.backend import BackendConfig, Module
from weboob.tools.value import ValueBackendPassword
from .browser import AmazonStoreCard
__all__ = ['AmazonStoreCardModule']
......@@ -39,16 +38,16 @@ class AmazonStoreCardModule(Module, CapBank):
ValueBackendPassword('username', label='User ID', masked=False),
ValueBackendPassword('password', label='Password'),
ValueBackendPassword('phone',
label='Phone to send verification code to', masked=False),
label='Phone to send verification code to', masked=False),
ValueBackendPassword('code_file',
label='File to read the verification code from', masked=False))
label='File to read the verification code from', masked=False))
BROWSER = AmazonStoreCard
def create_default_browser(self):
return self.create_browser(username = self.config['username'].get(),
password = self.config['password'].get(),
phone = self.config['phone'].get(),
code_file = self.config['code_file'].get())
return self.create_browser(username=self.config['username'].get(),
password=self.config['password'].get(),
phone=self.config['phone'].get(),
code_file=self.config['code_file'].get())
def iter_accounts(self):
return self.browser.iter_accounts()
......
......@@ -26,10 +26,18 @@ from weboob.tools.date import closest_date
from weboob.tools.pdf import decompress_pdf
from weboob.tools.tokenizer import ReTokenizer
from datetime import datetime, timedelta
from weboob.tools.compat import unicode
import re
import json
try:
cmp = cmp
except NameError:
def cmp(x, y):
return (x > y) - (x < y)
class SomePage(HTMLPage):
@property
def logged(self):
......@@ -39,7 +47,7 @@ class SomePage(HTMLPage):
class SummaryPage(SomePage):
def account(self):
label = u' '.join(self.doc.xpath(
'//div[contains(@class,"myCreditCardDetails")]')[0]\
'//div[contains(@class,"myCreditCardDetails")]')[0]
.text_content().split())
balance = self.amount(u'Balance')
cardlimit = self.doc.xpath(
......@@ -69,8 +77,8 @@ class SummaryPage(SomePage):
def amount(self, name):
return u''.join(self.doc.xpath(
u'//li[text()[.="%s"]]/../li[1]'%name)[0].text_content().split())\
.replace(u'\xb7',u'.').replace(u'*',u'')
u'//li[text()[.="%s"]]/../li[1]' % name)[0].text_content().split())\
.replace(u'\xb7', u'.').replace(u'*', u'')
class ActivityPage(SomePage):
......@@ -98,19 +106,20 @@ class ActivityPage(SomePage):
def parse_date(recdate):
return datetime.strptime(recdate, u'%B %d, %Y')
class StatementsPage(SomePage):
def iter_statements(self):
jss = self.doc.xpath(u'//a/@onclick[contains(.,"eBillViewPDFAction")]')
for js in jss:
url = re.match("window.open\('([^']*).*\)", js).group(1)
for i in xrange(self.browser.MAX_RETRIES):
for i in range(self.browser.MAX_RETRIES):
try:
self.browser.location(url)
break
except ServerError as e:
pass
last_error = e
else:
raise e
raise last_error
yield self.browser.page
......@@ -163,7 +172,7 @@ class StatementPage(RawPage):
pos, amount_layout = self.read_layout_td(pos)
pos, amount = self.read_amount(pos)
if tdate is None or pdate is None \
or desc is None or amount is None or amount == 0:
or desc is None or amount is None or amount == 0:
return startPos, None
else:
tdate = closest_date(tdate, date_from, date_to)
......@@ -208,7 +217,7 @@ class StatementPage(RawPage):
def read_text(self, pos):
t = self._tok.tok(pos)
#TODO: handle PDF encodings properly.
# TODO: handle PDF encodings properly.
return (pos+1, unicode(t.value(), errors='ignore')) \
if t.is_text() else (pos, None)
......
......@@ -85,7 +85,7 @@ class AccountPage(AmeliBasePage):
def iter_subscription_list(self):
names_list = self.doc.xpath('//span[@class="NomEtPrenomLabel"]')
fullname = CleanText(newlines=True).filter(names_list[0])
number = re.sub(r'[^\d]+', '', CleanText('//span[@class="blocNumSecu"]', replace=[(' ','')])(self.doc))
number = re.sub(r'[^\d]+', '', CleanText('//span[@class="blocNumSecu"]', replace=[(' ', '')])(self.doc))
sub = Subscription(number)
sub._id = number
sub.label = fullname
......@@ -118,7 +118,7 @@ class LastPaymentsPage(LoggedPage, AmeliBasePage):
try:
elt.xpath('.//a[contains(@id,"lienPDFReleve")]')[0]
except IndexError:
continue
continue
date_str = elt.xpath('.//span[contains(@id,"moisEnCours")]')[0].text
month_str = date_str.split()[0]
date = datetime.strptime(re.sub(month_str, str(FRENCH_MONTHS.index(month_str) + 1), date_str), "%m %Y").date()
......
......@@ -17,8 +17,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
import ssl
from .pages import LoginPage, AccountsPage, AccountHistoryPage
from weboob.browser import URL, LoginBrowser, need_login
from weboob.tools.json import json
......@@ -29,35 +27,18 @@ from weboob.browser.exceptions import ClientError
class AmundiBrowser(LoginBrowser):
TIMEOUT = 120.0
login = URL('/psf/authenticate', LoginPage)
authorize = URL('/psf/authorize', LoginPage)
accounts = URL('/psf/api/individu/positionFonds\?flagUrlFicheFonds=true&inclurePositionVide=false', AccountsPage)
account_history = URL('/psf/api/individu/operations\?valeurExterne=false&filtreStatutModeExclusion=false&statut=CPTA', AccountHistoryPage)
def __init__(self, website, *args, **kwargs):
self.BASEURL = website
super(AmundiBrowser, self).__init__(*args, **kwargs)
def prepare_request(self, req):
"""
Amundi uses TLS v1.0.
"""
preq = super(AmundiBrowser, self).prepare_request(req)
conn = self.session.adapters['https://'].get_connection(preq.url)
conn.ssl_version = ssl.PROTOCOL_TLSv1
return preq
login = URL(r'authenticate', LoginPage)
authorize = URL(r'authorize', LoginPage)
accounts = URL(r'api/individu/positionFonds\?flagUrlFicheFonds=true&inclurePositionVide=false', AccountsPage)
account_history = URL(r'api/individu/operations\?valeurExterne=false&filtreStatutModeExclusion=false&statut=CPTA', AccountHistoryPage)
def do_login(self):
"""
Attempt to log in.
Note: this method does nothing if we are already logged in.
"""
assert isinstance(self.username, basestring)
assert isinstance(self.password, basestring)
try:
self.login.go(data=json.dumps({'username' : self.username, 'password' : self.password}), \
self.login.go(data=json.dumps({'username': self.username, 'password': self.password}),
headers={'Content-Type': 'application/json;charset=UTF-8'})
self.token = self.authorize.go().get_token()
except ClientError:
......@@ -65,13 +46,22 @@ class AmundiBrowser(LoginBrowser):
@need_login
def iter_accounts(self):
return self.accounts.go(headers={'X-noee-authorization': ('noeprd %s' % self.token)}).iter_accounts()
return (self.accounts.go(headers={'X-noee-authorization': ('noeprd %s' % self.token)})
.iter_accounts())
@need_login
def iter_investments(self, account):
return self.accounts.go(headers={'X-noee-authorization': ('noeprd %s' % self.token)})\
.iter_investments(account_id=account.id)
return (self.accounts.go(headers={'X-noee-authorization': ('noeprd %s' % self.token)})
.iter_investments(account_id=account.id))
@need_login
def iter_history(self, account):
return self.account_history.go(headers={'X-noee-authorization': ('noeprd %s' % self.token)}).iter_history(account=account)
return (self.account_history.go(headers={'X-noee-authorization': ('noeprd %s' % self.token)})
.iter_history(account=account))
class EEAmundi(AmundiBrowser):
BASEURL = 'https://www.amundi-ee.com/psf/'
class TCAmundi(AmundiBrowser):
BASEURL = 'https://epargnants.amundi-tc.com/psf/'
......@@ -35,6 +35,11 @@ class CapBankTransferAddRecipient(CapBankTransfer, OLD.CapBankTransferAddRecipie
pass
class AddRecipientBankError(AddRecipientError):
code = 'bankMessage'
Account.TYPE_MORTGAGE = 17
Account.TYPE_CONSUMER_CREDIT = 18
Account.TYPE_REVOLVING_CREDIT = 19
......@@ -23,7 +23,7 @@ from weboob.capabilities.base import find_object
from weboob.tools.backend import Module, BackendConfig
from weboob.tools.value import ValueBackendPassword, Value
from .browser import AmundiBrowser
from .browser import EEAmundi, TCAmundi
__all__ = ['AmundiModule']
......@@ -35,59 +35,27 @@ class AmundiModule(Module, CapBankWealth):
EMAIL = 'james.galt.bi@gmail.com'
LICENSE = 'AGPLv3+'
VERSION = '1.3'
CONFIG = BackendConfig(ValueBackendPassword('login', label='Identifiant', regexp='\d+', masked=False),
ValueBackendPassword('password', label=u"Mot de passe", regexp='\d+'),
CONFIG = BackendConfig(ValueBackendPassword('login', label='Identifiant', regexp=r'\d+', masked=False),
ValueBackendPassword('password', label=u"Mot de passe", regexp=r'\d+'),
Value('website', label='Type de compte', default='ee',
choices={'ee': 'Amundi Epargne Entreprise',
'tc': 'Amundi Tenue de Compte'}))
BROWSER = AmundiBrowser
choices={'ee': 'Amundi Epargne Entreprise',
'tc': 'Amundi Tenue de Compte'}))
def create_default_browser(self):
w = {'ee': 'https://www.amundi-ee.com', 'tc': 'https://epargnants.amundi-tc.com'}
return self.create_browser(w[self.config['website'].get()], self.config['login'].get(), self.config['password'].get())
b = {'ee': EEAmundi, 'tc': TCAmundi}
self.BROWSER = b[self.config['website'].get()]
return self.create_browser(self.config['login'].get(), self.config['password'].get())
def get_account(self, id):
"""
Get an account from its ID.
:param id: ID of the account
:type id: :class:`str`
:rtype: :class:`Account`
:raises: :class:`AccountNotFound`
"""
return find_object(self.iter_accounts(), id=id, error=AccountNotFound)
def iter_accounts(self):
"""
Iter accounts.
:rtype: iter[:class:`Account`]
"""
return self.browser.iter_accounts()
def iter_investment(self, account):
"""
Iter investment of a market account
:param account: account to get investments
:type account: :class:`Account`
:rtype: iter[:class:`Investment`]
:raises: :class:`AccountNotFound`
"""
for inv in self.browser.iter_investments(account):
if inv.valuation != 0:
yield inv
def iter_history(self, account):
"""
Iter history of transactions on a specific account.
:param account: account to get history
:type account: :class:`Account`
:rtype: iter[:class:`Transaction`]
:raises: :class:`AccountNotFound`
"""
return self.browser.iter_history(account)
......@@ -17,6 +17,8 @@
# You should have received a copy of the GNU Affero General Public License
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
from datetime import datetime
from weboob.browser.elements import ItemElement, method, DictElement
......@@ -26,6 +28,7 @@ from weboob.browser.pages import LoggedPage, JsonPage
from weboob.capabilities.bank import Account, Investment, Transaction
from weboob.capabilities.base import NotAvailable
from weboob.exceptions import NoAccountsException
from weboob.tools.capabilities.bank.investments import is_isin_valid
class LoginPage(JsonPage):
......@@ -59,7 +62,7 @@ class AccountsPage(LoggedPage, JsonPage):
# just the id is a kind of company id so it can be unique on a backend but not unique on multiple backends
return '%s_%s' % (Field('id')(self), self.page.browser.username)
obj_currency = u"EUR"
obj_currency = 'EUR'
def obj_type(self):
return self.page.ACCOUNT_TYPES.get(Dict('typeDispositif')(self), Account.TYPE_LIFE_INSURANCE)
......@@ -67,7 +70,7 @@ class AccountsPage(LoggedPage, JsonPage):
def obj_label(self):
try:
return Dict('libelleDispositif')(self).encode('iso-8859-2').decode('utf8')
except (UnicodeEncodeError, UnicodeDecodeError):
except UnicodeError:
try:
return Dict('libelleDispositif')(self).encode('latin1').decode('utf8')
except UnicodeDecodeError:
......@@ -92,12 +95,17 @@ class AccountsPage(LoggedPage, JsonPage):
obj_code = Dict('codeIsin', default=NotAvailable)
obj_vdate = Date(Dict('dtVl'))
def obj_code_type(self):
if is_isin_valid(Field('code')(self)):
return Investment.CODE_TYPE_ISIN
return NotAvailable
class AccountHistoryPage(LoggedPage, JsonPage):
def belongs(self, instructions, account):
for ins in instructions:
if 'nomDispositif' in ins and 'codeDispositif' in ins and '%s%s' % (ins['nomDispositif'], ins['codeDispositif']) == \
'%s%s' % (account.label, account.id):
if 'nomDispositif' in ins and 'codeDispositif' in ins and '%s%s' % (
ins['nomDispositif'], ins['codeDispositif']) == '%s%s' % (account.label, account.id):
return True
return False
......@@ -105,8 +113,9 @@ class AccountHistoryPage(LoggedPage, JsonPage):
amount = 0
for ins in instructions:
if 'nomDispositif' in ins and 'montantNet' in ins and 'codeDispositif' in ins and '%s%s' % (ins['nomDispositif'], ins['codeDispositif']) == \
'%s%s' % (account.label, account.id):
if ('nomDispositif' in ins and 'montantNet' in ins and 'codeDispositif' in ins
and '%s%s' % (ins['nomDispositif'], ins['codeDispositif'])
== '%s%s' % (account.label, account.id)):
amount += ins['montantNet']
return CleanDecimal().filter(amount)
......@@ -119,21 +128,7 @@ class AccountHistoryPage(LoggedPage, JsonPage):
tr.amount = self.get_amount(hist['instructions'], account)
tr.rdate = datetime.strptime(hist['dateComptabilisation'].split('T')[0], '%Y-%m-%d')
tr.date = tr.rdate
tr.label = hist['libelleOperation'] if 'libelleOperation' in hist else hist['libelleCommunication']
tr.label = hist.get('libelleOperation') or hist['libelleCommunication']
tr.type = Transaction.TYPE_UNKNOWN
# Bypassed because we don't have the ISIN code
# tr.investments = []
# for ins in hist['instructions']:
# inv = Investment()
# inv.code = NotAvailable
# inv.label = ins['nomFonds']
# inv.description = ' '.join([ins['type'], ins['nomDispositif']])
# inv.vdate = datetime.strptime(ins.get('dateVlReel', ins.get('dateVlExecution')).split('T')[
# 0], '%Y-%m-%d')
# inv.valuation = Decimal(ins['montantNet'])
# inv.quantity = Decimal(ins['nombreDeParts'])
# inv.unitprice = inv.unitvalue = Decimal(ins['vlReel'])
# tr.investments.append(inv)
yield tr
......@@ -35,6 +35,11 @@ class CapBankTransferAddRecipient(CapBankTransfer, OLD.CapBankTransferAddRecipie
pass
class AddRecipientBankError(AddRecipientError):
code = 'bankMessage'
Account.TYPE_MORTGAGE = 17
Account.TYPE_CONSUMER_CREDIT = 18
Account.TYPE_REVOLVING_CREDIT = 19
......@@ -24,7 +24,7 @@ from calendar import day_name
from dateutil.relativedelta import relativedelta
import re
from weboob.browser import LoginBrowser, URL, need_login, StatesMixin
from weboob.browser.browsers import LoginBrowser, URL, need_login, StatesMixin
from weboob.browser.exceptions import ClientError, HTTPNotFound
from weboob.capabilities.base import NotAvailable
from weboob.capabilities.bill import Subscription
......@@ -32,6 +32,7 @@ from weboob.capabilities.bank import Account, Transaction, AddRecipientStep, Rec
from weboob.exceptions import BrowserIncorrectPassword, ActionNeeded
from weboob.tools.value import Value
from weboob.tools.capabilities.bank.transactions import sorted_transactions
from .compat.weboob_tools_capabilities_bank_investments import create_french_liquidity
from .pages.login import (
KeyboardPage, LoginPage, ChangepasswordPage, PredisconnectedPage, DeniedPage,
......@@ -39,9 +40,9 @@ from .pages.login import (
)
from .pages.bank import (
AccountsPage as BankAccountsPage, CBTransactionsPage, TransactionsPage,
UnavailablePage, IbanPage, LifeInsuranceIframe, BoursePage,
UnavailablePage, IbanPage, LifeInsuranceIframe, BoursePage, BankProfilePage,
)
from .pages.wealth import AccountsPage as WealthAccountsPage, InvestmentPage, HistoryPage
from .pages.wealth import AccountsPage as WealthAccountsPage, InvestmentPage, HistoryPage, ProfilePage
from .pages.transfer import (
RecipientsPage, AddRecipientPage, ValidateTransferPage, RegisterTransferPage,
ConfirmTransferPage, RecipientConfirmationPage,
......@@ -135,6 +136,7 @@ class AXABanque(AXABrowser, StatesMixin):
'webapp/axabanque/jsp/virementSepa/saisieVirementSepa.faces',
RegisterTransferPage)
confirm_transfer = URL('/webapp/axabanque/jsp/virementSepa/confirmationVirementSepa.faces', ConfirmTransferPage)
profile_page = URL('/transactionnel/client/coordonnees.html', BankProfilePage)