Exemplo n.º 1
0
 def switch_account_to_loan(self, account):
     loan = Loan()
     copy_attrs = ('id', 'number', 'label', 'type', 'currency', '_index',
                   '_category', '_contract', '_id_element_contrat',
                   'owner_type')
     for attr in copy_attrs:
         setattr(loan, attr, getattr(account, attr))
     loan.balance = -account.balance
     return loan
Exemplo n.º 2
0
    def get_revolving_attributes(self, account):
        loan = Loan()
        loan.id = account.id
        loan.label = '%s - %s' %(account.label, account.id)
        loan.currency = account.currency
        loan.url = account.url

        loan.used_amount =  CleanDecimal.US('//tr[td[contains(text(), "Montant Utilisé") or contains(text(), "Montant utilisé")]]/td[2]')(self.doc)
        loan.available_amount = CleanDecimal.US(Regexp(CleanText('//tr[td[contains(text(), "Montant Disponible") or contains(text(), "Montant disponible")]]/td[2]'), r'(.*) au'))(self.doc)
        loan.balance  = -loan.used_amount
        loan._has_cards = False
        loan.type = Account.TYPE_REVOLVING_CREDIT
        return loan
Exemplo n.º 3
0
    def get_loan_account(self, account):
        assert account._prestation_id in Dict('donnees/tabIdAllPrestations')(self.doc), \
            'Loan with prestation id %s should be on this page ...' % account._prestation_id

        for acc in Dict('donnees/tabPrestations')(self.doc):
            if CleanText(Dict('idPrestation'))(acc) == account._prestation_id:
                loan = Loan()
                loan.id = loan.number = account.id
                loan.label = account.label
                loan.type = account.type
                loan.ownership = account.ownership

                loan.currency = Currency(Dict('capitalRestantDu/devise'))(acc)
                loan.balance = Eval(lambda x: x / 100, CleanDecimal(Dict('capitalRestantDu/valeur')))(acc)
                loan.coming = account.coming

                loan.total_amount = Eval(lambda x: x / 100, CleanDecimal(Dict('montantPret/valeur')))(acc)
                loan.next_payment_amount = Eval(lambda x: x / 100, CleanDecimal(Dict('montantEcheance/valeur')))(acc)

                loan.duration = Dict('dureeNbMois')(acc)
                loan.maturity_date = datetime.datetime.strptime(Dict('dateFin')(acc), '%Y%m%d')

                # We only know the next payment day (without the month or the year). But since we know that's
                # a monthly repayment, we can guess it.
                if CleanText(Dict('periodicite'))(acc) == 'MENSUELLE':
                    repayment_day = CleanDecimal(Dict('jourEcheanceMensuelle'))(acc)
                    if not repayment_day:
                        loan.next_payment_date = NotAvailable
                    else:
                        now = datetime.datetime.now().date()
                        next_payment_date = now.replace(day=repayment_day)
                        if repayment_day < now.day:
                            next_payment_date += relativedelta(months=1)
                        loan.next_payment_date = next_payment_date
                else:
                    self.logger.warning('Not handled periodicity: %s', CleanText(Dict('periodicite'))(acc))

                self.set_parent_account_id(loan, acc)

                loan._internal_id = account._internal_id
                loan._prestation_id = account._prestation_id
                loan._loan_type = account._loan_type
                return loan
Exemplo n.º 4
0
    def get_loan_attributes(self, account):
        loan = Loan()
        loan.total_amount = CleanDecimal('//div/span[contains(text(), "Capital initial")]/following-sibling::*[1]', replace_dots=True)(self.doc)
        owner_name = CleanText('//a[@class="lien-entete login"]/span')(self.doc)
        loan.name = ' '.join(owner_name.split()[1:])
        loan.subscription_date = Date(Regexp(CleanText('//h4[span[contains(text(), "Date de départ du prêt")]]'), r'(\d{2}\/\d{2}\/\d{4})'), dayfirst=True)(self.doc)
        loan.maturity_date = Date(Regexp(CleanText('//h4[span[contains(text(), "Date de fin du prêt")]]'), r'(\d{2}\/\d{2}\/\d{4})'), dayfirst=True)(self.doc)
        loan.rate = Eval(lambda x: x / 100, CleanDecimal('//div/span[contains(text(), "Taux fixe")]/following-sibling::*[1]', replace_dots=True))(self.doc)
        loan.last_payment_amount = CleanDecimal('//div[@class="txt-detail  " and not (@style)]//span[contains(text(), "Echéance du")]/following-sibling::span[1]')(self.doc)
        loan.last_payment_date = Date(Regexp(CleanText('//div[@class="txt-detail  " and not (@style)]//span[contains(text(), "Echéance du")]'), r'(\d{2}\/\d{2}\/\d{4})'), dayfirst=True)(self.doc)

        loan.id = account.id
        loan.currency = account.currency
        loan.label = account.label
        loan.balance = account.balance
        loan.coming = account.coming
        loan.type = account.type
        loan._uncleaned_id = account._uncleaned_id
        loan._multiple_type = account._multiple_type
        return loan
