Пример #1
0
    def _add_account(self, accounts, link, label, account_type, balance):
        info = self._get_account_info(link)
        if info is None:
            self.logger.warning('Unable to parse account %r: %r' % (label, link))
            return

        account = Account()
        account.id = info['id']
        account.iban = u'FR76' + info['id']
        account._info = info
        account.label = label
        account.type = info['acc_type'] if 'acc_type' in info else account_type
        account.balance = Decimal(FrenchTransaction.clean_amount(balance)) if balance else self.get_balance(account)
        account.currency = account.get_currency(balance)
        account._card_links = []

        if account._info['type'] == 'HISTORIQUE_CB' and account.id in accounts:
            a = accounts[account.id]
            if not a.coming:
                a.coming = Decimal('0.0')
            a.coming += account.balance
            a._card_links.append(account._info)
            return

        accounts[account.id] = account
Пример #2
0
    def get_list(self):
        r = self.api_open('/transactionnel/services/rest/Account/accounts')

        for content in r.json()['content']:
            if self.accnum != '00000000000' and content['numero'] != self.accnum:
                continue
            for poste in content['postes']:
                a = Account()
                a._number = content['numeroLong']
                iban_response = self.api_open('/transactionnel/services/rest/Account/account/%s/iban' % a._number).json()
                a.iban = iban_response['content']['iban'] if 'content' in iban_response else NotAvailable
                a._nature = poste['codeNature']
                a._consultable = poste['consultable']
                a._univers = self.current_univers
                a.id = '%s.%s' % (a._number, a._nature)
                a.type = self.ACCOUNT_TYPES.get(poste['codeNature'], Account.TYPE_UNKNOWN)

                if 'numeroDossier' in poste and poste['numeroDossier']:
                    a._file_number = poste['numeroDossier']
                    a.id += '.%s' % a._file_number

                if poste['postePortefeuille']:
                    a.label = u'Portefeuille Titres'
                    a.balance = Decimal(str(poste['montantTitres']['valeur']))
                    a.currency = poste['montantTitres']['monnaie']['code'].strip()
                    yield a

                if 'libelle' not in poste:
                    continue

                a.label = ' '.join([content['intitule'].strip(), poste['libelle'].strip()])
                a.balance = Decimal(str(poste['solde']['valeur']))
                a.currency = poste['solde']['monnaie']['code'].strip()
                yield a
Пример #3
0
    def _add_account(self, accounts, link, label, account_type, balance):
        info = self._get_account_info(link, accounts)
        if info is None:
            self.logger.warning('Unable to parse account %r: %r' % (label, link))
            return

        account = Account()
        account.id = info['id']
        if is_rib_valid(info['id']):
            account.iban = rib2iban(info['id'])
        account._info = info
        account.label = label
        account.type = self.ACCOUNT_TYPES.get(label, info['acc_type'] if 'acc_type' in info else account_type)

        balance = balance or self.get_balance(account)
        account.balance = Decimal(FrenchTransaction.clean_amount(balance)) if balance and balance is not NotAvailable else NotAvailable

        account.currency = account.get_currency(balance) if balance and balance is not NotAvailable else NotAvailable
        account._card_links = []

        if account._info['type'] == 'HISTORIQUE_CB' and account.id in accounts:
            a = accounts[account.id]
            if not a.coming:
                a.coming = Decimal('0.0')
            if account.balance and account.balance is not NotAvailable:
                a.coming += account.balance
            a._card_links.append(account._info)
            return

        accounts[account.id] = account
Пример #4
0
    def get_list(self):
        table = self.find_table()
        for tr in self.parser.select(table, 'tr', 'many'):
            tds = self.parser.select(tr, 'td')
            if len(tds) != 6:
                continue
            tdlabel, tdid, tdcur, tdupdated, tdbal, tdbalcur = tds

            account = Account()
            account.label = to_unicode(tdlabel.text_content().strip())
            # this is important - and is also the last part of the id (considering spaces)
            # we can't use only the link as it does not goes where we want
            try:
                link = self.parser.select(tdlabel, 'a', 1)
            except BrokenPageError:
                # probably an account we can't display the history
                account._link_id = None
            else:
                account._link_id = parse_qs(link.attrib['href'])['ch4'][0]
            account.id = to_unicode(tdid.text.strip().replace(' ', ''))
            account.iban = 'FR76' + account.id
            # just in case we are showing the converted balances
            account._main_currency = Account.get_currency(tdcur.text)
            # we have to ignore those accounts, because using NotAvailable
            # makes boobank and probably many others crash
            if tdbal.text_content().strip() == 'indisponible':
                continue
            account.balance = Decimal(Transaction.clean_amount(tdbal.text_content()))
            account.currency = Account.get_currency(tdbalcur.text)
            account._updated = datetime.strptime(tdupdated.text, '%d/%m/%Y')
            yield account
