def get_error(self): return CleanText( '//h1[contains(text(), "Votre nouvel identifiant et mot de passe")]' )(self.doc)
def obj_start_date(self): start_time = Time( Regexp(CleanText('//aside[@id="detail"]/ul/li[1]'), r'(\d{2}:\d{2}) -'))(self) return CombineDate(self._date, start_time)(self)
def get_error(self): return CleanText( '//form[@id="CompteExterneActionForm"]//p[@class="container error"]//label[@class="error"]' )(self.doc)
def no_netfinca_access(self): return CleanText('//p[@class="gras" and contains(text(), "service CA-Titres est actuellement indisponible")]')(self.doc)
def get_perimeter_name(self): return Lower(CleanText('//div[@id="libPerimetre_2"]//span[@class="textePerimetre_2"]', default=''))(self.doc)
def is_here(self): return CleanText('//table[@class="ca-table"][caption[span[b[text()="Historique des opérations"]]]]')(self.doc)
def is_here(self): return CleanText('//span[@class="tdb-cartes-prop"]/b[contains(text(), "HISTORIQUE DES OPERATIONS")]')(self.doc)
def has_two_perimeters(self): # This message appears when there are only two perimeters. return CleanText('//div[@id="e-doc" and contains(text(), "Périmètre en cours de chargement")]')(self.doc)
def get_multiple_perimeters(self): perimeters = [] for perimeter in self.doc.xpath('//tr[@class="ca-forms"]//label[@class="gauche"]'): perimeters.append(CleanText(perimeter)(self)) return perimeters
def is_here(self): return CleanText('//form[@class="ca-forms"]//h1[text()="Fin de connexion"]')(self.doc)
def on_load(self): error_msg = CleanText('//fieldset//font[1]/text()', default='')(self.doc) if 'Le code personnel que vous allez choisir' in error_msg: raise BrowserPasswordExpired() assert False, 'Unhandled error on PasswordExpiredPage: %s' % error_msg
def get_accounts_url(self): return CleanText('//body')(self.doc)
def get_login_url(self): login_script = CleanText('//script[contains(text(), "acces_aux_comptes")]')(self.doc) url_search = re.search(r'([^"]+)" \|\|', login_script) if url_search: return url_search.group(1) return None
def unavailable_details(self): return CleanText('//p[contains(text(), "est pas disponible")]')( self.doc)
def condition(self): # Ignore cards that do not have a coming return CleanText('.//tr[1]/td[@class="cel-num"]')(self)
def is_here(self): return CleanText('//b[contains(text(), "IDENTITÉ BANCAIRE")]')(self.doc)
def condition(self): return 'Billet financier' not in CleanText('./td[1]')(self)
def get_iban(self): return CleanText('//div[@id="trPagePu"]//table[2]//td[font[b[contains(text(), "IBAN")]]]//tr//b/text()', replace=[(' ', '')], default=NotAvailable)(self.doc)
def parse(self, obj): self.env['date'] = DateGuesser(CleanText('./td[1]'), Env('date_guesser'))(self) self.env['vdate'] = NotAvailable if CleanText('//table[@class="ca-table"][caption[span[b[text()="Historique des opérations"]]]]//tr[count(td) = 4]')(self): # History table with 4 columns self.env['raw'] = CleanText('./td[2]', children=False)(self) self.env['amount'] = CleanDecimal.French('./td[last()]')(self) elif CleanText('//table[@class="ca-table"][caption[span[b[text()="Historique des opérations"]]]]//tr[count(td) = 5]')(self): # History table with 5 columns self.env['raw'] = CleanText('./td[3]', children=False)(self) self.env['amount'] = CleanDecimal.French('./td[last()]')(self) elif CleanText('//table[@class="ca-table"][caption[span[b[text()="Historique des opérations"]]]]//tr[count(td) = 6]')(self): # History table with 6 columns (contains vdate) self.env['raw'] = CleanText('./td[4]', children=False)(self) self.env['vdate'] = DateGuesser(CleanText('./td[2]'), Env('date_guesser'))(self) self.env['amount'] = CleanDecimal.French('./td[last()]')(self) elif CleanText('//table[@class="ca-table"][caption[span[b[text()="Historique des opérations"]]]]//tr[count(td) = 7]')(self): # History table with 7 columns self.env['amount'] = Coalesce( CleanDecimal.French('./td[6]', sign=lambda x: -1, default=None), CleanDecimal.French('./td[7]', default=None) )(self) if CleanText('//table[@class="ca-table"][caption[span[b[text()="Historique des opérations"]]]]//th[a[contains(text(), "Valeur")]]')(self): # With vdate column ('Valeur') self.env['raw'] = CleanText('./td[4]', children=False)(self) self.env['vdate'] = DateGuesser(CleanText('./td[2]'), Env('date_guesser'))(self) else: # Without any vdate column self.env['raw'] = CleanText('./td[3]', children=False)(self) else: assert False, 'This type of history table is not handled yet!'
def no_other_perimeter(self): return not CleanText('//a[@title="Espace Autres Comptes"]')(self.doc)
def is_here(self): return CleanText('//form[@class="ca-forms"]//h1[contains(text(), "Service indisponible")]')(self.doc)
def condition(self): # Skip card coming lines return 'Encours carte' not in CleanText(TableCell('label', colspan=True))(self)
def on_load(self): new_session_value = Regexp( CleanText('//script[@language="JavaScript"][contains(text(), "idSessionSag")]'), r'idSessionSag = "([^"]+)', default=None)(self.doc) if new_session_value: self.browser.session_value = new_session_value
def obj_balance(self): value_balance = CleanText(TableCell('value_balance', default='', colspan=True))(self) # Skip invalid balance values in the 'Value' column (for example for Revolving credits) if value_balance not in ('', 'Montant disponible'): return CleanDecimal.French().filter(value_balance) return CleanDecimal.French(CleanText(TableCell('operation_balance', default='', colspan=True)))(self)
def obj_code(self): code = CleanText('.//span[@class="cl-secondary"]')(self) if is_isin_valid(code): return code return NotAvailable
def has_unique_card(self): return not CleanText('//table[@summary]//caption[@class="ca-table caption"or @class="caption tdb-cartes-caption"]')(self.doc)
def on_load(self): if not self.doc.xpath('//input[@id="otp"]') and not self.doc.xpath( '//div[@class="confirmationAjoutCompteExterne"]'): raise AddRecipientBankError(message=CleanText( '//div[@id="aidesecuforte"]/p[contains("Nous vous invitons")]') (self.doc))
def is_here(self): return CleanText('//div[@class="boutons-act"]//h1[contains(text(), "Cartes")]')(self.doc)
def is_account_transferable(self, origin_account): for account in self.doc.xpath( '//select[@name="compteADebiter"]/option[not(@selected)]'): if origin_account.id in CleanText('.')(account): return True return False
def on_load(self): error_message = CleanText('//p[@id="errorSigned"]')(self.doc) if error_message: raise ActionNeeded(error_message)