Exemplo n.º 5
0
    def get_revolving_attributes(self, account):
        loan = Loan()

        loan.available_amount = CleanDecimal('//div/span[contains(text(), "Montant disponible")]/following-sibling::*[1]', replace_dots=True)(self.doc)
        loan.used_amount = CleanDecimal('//div/span[contains(text(), "Montant Utilisé")]/following-sibling::*[1]', replace_dots=True)(self.doc)
        loan.total_amount = CleanDecimal('//div/span[contains(text(), "Réserve accordée")]/following-sibling::*[1]', replace_dots=True)(self.doc)
        loan.last_payment_amount = CleanDecimal('//div/span[contains(text(), "Echéance Précédente")]/following-sibling::*[1]', replace_dots=True)(self.doc)
        loan.last_payment_date = Date(Regexp(CleanText('//div/span[contains(text(), "Echéance Précédente")]/following-sibling::*[2]'), r'(\d{2}\/\d{2}\/\d{4})'), dayfirst=True)(self.doc)
        owner_name = CleanText('//a[@class="lien-entete login"]/span')(self.doc)
        loan.name = ' '.join(owner_name.split()[1:])

        loan.id = account.id
        loan.currency = account.currency
        loan.label = account.label
        loan.balance = account.balance
        loan.coming = account.coming
        loan.type = account.type
        loan._uncleaned_id = account._uncleaned_id
        loan._multiple_type = account._multiple_type
        return loan
Exemplo n.º 6
0
    def get_loan_account(self, account):
        assert account._prestation_id in Dict('donnees/tabIdAllPrestations')(self.doc), \
            'Loan with prestation id %s should be on this page ...' % account._prestation_id

        for acc in Dict('donnees/tabPrestations')(self.doc):
            if CleanText(Dict('idPrestation'))(acc) == account._prestation_id:
                loan = Loan()
                loan.id = loan.number = account.id
                loan.label = account.label
                loan.type = account.type
                loan.ownership = account.ownership

                loan.currency = Currency(Dict('capitalRestantDu/devise'))(acc)
                loan.balance = Eval(
                    lambda x: x / 100,
                    CleanDecimal(Dict('capitalRestantDu/valeur')))(acc)
                loan.coming = account.coming

                loan.total_amount = Eval(
                    lambda x: x / 100,
                    CleanDecimal(Dict('montantPret/valeur')))(acc)
                loan.next_payment_amount = Eval(
                    lambda x: x / 100,
                    CleanDecimal(Dict('montantEcheance/valeur')))(acc)
                loan.next_payment_date = self.guess_loan_monthly_repayment(acc)

                loan.duration = Dict('dureeNbMois')(acc)
                loan.maturity_date = datetime.datetime.strptime(
                    Dict('dateFin')(acc), '%Y%m%d')

                self.set_parent_account_id(loan, acc)

                loan._internal_id = account._internal_id
                loan._prestation_id = account._prestation_id
                loan._loan_type = account._loan_type
                return loan