Пример #5
0
    def iter_accounts(self):
        # Throw error from password value or random error
        self.maybe_generate_error(8)

        accounts = []

        first_account = Account()
        first_account.id = 'FR235711131719@fakebank'
        first_account.label = 'Compte chèque'
        first_account.currency = Currency.get_currency('42 €')
        first_account.iban = 'FR235711131719'
        first_account.balance = Decimal(random.uniform(0, 150))
        first_account.type = Account.TYPE_CHECKING
        accounts.append(first_account)

        second_account = Account()
        second_account.id = 'livretA@fakebank'
        second_account.label = 'Livret A'
        second_account.currency = Currency.get_currency('$42')
        second_account.balance = Decimal(500.0)
        second_account.type = Account.TYPE_SAVINGS
        accounts.append(second_account)

        third_account = Account()
        third_account.id = 'PEL@fakebank'
        third_account.label = 'Plan Epargne Logement'
        third_account.balance = Decimal(0.0)
        third_account.type = Account.TYPE_SAVINGS
        accounts.append(third_account)

        return accounts
Пример #6
0
    def _add_account(self, accounts, link, label, account_type, balance):
        info = self._get_account_info(link)
        if info is None:
            self.logger.warning('Unable to parse account %r: %r' %
                                (label, link))
            return

        account = Account()
        account.id = info['id']
        account.iban = u'FR76' + info['id']
        account._info = info
        account.label = label
        account.type = info['acc_type'] if 'acc_type' in info else account_type
        account.balance = Decimal(FrenchTransaction.clean_amount(
            balance)) if balance else self.get_balance(account)
        account.currency = account.get_currency(balance)
        account._card_links = []

        if account._info['type'] == 'HISTORIQUE_CB' and account.id in accounts:
            a = accounts[account.id]
            if not a.coming:
                a.coming = Decimal('0.0')
            a.coming += account.balance
            a._card_links.append(account._info)
            return

        accounts[account.id] = account
Пример #7
0
    def get_list(self):
        r = self.api_open('/transactionnel/services/rest/Account/accounts')

        for content in r.json()['content']:
            if self.accnum != '00000000000' and content[
                    'numero'] != self.accnum:
                continue
            for poste in content['postes']:
                a = Account()
                a._number = content['numeroLong']
                a._nature = poste['codeNature']
                a._consultable = poste['consultable']
                a._univers = self.current_univers
                a.id = '%s.%s' % (a._number, a._nature)
                a.type = self.ACCOUNT_TYPES.get(poste['codeNature'],
                                                Account.TYPE_UNKNOWN)
                if a.type == Account.TYPE_CHECKING:
                    iban_response = self.api_open(
                        '/transactionnel/services/rest/Account/account/%s/iban'
                        % a._number).json()
                    a.iban = iban_response['content'][
                        'iban'] if 'content' in iban_response else NotAvailable
                else:
                    a.iban = NotAvailable

                if 'numeroDossier' in poste and poste['numeroDossier']:
                    a._file_number = poste['numeroDossier']
                    a.id += '.%s' % a._file_number

                if poste['postePortefeuille']:
                    a.label = u'Portefeuille Titres'
                    a.balance = Decimal(str(poste['montantTitres']['valeur']))
                    a.currency = poste['montantTitres']['monnaie'][
                        'code'].strip()
                    yield a

                if 'libelle' not in poste:
                    continue

                a.label = ' '.join(
                    [content['intitule'].strip(), poste['libelle'].strip()])
                a.balance = Decimal(str(poste['solde']['valeur']))
                a.currency = poste['solde']['monnaie']['code'].strip()
                yield a
Пример #8
0
 def iter_accounts(self):
     for classeur in self.doc.get('donnees', {}).get('classeurs', {}):
         title = classeur['title']
         for compte in classeur.get('comptes', []):
             a = Account()
             a.label = CleanText().filter(compte['libelle'])
             a._id = compte['id']
             a.type = self.obj_type(a.label)
             a.number = compte['iban'].replace(' ', '')
             # for some account that don't have Iban the account number is store under this variable in the Json
             if not is_iban_valid(a.number):
                 a.iban = NotAvailable
             else:
                 a.iban = a.number
             # id based on iban to match ids in database.
             a.id = a.number[4:-2] if len(a.number) == 27 else a.number
             a._agency = compte['agenceGestionnaire']
             a._title = title
             yield a
Пример #9
0
 def iter_accounts(self):
     for classeur in self.doc.get('donnees', {}).get('classeurs', {}):
         title = classeur['title']
         for compte in classeur.get('comptes', []):
             a = Account()
             a.label = CleanText().filter(compte['libelle'])
             a._id = compte['id']
             a.type = self.obj_type(a.label)
             a.number = compte['iban'].replace(' ', '')
             # for some account that don't have Iban the account number is store under this variable in the Json
             if not is_iban_valid(a.number):
                 a.iban = NotAvailable
             else:
                 a.iban = a.number
             # id based on iban to match ids in database.
             a.id = a.number[4:-2] if len(a.number) == 27 else a.number
             a._agency = compte['agenceGestionnaire']
             a._title = title
             yield a
Пример #10
0
    def get_accounts(self):
        accounts = {}
        content = self.doc.xpath('//div[@id="moneyPage" or @id="MoneyPage"]')[0]

        # Multiple accounts
        lines = content.xpath('(//div[@class="col-md-8 multi-currency"])[1]/ul/li')
        for li in lines:
            account = Account()
            account.iban = NotAvailable
            account.type = Account.TYPE_CHECKING
            currency_code = CleanText().filter((li.xpath('./span[@class="currencyUnit"]/span') or li.xpath('./span[1]'))[0])
            currency = Currency.get_currency(currency_code)
            if not currency:
                self.logger.warning('Unable to find currency %r', currency_code)
                continue
            account.id = currency
            account.currency = currency
            account.balance = CleanDecimal(replace_dots=True).filter(li.xpath('./span[@class="amount"]/text()'))
            account.label = u'%s %s*' % (self.browser.username, account.currency)
            accounts[account.id] = account
            self.browser.account_currencies.append(account.currency)

        if not accounts:
        # Primary currency account
            primary_account = Account()
            primary_account.iban = NotAvailable
            primary_account.type = Account.TYPE_CHECKING
            try:
                balance = CleanText('.')(content.xpath('//div[contains(@class, "col-md-6")][contains(@class, "available")]')[0])
            except IndexError:
                primary_account.id = 'EUR'
                primary_account.currency = u'EUR'
                primary_account.balance = NotAvailable
                primary_account.label = u'%s' % (self.browser.username)
            else:
                primary_account.currency = Account.get_currency(balance)
                primary_account.id = unicode(primary_account.currency)
                primary_account.balance = Decimal(FrenchTransaction.clean_amount(balance))
                primary_account.label = u'%s %s*' % (self.browser.username, primary_account.currency)

            accounts[primary_account.id] = primary_account

        return accounts
Пример #11
0
 def iter_accounts(self):
     for classeur in self.doc.get('donnees', {}).get('classeurs', {}):
         title = classeur['title']
         for compte in classeur.get('comptes', []):
             a = Account()
             a.label = CleanText().filter(compte['libelle'])
             a._id = compte['id']
             a.iban = compte['iban'].replace(' ', '')
             # id based on iban to match ids in database.
             a.id = a.iban[4:-2] if len(a.iban) == 27 else a.iban
             a.type = self.obj_type(a.label)
             a._agency = compte['agenceGestionnaire']
             a._title = title
             yield a
Пример #12
0
 def iter_accounts(self):
     for classeur in self.doc['donnees']['classeurs']:
         title = classeur['title']
         for compte in classeur['comptes']:
             a = Account()
             a.label = compte['libelle']
             a._id = compte['id']
             a.iban = compte['iban'].replace(' ', '')
             # id based on iban to match ids in database.
             a.id = a.iban[4:-2]
             a.type = Account.TYPE_CHECKING
             a._agency = compte['agenceGestionnaire']
             a._title = title
             yield a
Пример #13
0
    def get_accounts(self):
        account = self.request('/api/accounts')

        a = Account()

        # Number26 only provides a checking account (as of sept 19th 2016).
        a.type = Account.TYPE_CHECKING
        a.label = u'Checking account'

        a.id = account["id"]
        a.number = NotAvailable
        a.balance = Decimal(str(account["availableBalance"]))
        a.iban = account["iban"]
        a.currency = u'EUR'

        return [a]
Пример #14
0
    def get_accounts(self):
        account = self.request('/api/accounts')

        a = Account()

        # Number26 only provides a checking account (as of sept 19th 2016).
        a.type = Account.TYPE_CHECKING
        a.label = u'Checking account'

        a.id = account["id"]
        a.number = NotAvailable
        a.balance = Decimal(str(account["availableBalance"]))
        a.iban = account["iban"]
        a.currency = u'EUR'

        return [a]