Exemplo n.º 7
0
    def get_list(self):
        accounts = []

        for cpt in self.doc.xpath(
                '//div[contains(@class, " compte") and not(contains(@class, "compte_selected"))]'
        ):

            # ignore auto assurance accounts
            if 'aut' in cpt.get('class'):
                continue

            account = Account()
            account._history_link = Link(
                './ul/li/a[contains(@id, "consulter_solde") '
                'or contains(@id, "historique") '
                'or contains(@id, "contrat") '
                'or contains(@id, "assurance_vie_operations")]')(cpt)

            # this is to test if access to the accounts info is blocked for different reasons
            page = self.browser.open(account._history_link).page
            if isinstance(page, LoanPage):
                account = Loan()

            account._history_link = Link(
                './ul/li/a[contains(@id, "consulter_solde") '
                'or contains(@id, "historique") '
                'or contains(@id, "contrat") '
                'or contains(@id, "assurance_vie_operations")]')(cpt)
            if isinstance(page, LoanPage):
                account.id = CleanText(
                    '(//p[@id="c_montantEmprunte"]//span[@class="valStatic"]//strong)[1]'
                )(cpt)
                account.label = CleanText(
                    '(//p[@id="c_montantEmprunte"]//span[@class="valStatic"]//strong)[1]'
                )(cpt)
                account.type = Account.TYPE_LOAN
                account_history_page = self.browser.open(
                    account._history_link).page
                account.total_amount = account_history_page.get_total_amount()
                account.next_payment_amount = account_history_page.get_next_payment_amount(
                )
                account.next_payment_date = account_history_page.get_next_payment_date(
                )
                account.account_label = account_history_page.get_account_label(
                )
                account.subscription_date = account_history_page.get_subscription_date(
                )
                account.maturity_date = account_history_page.get_maturity_date(
                )

            if len(accounts) == 0:
                global_error_message = page.doc.xpath(
                    '//div[@id="as_renouvellementMIFID.do_"]/div[contains(text(), "Bonjour")] '
                    '| //div[@id="as_afficherMessageBloquantMigration.do_"]//div[@class="content_message"] '
                    '| //p[contains(text(), "Et si vous faisiez de Fortuneo votre banque principale")] '
                    '| //div[@id="as_renouvellementMotDePasse.do_"]//p[contains(text(), "votre mot de passe")]'
                    '| //div[@id="as_afficherSecuriteForteOTPIdentification.do_"]//span[contains(text(), "Pour valider ")]'
                )
                if global_error_message:
                    raise ActionNeeded(CleanText('.')(global_error_message[0]))
            local_error_message = page.doc.xpath(
                '//div[@id="error"]/p[@class="erreur_texte1"]')
            if local_error_message:
                raise BrowserUnavailable(
                    CleanText('.')(local_error_message[0]))

            number = RawText('./a[contains(@class, "numero_compte")]')(
                cpt).replace(u'N° ', '')

            account.id = CleanText(None).filter(number).replace(u'N°', '')

            account._card_links = []
            card_link = Link('./ul/li/a[contains(text(), "Carte bancaire")]',
                             default='')(cpt)
            if len(card_link) > 0:
                account._card_links.append(card_link)

            account.label = CleanText(
                './a[contains(@class, "numero_compte")]/@title')(cpt)

            for pattern, type in self.ACCOUNT_TYPES.items():
                if pattern in account._history_link:
                    account.type = type
                    break

            if account.type in {
                    Account.TYPE_PEA, Account.TYPE_MARKET,
                    Account.TYPE_LIFE_INSURANCE
            }:
                account._investment_link = Link(
                    './ul/li/a[contains(@id, "portefeuille")]')(cpt)
                balance = self.browser.open(
                    account._investment_link).page.get_balance(account.type)
                if account.type in {Account.TYPE_PEA, Account.TYPE_MARKET}:
                    self.browser.investments[account.id] = list(
                        self.browser.open(
                            account._investment_link).page.get_investments(
                                account))
            else:
                balance = self.browser.open(
                    account._history_link).page.get_balance()
                if account.type is not Account.TYPE_LOAN:
                    account.coming = self.browser.open(
                        account._history_link).page.get_coming()

            if account.type in {Account.TYPE_PEA, Account.TYPE_MARKET}:
                account.currency = self.browser.open(
                    account._investment_link).page.get_currency()
            else:
                account.currency = account.get_currency(balance)
            account.balance = CleanDecimal(None,
                                           replace_dots=True).filter(balance)

            if account.type in (Account.TYPE_CHECKING, Account.TYPE_SAVINGS):
                # Need a token sent by SMS to customers
                account.iban = NotAvailable

            if (account.label, account.id, account.balance) not in [
                (a.label, a.id, a.balance) for a in accounts
            ]:
                accounts.append(account)
        return accounts