Пример #15
0
    def iter_accounts(self):
        if self.accounts:
            for account in self.accounts:
                yield account
            return

        waiting = False
        for project in self.users['projects']:
            self.open('/user/%s/project/%s/' %
                      (self.users['userId'], project['projectId']),
                      method="OPTIONS")
            me = self.request('/user/%s/project/%s/' %
                              (self.users['userId'], project['projectId']),
                              headers=self.request_headers)

            waiting = (me['status'] in self.waiting_statuses)

            # Check project in progress
            if not me['numeroContrat'] or not me['dateAdhesion'] or not me[
                    'solde']:
                continue

            a = Account()
            a.id = "".join(me['numeroContrat'].split())
            a.number = me['numeroContrat']
            a.label = " ".join(me['supportEpargne'].split("_"))
            a.type = Account.TYPE_LIFE_INSURANCE if "assurance vie" in a.label.lower() else \
                     Account.TYPE_MARKET if "compte titre" in a.label.lower() else \
                     Account.TYPE_PEA if "pea" in a.label.lower() else \
                     Account.TYPE_UNKNOWN
            a.balance = CleanDecimal().filter(me['solde'])
            a.currency = u'EUR'  # performanceEuro, montantEuro everywhere in Yomoni JSON
            a.iban = me['ibancompteTitre'] or NotAvailable
            a._project_id = project['projectId']
            a.valuation_diff = CleanDecimal().filter(me['performanceEuro'])
            a._startbalance = me['montantDepart']

            self.accounts.append(a)

            self.iter_investment(a, me['sousJacents'])

            yield a

        if not self.accounts and waiting:
            raise ActionNeeded(
                "Le service client Yomoni est en attente d'un retour de votre part."
            )
Пример #16
0
    def get_list(self, pro=True):
        accounts = []
        for tr in self.document.xpath('//tr[@class="comptes"]'):
            cols = tr.findall('td')

            if len(cols) < 5:
                continue

            account = Account()
            account.id = self.parser.tocleanstring(cols[self.COL_ID]).replace(" ", "")
            account.label = self.parser.tocleanstring(cols[self.COL_LABEL])
            account.balance = Decimal(self.parser.tocleanstring(cols[self.COL_BALANCE]))
            try:
                account.coming = Decimal(self.parser.tocleanstring(cols[self.COL_COMING]))
            except InvalidOperation:
                if self.parser.tocleanstring(cols[self.COL_COMING]) != '-':
                    self.logger.warning('Unable to parse coming value', exc_info=True)
                account.coming = NotAvailable
            account._link_id = None
            account._stp = None

            a = cols[self.COL_LABEL].find('a')
            if a is not None:
                url = urlparse(a.attrib['href'])
                p = dict(parse_qsl(url.query))
                account._link_id = p.get('ch4', None)
                account._stp = p.get('stp', None)

            for input_tag in tr.xpath('.//input[starts-with(@id, "urlRib")]'):
                m = re.search('ch4=(\w+)', input_tag.get('value', ''))
                if m:
                    account.iban = unicode(m.group(1))

            accounts.append(account)

        # If there are also personnal accounts linked, display the page and iter on them.
        if pro and len(self.document.xpath('//div[@class="onglets"]//a[contains(@href, "afficherComptesPrives")]')) > 0:
            self.browser.select_form(name='myForm')
            self.browser.set_all_readonly(False)
            self.browser['udcAction'] = '/afficherComptesPrives'
            self.browser.submit()

            for a in self.browser.page.get_list(False):
                accounts.append(a)

        return accounts
Пример #17
0
    def get_list(self):
        iban = None
        for tr in self.document.xpath('//table[@class="ca-table"]/tr'):
            if not tr.attrib.get('class', '').startswith('colcelligne'):
                continue

            cols = tr.findall('td')
            if not cols or len(cols) < 7:
                continue

            account = Account()
            account.id = self.parser.tocleanstring(cols[self.COL_ID])
            account.label = self.parser.tocleanstring(cols[self.COL_LABEL])
            account.type = self.TYPES.get(account.label, Account.TYPE_UNKNOWN)
            balance = self.parser.tocleanstring(cols[self.COL_VALUE])
            # we have to ignore those accounts, because using NotAvailable
            # makes boobank and probably many others crash
            if balance in ('indisponible', ''):
                continue
            account.balance = Decimal(Transaction.clean_amount(balance))
            account.currency = account.get_currency(
                self.parser.tocleanstring(cols[self.COL_CURRENCY]))
            account._link = None

            a = cols[0].find('a')
            if a is not None:
                account._link = a.attrib['href'].replace(' ', '%20')
                page = self.browser.get_page(
                    self.browser.openurl(account._link))
                url = page.get_iban_url()
                if url:
                    page = self.browser.get_page(self.browser.openurl(url))
                    iban = account.iban = page.get_iban()
                elif iban:
                    # In case there is no available IBAN on this account (for
                    # example saving account), calculate it from the previous
                    # IBAN.
                    bankcode = iban[4:9]
                    counter = iban[9:14]
                    key = 97 - ((int(bankcode) * 89 + int(counter) * 15 +
                                 int(account.id) * 3) % 97)
                    account.iban = iban[:
                                        4] + bankcode + counter + account.id + str(
                                            key)

            yield account
Пример #18
0
    def get_list(self, pro=True):
        accounts = []
        for tr in self.document.xpath('//tr[@class="comptes"]'):
            cols = tr.findall('td')

            if len(cols) < 5:
                continue

            account = Account()
            account.id = self.parser.tocleanstring(cols[self.COL_ID]).replace(" ", "")
            account.label = self.parser.tocleanstring(cols[self.COL_LABEL])
            account.balance = Decimal(self.parser.tocleanstring(cols[self.COL_BALANCE]))
            try:
                account.coming = Decimal(self.parser.tocleanstring(cols[self.COL_COMING]))
            except InvalidOperation:
                if self.parser.tocleanstring(cols[self.COL_COMING]) != '-':
                    self.logger.warning('Unable to parse coming value', exc_info=True)
                account.coming = NotAvailable
            account._link_id = None
            account._stp = None

            a = cols[self.COL_LABEL].find('a')
            if a is not None:
                url = urlparse(a.attrib['href'])
                p = dict(parse_qsl(url.query))
                account._link_id = p.get('ch4', None)
                account._stp = p.get('stp', None)

            for input_tag in tr.xpath('.//input[starts-with(@id, "urlRib")]'):
                m = re.search('ch4=(\w+)', input_tag.get('value', ''))
                if m:
                    account.iban = unicode(m.group(1))

            accounts.append(account)

        # If there are also personnal accounts linked, display the page and iter on them.
        if pro and len(self.document.xpath('//div[@class="onglets"]//a[contains(@href, "afficherComptesPrives")]')) > 0:
            self.browser.select_form(name='myForm')
            self.browser.set_all_readonly(False)
            self.browser['udcAction'] = '/afficherComptesPrives'
            self.browser.submit()

            for a in self.browser.page.get_list(False):
                accounts.append(a)

        return accounts
Пример #19
0
    def parse_table(self, what, actype=Account.TYPE_UNKNOWN):
        tables = self.document.xpath("//table[@id='%s']" % what,
                                     smart_strings=False)
        if len(tables) < 1:
            return

        lines = tables[0].xpath(".//tbody/tr")
        for line in lines:
            account = Account()
            tmp = line.xpath("./td//a")[0]
            account.label = to_unicode(tmp.text)
            account.type = actype
            account._link_id = tmp.get("href")
            if 'BourseEnLigne' in account._link_id:
                account.type = Account.TYPE_MARKET

            tmp = line.xpath("./td/span/strong")
            if len(tmp) >= 2:
                tmp_id = tmp[0].text
                tmp_balance = tmp[1].text
            else:
                tmp_id = line.xpath("./td//span")[1].text
                tmp_balance = tmp[0].text

            account.id = tmp_id
            account.currency = account.get_currency(tmp_balance)
            account.balance = Decimal(
                FrenchTransaction.clean_amount(tmp_balance))

            if account.id in self.accounts:
                a = self.accounts[account.id]
                a._card_links.append(account._link_id)
                if not a.coming:
                    a.coming = Decimal('0.0')
                a.coming += account.balance
            else:
                account._card_links = []
                self.accounts[account.id] = account

                page = self.browser.get_page(
                    self.browser.openurl(
                        self.browser.buildurl(
                            '/voscomptes/canalXHTML/comptesCommun/imprimerRIB/init-imprimer_rib.ea',
                            ('compte.numero', account.id))))
                account.iban = page.get_iban()
Пример #20
0
    def get_list(self):
        iban = None
        for tr in self.document.xpath('//table[@class="ca-table"]/tr'):
            if not tr.attrib.get('class', '').startswith('colcelligne'):
                continue

            cols = tr.findall('td')
            if not cols or len(cols) < 7:
                continue

            account = Account()
            account.id = self.parser.tocleanstring(cols[self.COL_ID])
            account.label = self.parser.tocleanstring(cols[self.COL_LABEL])
            account.type = self.TYPES.get(account.label, Account.TYPE_UNKNOWN)
            balance = self.parser.tocleanstring(cols[self.COL_VALUE])
            # we have to ignore those accounts, because using NotAvailable
            # makes boobank and probably many others crash
            if balance in ('indisponible', ''):
                continue
            account.balance = Decimal(Transaction.clean_amount(balance))
            account.currency = account.get_currency(self.parser.tocleanstring(cols[self.COL_CURRENCY]))
            account._link = None

            a = cols[0].find('a')
            if a is not None:
                account._link = a.attrib['href'].replace(' ', '%20')
                page = self.browser.get_page(self.browser.openurl(account._link))
                url = page.get_iban_url()
                if url:
                    page = self.browser.get_page(self.browser.openurl(url))
                    iban = account.iban = page.get_iban()
                elif iban:
                    # In case there is no available IBAN on this account (for
                    # example saving account), calculate it from the previous
                    # IBAN.
                    bankcode = iban[4:9]
                    counter = iban[9:14]
                    key = 97 - ((int(bankcode) * 89 + int(counter) * 15 + int(account.id) * 3) % 97)
                    account.iban = iban[:4] + bankcode + counter + account.id + str(key)

            yield account