Exemplo n.º 8
0
    def get_revolving_account(self, account):
        loan = Loan()
        loan.id = loan.number = account.id
        loan.label = account.label
        loan.type = account.type
        loan.ownership = account.ownership

        loan.currency = account.currency
        loan.balance = account.balance
        loan.coming = account.coming

        loan._internal_id = account._internal_id
        loan._prestation_id = account._prestation_id
        loan._loan_type = account._loan_type
        loan._is_json_histo = account._is_json_histo
        loan._parent_id = None

        if Dict('donnees/tabIdAllPrestations')(self.doc):
            for acc in Dict('donnees/tabPrestations')(self.doc):
                if CleanText(Dict('idPrestation'))(acc) == account._prestation_id:

                    # coming
                    if Dict('encoursFinMois', default=NotAvailable)(acc):
                        loan.coming = eval_decimal_amount('encoursFinMois/valeur', 'encoursFinMois/posDecimale')(acc)

                    # total amount
                    if Dict('reserveAutorisee', default=NotAvailable)(acc):
                        loan.total_amount = eval_decimal_amount('reserveAutorisee/valeur', 'reserveAutorisee/posDecimale')(acc)
                    elif Dict('montantAutorise', default=NotAvailable)(acc):
                        loan.total_amount = eval_decimal_amount('montantAutorise/valeur', 'montantAutorise/posDecimale')(acc)
                    else:
                        loan.total_amount = eval_decimal_amount('reserveMaximum/valeur', 'reserveMaximum/posDecimale')(acc)

                    # available amount
                    if Dict('montantDisponible', default=NotAvailable)(acc):
                        loan.available_amount = eval_decimal_amount('montantDisponible/valeur', 'montantDisponible/posDecimale')(acc)
                    else:
                        loan.available_amount = eval_decimal_amount('reserveDispo/valeur', 'reserveDispo/posDecimale')(acc)

                    # used amount
                    if Dict('reserveUtilisee', default=NotAvailable)(acc):
                        loan.used_amount = eval_decimal_amount('reserveUtilisee/valeur', 'reserveUtilisee/posDecimale')(acc)
                    elif Dict('montantUtilise', default=NotAvailable)(acc):
                        loan.available_amount = eval_decimal_amount('montantUtilise/valeur', 'montantUtilise/posDecimale')(acc)

                    # next payment amount
                    if Dict('prochaineEcheance', default=NotAvailable)(acc):
                        loan.next_payment_amount = eval_decimal_amount('prochaineEcheance/valeur', 'prochaineEcheance/posDecimale')(acc)
                    elif Dict('montantMensualite', default=NotAvailable)(acc):
                        loan.next_payment_amount = eval_decimal_amount('montantMensualite/valeur', 'montantMensualite/posDecimale')(acc)
                        loan.last_payment_amount = loan.next_payment_amount

                    loan.duration = Dict('dureeNbMois')(acc)

                    if Dict('dateMensualite', default=NotAvailable)(acc):
                        loan.next_payment_date = datetime.datetime.strptime(Dict('dateMensualite')(acc), '%Y%m%d')

                    self.set_parent_account_id(loan, acc)

                    return loan
        return loan