Пример #21
0
    def iter_accounts(self):
        if self.accounts:
            for account in self.accounts:
                yield account
            return

        waiting = False

        for project in self.users['projects']:
            me = self.request('/user/%s/project/%s/' %
                              (self.users['userId'], project['projectId']))

            waiting = (me['status']
                       in ('RETURN_CUSTOMER_SERVICE', 'SUBSCRIPTION_STEP_3'))

            # Check project in progress
            if not me['numeroContrat'] or not me['dateAdhesion']:
                continue

            a = Account()
            a.id = "".join(me['numeroContrat'].split())
            a.label = " ".join(me['supportEpargne'].split("_"))
            a.type = Account.TYPE_LIFE_INSURANCE if "assurance vie" in a.label.lower() else \
                     Account.TYPE_MARKET if "compte titre" in a.label.lower() else \
                     Account.TYPE_UNKNOWN
            a.balance = CleanDecimal().filter(me['solde'])
            a.iban = me['ibancompteTitre'] or NotAvailable
            a.number = project['projectId']
            a.valuation_diff = CleanDecimal().filter(me['performanceEuro'])
            a._startbalance = me['montantDepart']

            self.accounts.append(a)

            self.iter_investment(a, me['sousJacents'])

            yield a

        if not self.accounts and waiting:
            raise ActionNeeded(
                "Le service client Yomoni est en attente d'un retour de votre part"
            )
Пример #22
0
    def iter_accounts(self):
        if self.accounts:
            for account in self.accounts:
                yield account
            return

        waiting = False
        for project in self.users['projects']:
            self.open('/user/%s/project/%s/' % (self.users['userId'], project['projectId']), method="OPTIONS")
            me = self.request('/user/%s/project/%s/' % (self.users['userId'], project['projectId']), headers=self.request_headers)

            waiting = (me['status'] in self.waiting_statuses)

            # Check project in progress
            if not me['numeroContrat'] or not me['dateAdhesion']:
                continue

            a = Account()
            a.id = "".join(me['numeroContrat'].split())
            a.label = " ".join(me['supportEpargne'].split("_"))
            a.type = Account.TYPE_LIFE_INSURANCE if "assurance vie" in a.label.lower() else \
                     Account.TYPE_MARKET if "compte titre" in a.label.lower() else \
                     Account.TYPE_PEA if "pea" in a.label.lower() else \
                     Account.TYPE_UNKNOWN
            a.balance = CleanDecimal().filter(me['solde'])
            a.currency = u'EUR' # performanceEuro, montantEuro everywhere in Yomoni JSON
            a.iban = me['ibancompteTitre'] or NotAvailable
            a.number = project['projectId']
            a.valuation_diff = CleanDecimal().filter(me['performanceEuro'])
            a._startbalance = me['montantDepart']

            self.accounts.append(a)

            self.iter_investment(a, me['sousJacents'])

            yield a

        if not self.accounts and waiting:
            raise ActionNeeded("Le service client Yomoni est en attente d'un retour de votre part.")
Пример #23
0
    def parse_table(self, what, actype=Account.TYPE_UNKNOWN):
        tables = self.document.xpath("//table[@id='%s']" % what, smart_strings=False)
        if len(tables) < 1:
            return

        lines = tables[0].xpath(".//tbody/tr")
        for line in lines:
            account = Account()
            tmp = line.xpath("./td//a")[0]
            account.label = to_unicode(tmp.text)
            account.type = actype
            account._link_id = tmp.get("href")
            if 'BourseEnLigne' in account._link_id:
                account.type = Account.TYPE_MARKET

            tmp = line.xpath("./td/span/strong")
            if len(tmp) >= 2:
                tmp_id = tmp[0].text
                tmp_balance = tmp[1].text
            else:
                tmp_id = line.xpath("./td//span")[1].text
                tmp_balance = tmp[0].text

            account.id = tmp_id
            account.currency = account.get_currency(tmp_balance)
            account.balance = Decimal(FrenchTransaction.clean_amount(tmp_balance))

            if account.id in self.accounts:
                a = self.accounts[account.id]
                a._card_links.append(account._link_id)
                if not a.coming:
                    a.coming = Decimal('0.0')
                a.coming += account.balance
            else:
                account._card_links = []
                self.accounts[account.id] = account

                page = self.browser.get_page(self.browser.openurl(self.browser.buildurl('/voscomptes/canalXHTML/comptesCommun/imprimerRIB/init-imprimer_rib.ea', ('compte.numero', account.id))))
                account.iban = page.get_iban()
Пример #24
0
    def _add_account(self, accounts, link, label, account_type, balance):
        info = self._get_account_info(link, accounts)
        if info is None:
            self.logger.warning('Unable to parse account %r: %r' %
                                (label, link))
            return

        account = Account()
        account.id = info['id']
        if is_rib_valid(info['id']):
            account.iban = rib2iban(info['id'])
        account._info = info
        account.label = label
        account.type = self.ACCOUNT_TYPES.get(
            label, info['acc_type'] if 'acc_type' in info else account_type)

        balance = balance or self.get_balance(account)
        account.balance = Decimal(
            FrenchTransaction.clean_amount(balance)
        ) if balance and balance is not NotAvailable else NotAvailable

        account.currency = account.get_currency(
            balance
        ) if balance and balance is not NotAvailable else NotAvailable
        account._card_links = []

        if account._info['type'] == 'HISTORIQUE_CB' and account.id in accounts:
            a = accounts[account.id]
            if not a.coming:
                a.coming = Decimal('0.0')
            if account.balance and account.balance is not NotAvailable:
                a.coming += account.balance
            a._card_links.append(account._info)
            return

        accounts[account.id] = account
Пример #25
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
Пример #26
0
    def get_list(self):
        call_response = self.location(
            '/transactionnel/services/rest/Account/accounts'
        ).json().get('content', [])
        seen = set()

        accounts_list = []

        for content in call_response:
            if self.accnum != '00000000000' and content['numero'] != self.accnum:
                continue
            for poste in content['postes']:
                a = Account()
                a._number = content['numeroLong']
                a._nature = poste['codeNature']
                a._codeSousPoste = poste['codeSousPoste'] if 'codeSousPoste' in poste else None
                a._consultable = poste['consultable']
                a._univers = self.current_univers
                a.id = '%s.%s' % (a._number, a._nature)

                if a.id in seen:
                    # some accounts like "compte à terme fidélis" have the same _number and _nature
                    # but in fact are kind of closed, so worthless...
                    self.logger.warning('ignored account id %r (%r) because it is already used', a.id, poste.get('numeroDossier'))
                    continue

                seen.add(a.id)

                a.type = self.ACCOUNT_TYPES.get(poste['codeNature'], Account.TYPE_UNKNOWN)
                if a.type == Account.TYPE_CHECKING:
                    iban_response = self.location(
                        '/transactionnel/services/rest/Account/account/%s/iban' % a._number
                    ).json().get('content', {})
                    a.iban = iban_response.get('iban', NotAvailable)
                else:
                    a.iban = NotAvailable

                if a.type == Account.TYPE_CARD:
                    a.parent = find_object(accounts_list, _number=a._number, type=Account.TYPE_CHECKING)

                if 'numeroDossier' in poste and poste['numeroDossier']:
                    a._file_number = poste['numeroDossier']
                    a.id += '.%s' % a._file_number

                if poste['postePortefeuille']:
                    a.label = u'Portefeuille Titres'
                    a.balance = Decimal(str(poste['montantTitres']['valeur']))
                    a.currency = poste['montantTitres']['monnaie']['code'].strip()
                    if not a.balance and not a.currency and 'dateTitres' not in poste:
                        continue
                    accounts_list.append(a)

                if 'libelle' not in poste:
                    continue

                a.label = ' '.join([content['intitule'].strip(), poste['libelle'].strip()])
                a.balance = Decimal(str(poste['solde']['valeur']))
                a.currency = poste['solde']['monnaie']['code'].strip()
                # Some accounts may have balance currency
                if 'Solde en devises' in a.label and a.currency != u'EUR':
                    a.id += str(poste['monnaie']['codeSwift'])
                accounts_list.append(a)

        return accounts_list