Exemplo n.º 9
0
    def get_list(self):
        accounts = []

        for cpt in self.doc.xpath('//div[contains(@class, " compte") and not(contains(@class, "compte_selected"))]'):

            # ignore auto assurance accounts
            if 'aut' in cpt.get('class'):
                continue

            account = Account()
            account._history_link = Link('./ul/li/a[contains(@id, "consulter_solde") '
                                         'or contains(@id, "historique") '
                                         'or contains(@id, "contrat") '
                                         'or contains(@id, "assurance_vie_operations")]')(cpt)

            # this is to test if access to the accounts info is blocked for different reasons
            page = self.browser.open(account._history_link).page
            if isinstance(page, LoanPage):
                account = Loan()

            account._history_link = Link('./ul/li/a[contains(@id, "consulter_solde") '
                                         'or contains(@id, "historique") '
                                         'or contains(@id, "contrat") '
                                         'or contains(@id, "assurance_vie_operations")]')(cpt)
            if isinstance(page, LoanPage):
                account.id = CleanText('(//p[@id="c_montantEmprunte"]//span[@class="valStatic"]//strong)[1]')(cpt)
                account.label = CleanText('(//p[@id="c_montantEmprunte"]//span[@class="valStatic"]//strong)[1]')(cpt)
                account.type = Account.TYPE_LOAN
                account_history_page = page
                account.total_amount = account_history_page.get_total_amount()
                account.next_payment_amount = account_history_page.get_next_payment_amount()
                account.next_payment_date = account_history_page.get_next_payment_date()
                account.account_label = account_history_page.get_account_label()
                account.subscription_date = account_history_page.get_subscription_date()
                account.maturity_date = account_history_page.get_maturity_date()
                account.ownership = account_history_page.get_owner()

            if len(accounts) == 0:
                global_error_message = page.doc.xpath('//div[@id="as_renouvellementMIFID.do_"]/div[contains(text(), "Bonjour")] '
                                                      '| //div[@id="as_afficherMessageBloquantMigration.do_"]//div[@class="content_message"] '
                                                      '| //p[contains(text(), "Et si vous faisiez de Fortuneo votre banque principale")] '
                                                      '| //div[@id="as_renouvellementMotDePasse.do_"]//p[contains(text(), "votre mot de passe")]'
                                                      '| //div[@id="as_afficherSecuriteForteOTPIdentification.do_"]//span[contains(text(), "Pour valider ")]')
                if global_error_message:
                    if "Et si vous faisiez de Fortuneo votre banque principale" in CleanText(global_error_message)(self):
                        self.browser.location('/ReloadContext', data={'action': 4})
                        return
                    raise ActionNeeded(CleanText('.')(global_error_message[0]))
            local_error_message = page.doc.xpath('//div[@id="error"]/p[@class="erreur_texte1"]')
            if local_error_message:
                raise BrowserUnavailable(CleanText('.')(local_error_message[0]))

            account.id = account.number = CleanText('./a[contains(@class, "numero_compte")]/div')(cpt).replace(u'N° ', '')
            account._ca = CleanText('./a[contains(@class, "numero_compte")]/@rel')(cpt)

            account._card_links = []
            card_link = Link('./ul/li/a[contains(text(), "Carte bancaire")]', default='')(cpt)
            if len(card_link) > 0:
                account._card_links.append(card_link)

            account.label = CleanText('./a[contains(@class, "numero_compte")]/@title')(cpt)

            for pattern, type in self.ACCOUNT_TYPES.items():
                if pattern in account._history_link:
                    account.type = type
                    break

            investment_page = None
            if account.type in (Account.TYPE_PEA, Account.TYPE_MARKET, Account.TYPE_LIFE_INSURANCE):
                account._investment_link = Link('./ul/li/a[contains(@id, "portefeuille")]')(cpt)
                investment_page = self.browser.location(account._investment_link).page
                balance = investment_page.get_balance(account.type)
                if account.type in (Account.TYPE_PEA, Account.TYPE_MARKET):
                    self.browser.investments[account.id] = list(self.browser.open(account._investment_link).page.get_investments(account))
            else:
                balance = page.get_balance()
                if account.type is not Account.TYPE_LOAN:
                    account.coming = page.get_coming()

            if account.type in (Account.TYPE_PEA, Account.TYPE_MARKET):
                account.currency = investment_page.get_currency()
            elif balance:
                account.currency = account.get_currency(balance)

            account.balance = CleanDecimal.French().filter(balance)

            if account.type in (Account.TYPE_CHECKING, Account.TYPE_SAVINGS):
                # Need a token sent by SMS to customers
                account.iban = NotAvailable

            if account.type is not Account.TYPE_LOAN:
                regexp = re.search(r'(m\. |mme\. )(.+)', CleanText('//span[has-class("mon_espace_nom")]')(self.doc), re.IGNORECASE)
                if regexp and len(regexp.groups()) == 2:
                    gender = regexp.group(1).replace('.', '').rstrip()
                    name = regexp.group(2)
                    label = account.label
                    if re.search(r'(m|mr|me|mme|mlle|mle|ml)\.? (.*)\bou (m|mr|me|mme|mlle|mle|ml)\b(.*)', label, re.IGNORECASE):
                        account.ownership = AccountOwnership.CO_OWNER
                    elif re.search(r'{} {}'.format(gender, name), label, re.IGNORECASE):
                        account.ownership = AccountOwnership.OWNER
                    else:
                        account.ownership = AccountOwnership.ATTORNEY

            if (account.label, account.id, account.balance) not in [(a.label, a.id, a.balance) for a in accounts]:
                accounts.append(account)
        return accounts