Пример #27
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, "assurance_vie_operations")]')(cpt)

            # this is to test if there is a redirection to a form for recently created profiles
            if len(accounts) == 0:
                message = self.browser.open(
                    account._history_link).page.doc.xpath(
                        '//div[@id="as_renouvellementMIFID.do_"]')
                if message:
                    raise ActionNeeded(
                        CleanText('./div[contains(text(), "Bonjour")]')(
                            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.iteritems():
                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.cache["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 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 iter(accounts)
Пример #28
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()

            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

            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.open(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()
            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
Пример #29
0
    def get_accounts(self):
        # This is required in case the browser is left in the middle of add_recipient and the session expires.
        if self.login.is_here():
            return self.get_accounts_list()

        profile_name = self.get_profile_name()
        if ' ' in profile_name:
            owner_name = re.search(r' (.+)', profile_name).group(1).upper()
        else:
            owner_name = profile_name.upper()

        # retrieve life insurance accounts
        self.assurancevie.stay_or_go()
        if self.no_perm.is_here():
            self.logger.warning('Life insurances are unavailable.')
        else:
            # retrieve life insurances from popups
            for a in self.page.get_popup_life_insurance(name=owner_name):
                self.update_accounts(a)

            # retrieve life insurances from calie website
            calie_index = self.page.get_calie_life_insurances_first_index()
            if calie_index:
                form = self.page.get_form(id="formRedirectPart")
                form['INDEX'] = calie_index
                form.submit()
                # if only one calie insurance, request directly leads to details on CaliePage
                if self.calie_detail.is_here():
                    self.page.check_error()
                    a = Account()
                    a.url = self.url
                    self.page.fill_account(obj=a)
                    self.update_accounts(a)
                # if several calie insurances, request leads to CalieContractsPage
                elif self.calie_contracts.is_here():
                    for a in self.page.iter_calie_life_insurance():
                        if a.url:
                            self.location(a.url)
                            self.page.fill_account(obj=a)
                            self.update_accounts(a)
                        else:
                            self.logger.warning(
                                '%s has no url to parse detail to' % a)
                # get back to life insurances list page
                self.assurancevie.stay_or_go()

            # retrieve life insurances on special lcl life insurance website
            if self.page.is_website_life_insurance():
                self.go_life_insurance_website()
                for life_insurance in self.page.iter_life_insurance():
                    life_insurance = self.update_life_insurance_account(
                        life_insurance)
                    self.update_accounts(life_insurance)
                self.go_back_from_life_insurance_website()

        # retrieve accounts on main page
        self.accounts.go()
        for a in self.page.get_accounts_list(name=owner_name):
            if not self.check_accounts(a):
                continue

            self.location('/outil/UWRI/Accueil/')
            if self.no_perm.is_here():
                self.logger.warning('RIB is unavailable.')
            elif self.page.has_iban_choice():
                self.rib.go(
                    data={
                        'compte': '%s/%s/%s' %
                        (a.id[0:5], a.id[5:11], a.id[11:])
                    })
                if self.rib.is_here():
                    iban = self.page.get_iban()
                    a.iban = iban if iban and a.id[
                        11:] in iban else NotAvailable
            else:
                iban = self.page.check_iban_by_account(a.id)
                a.iban = iban if iban is not None else NotAvailable
            self.update_accounts(a)

        # retrieve loans accounts
        self.loans.stay_or_go()
        if self.no_perm.is_here():
            self.logger.warning('Loans are unavailable.')
        else:
            for a in self.page.get_list():
                self.update_accounts(a)

        # retrieve pro loans accounts
        self.loans_pro.stay_or_go()
        if self.no_perm.is_here():
            self.logger.warning('Loans are unavailable.')
        else:
            for a in self.page.get_list():
                self.update_accounts(a)

        if self.connexion_bourse():
            for a in self.page.get_list(name=owner_name):
                self.update_accounts(a)
            self.deconnexion_bourse()
            # Disconnecting from bourse portal before returning account list
            # to be sure that we are on the banque portal

        # retrieve deposit accounts
        self.deposit.stay_or_go()
        if self.no_perm.is_here():
            self.logger.warning('Deposits are unavailable.')
        else:
            for a in self.page.get_list(name=owner_name):
                # There is no id on the page listing the 'Compte à terme'
                # So a form must be submitted to access the id of the contract
                self.set_deposit_account_id(a)
                self.update_accounts(a)
Пример #30
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
Пример #31
0
    def get_list(self):
        r = self.api_open('/transactionnel/services/rest/Account/accounts')

        seen = set()

        for content in r.json()['content']:
            if self.accnum != '00000000000' and content[
                    'numero'] != self.accnum:
                continue
            for poste in content['postes']:
                a = Account()
                a._number = content['numeroLong']
                a._nature = poste['codeNature']
                a._consultable = poste['consultable']
                a._univers = self.current_univers
                a.id = '%s.%s' % (a._number, a._nature)

                if a.id in seen:
                    # some accounts like "compte à terme fidélis" have the same _number and _nature
                    # but in fact are kind of closed, so worthless...
                    self.logger.warning(
                        'ignored account id %r (%r) because it is already used',
                        a.id, poste.get('numeroDossier'))
                    continue
                seen.add(a.id)

                a.type = self.ACCOUNT_TYPES.get(poste['codeNature'],
                                                Account.TYPE_UNKNOWN)
                if a.type == Account.TYPE_CHECKING:
                    iban_response = self.api_open(
                        '/transactionnel/services/rest/Account/account/%s/iban'
                        % a._number).json()
                    a.iban = iban_response['content'][
                        'iban'] if 'content' in iban_response else NotAvailable
                else:
                    a.iban = NotAvailable

                if 'numeroDossier' in poste and poste['numeroDossier']:
                    a._file_number = poste['numeroDossier']
                    a.id += '.%s' % a._file_number

                if poste['postePortefeuille']:
                    a.label = u'Portefeuille Titres'
                    a.balance = Decimal(str(poste['montantTitres']['valeur']))
                    a.currency = poste['montantTitres']['monnaie'][
                        'code'].strip()
                    if not a.balance and not a.currency and 'dateTitres' not in poste:
                        continue
                    yield a

                if 'libelle' not in poste:
                    continue

                a.label = ' '.join(
                    [content['intitule'].strip(), poste['libelle'].strip()])
                a.balance = Decimal(str(poste['solde']['valeur']))
                a.currency = poste['solde']['monnaie']['code'].strip()
                # Some accounts may have balance currency
                if 'Solde en devises' in a.label and a.currency != u'EUR':
                    a.id += str(poste['monnaie']['codeSwift'])
                yield a