Beispiel #1
0
    def get_list(self):
        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:
                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')

            yield account
Beispiel #2
0
    def get_list(self):
        accounts = []
        previous_account = None

        noaccounts = self.get_from_js('_js_noMvts =', ';')
        if noaccounts is not None:
            assert 'avez aucun compte' in noaccounts
            return []

        txt = self.get_from_js('_data = new Array(', ');', is_list=True)

        if txt is None:
            raise BrowserUnavailable('Unable to find accounts list in scripts')

        data = json.loads('[%s]' % txt.replace("'", '"'))

        for line in data:
            a = Account()
            a.id = line[self.COL_ID].replace(' ', '')

            if re.match(r'Classement=(.*?):::Banque=(.*?):::Agence=(.*?):::SScompte=(.*?):::Serie=(.*)', a.id):
                a.id = str(CleanDecimal().filter(a.id))

            a._acc_nb = a.id.split('_')[0] if len(a.id.split('_')) > 1 else None
            a.label = MyStrip(line[self.COL_LABEL], xpath='.//div[@class="libelleCompteTDB"]')
            # This account can be multiple life insurance accounts
            if a.label == 'ASSURANCE VIE-BON CAPI-SCPI-DIVERS *':
                continue

            a.balance = Decimal(FrenchTransaction.clean_amount(line[self.COL_BALANCE]))
            a.currency = a.get_currency(line[self.COL_BALANCE])
            a.type = self.get_account_type(a.label)

            # The parent account must be created right before
            if a.type == Account.TYPE_CARD:
                # duplicate
                if find_object(accounts, id=a.id):
                    self.logger.warning('Ignoring duplicate card %r', a.id)
                    continue
                a.parent = previous_account

            if line[self.COL_HISTORY] == 'true':
                a._inv = False
                a._link = self.get_history_link()
                a._args = self.make__args_dict(line)
            else:
                a._inv = True
                a._args = {'_ipc_eventValue':  line[self.COL_ID],
                           '_ipc_fireEvent':   line[self.COL_FIRE_EVENT],
                          }
                a._link = self.doc.xpath('//form[@name="changePageForm"]')[0].attrib['action']

            if a.type is Account.TYPE_CARD:
                a.coming = a.balance
                a.balance = Decimal('0.0')

            accounts.append(a)
            previous_account = a

        return accounts
Beispiel #3
0
    def get_list(self):
        accounts = []
        previous_account = None

        noaccounts = self.get_from_js('_js_noMvts =', ';')
        if noaccounts is not None:
            assert 'avez aucun compte' in noaccounts
            return []

        txt = self.get_from_js('_data = new Array(', ');', is_list=True)

        if txt is None:
            raise BrowserUnavailable('Unable to find accounts list in scripts')

        data = json.loads('[%s]' % txt.replace("'", '"'))

        for line in data:
            a = Account()
            a.id = line[self.COL_ID].replace(' ', '')

            if re.match(r'Classement=(.*?):::Banque=(.*?):::Agence=(.*?):::SScompte=(.*?):::Serie=(.*)', a.id):
                a.id = str(CleanDecimal().filter(a.id))

            a._acc_nb = a.id.split('_')[0] if len(a.id.split('_')) > 1 else None
            a.label = MyStrip(line[self.COL_LABEL], xpath='.//div[@class="libelleCompteTDB"]')
            # This account can be multiple life insurance accounts
            if a.label == 'ASSURANCE VIE-BON CAPI-SCPI-DIVERS *':
                continue

            a.balance = Decimal(FrenchTransaction.clean_amount(line[self.COL_BALANCE]))
            a.currency = a.get_currency(line[self.COL_BALANCE])
            a.type = self.get_account_type(a.label)

            # The parent account must be created right before
            if a.type == Account.TYPE_CARD:
                # duplicate
                if find_object(accounts, id=a.id):
                    self.logger.warning('Ignoring duplicate card %r', a.id)
                    continue
                a.parent = previous_account

            if line[self.COL_HISTORY] == 'true':
                a._inv = False
                a._link = self.get_history_link()
                a._args = self.make__args_dict(line)
            else:
                a._inv = True
                a._args = {'_ipc_eventValue':  line[self.COL_ID],
                           '_ipc_fireEvent':   line[self.COL_FIRE_EVENT],
                          }
                a._link = self.doc.xpath('//form[@name="changePageForm"]')[0].attrib['action']

            if a.type is Account.TYPE_CARD:
                a.coming = a.balance
                a.balance = Decimal('0.0')

            accounts.append(a)
            previous_account = a

        return accounts
Beispiel #4
0
    def get_list(self):
        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:
                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')

            yield account
Beispiel #5
0
    def get_list(self):
        for div in self.document.xpath('.//div[@id="card-details"]'):
            a = Account()
            a.id = self.parser.tocleanstring(
                div.xpath('.//span[@class="acc-num"]')[0])
            a.label = self.parser.tocleanstring(
                div.xpath('.//span[@class="card-desc"]')[0])
            if "carte" in a.label.lower():
                a.type = Account.TYPE_CARD
            balance = self.parser.tocleanstring(
                div.xpath('.//span[@class="balance-data"]')[0])
            if balance in (u'Indisponible',
                           u'Indisponible Facturation en cours', ''):
                a.balance = NotAvailable
            else:
                a.currency = a.get_currency(balance)
                a.balance = -abs(
                    CleanDecimal(
                        replace_dots=a.currency == 'EUR').filter(balance))

            # Cancel card don't have a link to watch history
            link = self.document.xpath('.//div[@class="wide-bar"]/h3/a')
            if len(link) == 1:
                a._link = link[0].attrib['href']
            else:
                a._link = None

            yield a
Beispiel #6
0
    def get_list(self):
        account_type = Account.TYPE_UNKNOWN
        accounts = []

        for tr in self.document.xpath('//table[@class="ecli"]/tr'):
            if tr.attrib.get('class', '') == 'entete':
                account_type = self.ACCOUNT_TYPES.get(tr.find('th').text.strip(), Account.TYPE_UNKNOWN)
                continue

            tds = tr.findall('td')

            balance = tds[-1].text.strip()
            if balance == '':
                continue

            account = Account()
            account.label = u' '.join([txt.strip() for txt in tds[0].itertext()])
            account.label = re.sub(u'[ \xa0\u2022\r\n\t]+', u' ', account.label).strip()
            account.id = re.findall('(\d+)', account.label)[0]
            account.balance = Decimal(FrenchTransaction.clean_amount(balance))
            account.currency = account.get_currency(balance)
            account.type = account_type
            m = re.search(r"javascript:submitForm\(([\w_]+),'([^']+)'\);", tds[0].find('a').attrib['onclick'])
            if not m:
                self.logger.warning('Unable to find link for %r' % account.label)
                account._link = None
            else:
                account._link = m.group(2)

            accounts.append(account)

        return accounts
Beispiel #7
0
    def get_list(self):
        accounts = []

        txt = self.get_from_js('_data = new Array(', ');', is_list=True)

        if txt is None:
            raise BrokenPageError('Unable to find accounts list in scripts')

        data = json.loads('[%s]' % txt.replace("'", '"'))

        for line in data:
            a = Account()
            a.id = line[self.COL_ID].replace(' ', '')
            a._acc_nb = a.id.split('_')[0] if len(
                a.id.split('_')) > 1 else None
            fp = StringIO(
                unicode(line[self.COL_LABEL]).encode(self.browser.ENCODING))
            a.label = self.parser.tocleanstring(
                self.parser.parse(fp, self.browser.ENCODING).xpath(
                    '//div[@class="libelleCompteTDB"]')[0])
            # This account can be multiple life insurance accounts
            if a.label == 'ASSURANCE VIE-BON CAPI-SCPI-DIVERS *':
                continue

            a.balance = Decimal(
                FrenchTransaction.clean_amount(line[self.COL_BALANCE]))
            a.currency = a.get_currency(line[self.COL_BALANCE])
            a.type = self.get_account_type(a.label)
            if line[self.COL_HISTORY] == 'true':
                a._inv = False
                a._link = self.get_history_link()
                a._args = {
                    '_eventId': 'clicDetailCompte',
                    '_ipc_eventValue': '',
                    '_ipc_fireEvent': '',
                    'deviseAffichee': 'DEVISE',
                    'execution': self.get_execution(),
                    'idCompteClique': line[self.COL_ID],
                }
            else:
                a._inv = True
                a._args = {
                    '_ipc_eventValue': line[self.COL_ID],
                    '_ipc_fireEvent': line[self.COL_FIRE_EVENT],
                }
                a._link = self.document.xpath(
                    '//form[@name="changePageForm"]')[0].attrib['action']

            if a.id.find('_CarteVisa') >= 0:
                accounts[-1]._card_ids.append(a._args)
                if not accounts[-1].coming:
                    accounts[-1].coming = Decimal('0.0')
                accounts[-1].coming += a.balance
                continue

            a._card_ids = []
            accounts.append(a)

        return accounts
Beispiel #8
0
    def get_list(self):
        TABLE_XPATH = '//table[caption[@class="caption tdb-cartes-caption" or @class="ca-table caption"]]'

        cards_tables = self.document.xpath(TABLE_XPATH)

        currency = self.document.xpath('//table/caption//span/text()[starts-with(.,"Montants en ")]')[0].replace("Montants en ", "") or None
        if cards_tables:
            self.logger.debug('There are several cards')
            xpaths = {
                '_id': './caption/span[@class="tdb-cartes-num"]',
                'label1': './caption/span[contains(@class, "tdb-cartes-carte")]',
                'label2': './caption/span[@class="tdb-cartes-prop"]',
                'balance': './/tr/td[@class="cel-num"]',
                'currency': '//table/caption//span/text()[starts-with(.,"Montants en ")]',
                'link': './/tr//a/@href[contains(., "fwkaction=Detail")]',
            }
        else:
            self.logger.debug('There is only one card')
            xpaths = {
                '_id': './/tr/td[@class="cel-texte"]',
                'label1': './/tr[@class="ligne-impaire ligne-bleu"]/th',
                'label2': './caption/span[@class="tdb-cartes-prop"]/b',
                'balance': './/tr[last()-1]/td[@class="cel-num"] | .//tr[last()-2]/td[@class="cel-num"]',
                'currency': '//table/caption//span/text()[starts-with(.,"Montants en ")]',
            }
            TABLE_XPATH = '(//table[@class="ca-table"])[1]'
            cards_tables = self.document.xpath(TABLE_XPATH)


        for table in cards_tables:
            get = lambda name: self.parser.tocleanstring(table.xpath(xpaths[name])[0])

            account = Account()
            account.type = account.TYPE_CARD
            account.id = ''.join(get('_id').split()[1:])
            account._id = ' '.join(get('_id').split()[1:])
            account.label = '%s - %s' % (get('label1'),
                                         re.sub('\s*-\s*$', '', get('label2')))
            try:
                account.balance = Decimal(Transaction.clean_amount(table.xpath(xpaths['balance'])[-1].text))
                account.currency = account.get_currency(self.document
                        .xpath(xpaths['currency'])[0].replace("Montants en ", ""))
                if not account.currency and currency:
                    account.currency = Account.get_currency(currency)
            except IndexError:
                account.balance = Decimal('0.0')

            if 'link' in xpaths:
                try:
                    account._link = table.xpath(xpaths['link'])[-1]
                except IndexError:
                    account._link = None
                else:
                    account._link = re.sub('[\n\r\t]+', '', account._link)
            else:
                account._link = self.url

            account._perimeter = self.browser.current_perimeter
            yield account
Beispiel #9
0
    def get_list(self):
        account_type = Account.TYPE_UNKNOWN
        accounts = []

        for tr in self.doc.xpath('//div[@class="finance"]/form/table[@class="ecli"]/tr'):
            if tr.attrib.get('class', '') == 'entete':
                account_type = self.ACCOUNT_TYPES.get(tr.find('th').text.strip(), Account.TYPE_UNKNOWN)
                continue

            tds = tr.findall('td')
            a = tds[0].find('a')

            # Skip accounts that can't be accessed
            if a is None:
                continue

            balance = tds[-1].text.strip()

            account = Account()
            account.label = u' '.join([txt.strip() for txt in tds[0].itertext()])
            account.label = re.sub(u'[ \xa0\u2022\r\n\t]+', u' ', account.label).strip()

            # take "N° (FOO123 456)" but "N° (FOO123) MR. BAR"
            account.id = re.search(r'N° (\w+( \d+)*)', account.label).group(1).replace(' ', '')
            account.type = account_type

            for patt, type in self.ACCOUNT_TYPES2.items():
                if patt in account.label.lower():
                    account.type = type
                    break

            if balance:
                account.balance = Decimal(FrenchTransaction.clean_amount(balance))
                account.currency = account.get_currency(balance)

            if 'onclick' in a.attrib:
                m = re.search(r"javascript:submitForm\(([\w_]+),'([^']+)'\);", a.attrib['onclick'])
                if not m:
                    self.logger.warning('Unable to find link for %r' % account.label)
                    account._link = None
                else:
                    account._link = m.group(2)
            else:
                account._link = a.attrib['href'].strip()

            if accounts and accounts[-1].label == account.label and account.type == Account.TYPE_PEA:
                self.logger.warning('%s seems to be a duplicate of %s, skipping', account, accounts[-1])
                continue

            accounts.append(account)
        return accounts
Beispiel #10
0
    def get_list(self):
        accounts = []

        txt = self.get_from_js('_data = new Array(', ');', is_list=True)

        if txt is None:
            raise BrokenPageError('Unable to find accounts list in scripts')

        data = json.loads('[%s]' % txt.replace("'", '"'))

        for line in data:
            a = Account()
            a.id = line[self.COL_ID].replace(' ', '')
            a._acc_nb = a.id.split('_')[0] if len(a.id.split('_')) > 1 else None
            fp = StringIO(unicode(line[self.COL_LABEL]).encode(self.browser.ENCODING))
            a.label = self.parser.tocleanstring(self.parser.parse(fp, self.browser.ENCODING).xpath('//div[@class="libelleCompteTDB"]')[0])
            # This account can be multiple life insurance accounts
            if a.label == 'ASSURANCE VIE-BON CAPI-SCPI-DIVERS *':
                continue

            a.balance = Decimal(FrenchTransaction.clean_amount(line[self.COL_BALANCE]))
            a.currency = a.get_currency(line[self.COL_BALANCE])
            a.type = self.get_account_type(a.label)
            if line[self.COL_HISTORY] == 'true':
                a._inv = False
                a._link = self.get_history_link()
                a._args = {'_eventId':         'clicDetailCompte',
                           '_ipc_eventValue':  '',
                           '_ipc_fireEvent':   '',
                           'deviseAffichee':   'DEVISE',
                           'execution':        self.get_execution(),
                           'idCompteClique':   line[self.COL_ID],
                          }
            else:
                a._inv = True
                a._args = {'_ipc_eventValue':  line[self.COL_ID],
                           '_ipc_fireEvent':   line[self.COL_FIRE_EVENT],
                          }
                a._link = self.document.xpath('//form[@name="changePageForm"]')[0].attrib['action']

            if a.id.find('_CarteVisa') >= 0:
                accounts[-1]._card_ids.append(a._args)
                if not accounts[-1].coming:
                    accounts[-1].coming = Decimal('0.0')
                accounts[-1].coming += a.balance
                continue

            a._card_ids = []
            accounts.append(a)

        return accounts
Beispiel #11
0
    def get_list(self):
        account_type = Account.TYPE_UNKNOWN
        accounts = []

        for tr in self.doc.xpath(
                '//div[@class="finance"]/form/table[@class="ecli"]/tr'):
            if tr.attrib.get('class', '') == 'entete':
                account_type = self.ACCOUNT_TYPES.get(
                    tr.find('th').text.strip(), Account.TYPE_UNKNOWN)
                continue

            tds = tr.findall('td')
            a = tds[0].find('a')

            # Skip accounts that can't be accessed
            if a is None:
                continue

            balance = tds[-1].text.strip()

            account = Account()
            account.label = u' '.join(
                [txt.strip() for txt in tds[0].itertext()])
            account.label = re.sub(u'[ \xa0\u2022\r\n\t]+', u' ',
                                   account.label).strip()
            account.id = Regexp(pattern=u'N° ((.*?) |(.*))').filter(
                account.label).strip()
            account.type = account_type
            if balance:
                account.balance = Decimal(
                    FrenchTransaction.clean_amount(balance))
                account.currency = account.get_currency(balance)

            if 'onclick' in a.attrib:
                m = re.search(r"javascript:submitForm\(([\w_]+),'([^']+)'\);",
                              a.attrib['onclick'])
                if not m:
                    self.logger.warning('Unable to find link for %r' %
                                        account.label)
                    account._link = None
                else:
                    account._link = m.group(2)
            else:
                account._link = a.attrib['href'].strip()

            accounts.append(account)

        return accounts
Beispiel #12
0
    def get_list(self):
        for tr in self.document.xpath('//table[@class="datas"]//tr'):
            if tr.attrib.get('class', '') == 'entete':
                continue

            cols = tr.findall('td')

            a = Account()
            a.label = unicode(cols[self.COL_ID].xpath('.//span[@class="left-underline"]')[0].text.strip())
            a.type = self.get_account_type(a.label)
            balance = self.parser.tocleanstring(cols[self.COL_BALANCE])
            a.balance = Decimal(FrenchTransaction.clean_amount(balance))
            a.currency = a.get_currency(balance)
            a._link, a._args = self.params_from_js(cols[self.COL_ID].find('a').attrib['href'])
            a._acc_nb = cols[self.COL_ID].xpath('.//span[@class="right-underline"]')[0].text.replace(' ', '').strip()
            if a._args:
                a.id = '%s%s%s' % (a._acc_nb, a._args['IndiceCompte'], a._args['Indiceclassement'])
            else:
                a.id = a._acc_nb
            # This account can be multiple life insurance accounts
            if any(a.label.startswith(lab) for lab in ['ASS.VIE-BONS CAPI-SCPI-DIVERS', 'BONS CAPI-SCPI-DIVERS']) or \
               u'Aucun d\\351tail correspondant pour ce compte' in tr.xpath('.//a/@href')[0]:
                continue

            if a.type is Account.TYPE_CARD:
                a.coming = a.balance
                a.balance = Decimal('0.0')

            a._inv = False

            yield a
Beispiel #13
0
    def get_list(self):
        account_type = Account.TYPE_UNKNOWN

        for tr in self.document.xpath('//table[@class="ca-table"]/tr'):
            try:
                title = tr.xpath('.//h3/text()')[0].lower().strip()
            except IndexError:
                pass
            else:
                account_type = self.TYPES.get(title, Account.TYPE_UNKNOWN)

            if not tr.attrib.get('class', '').startswith('colcelligne'):
                continue

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

            account = Account()
            account.id = self.parser.tocleanstring(cols[self.COL_ID])
            account.label = self.parser.tocleanstring(cols[self.COL_LABEL])
            account.type = account_type or 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

            self.set_link(account, cols)

            account._perimeter = self.browser.current_perimeter
            yield account
Beispiel #14
0
    def get_list(self):
        for tr in self.document.xpath('//table[@class="datas"]//tr'):
            if tr.attrib.get('class', '') == 'entete':
                continue

            cols = tr.findall('td')

            a = Account()
            a.label = unicode(cols[self.COL_ID].xpath(
                './/span[@class="left-underline"]')[0].text.strip())
            a.type = self.get_account_type(a.label)
            balance = self.parser.tocleanstring(cols[self.COL_BALANCE])
            a.balance = Decimal(FrenchTransaction.clean_amount(balance))
            a.currency = a.get_currency(balance)
            a._link, a._args = self.params_from_js(
                cols[self.COL_ID].find('a').attrib['href'])
            a._acc_nb = cols[self.COL_ID].xpath(
                './/span[@class="right-underline"]')[0].text.replace(
                    ' ', '').strip()
            if a._args:
                a.id = '%s%s%s' % (a._acc_nb, a._args['IndiceCompte'],
                                   a._args['Indiceclassement'])
            else:
                a.id = a._acc_nb

            a._card_ids = []
            a._inv = False

            yield a
Beispiel #15
0
    def get_list(self):
        for box in self.document.getroot().cssselect(
                'div.roundedBox div.contentBox'):
            a = Account()
            a.id = self.parser.tocleanstring(
                box.xpath(
                    './/tr[@id="summaryImageHeaderRow"]//div[@class="summaryTitles"]'
                )[0])
            a.label = self.parser.tocleanstring(
                box.xpath('.//span[@class="cardTitle"]')[0])
            if "carte" in a.label.lower():
                a.type = Account.TYPE_CARD
            balance = self.parser.tocleanstring(
                self.parser.select(box, 'td#colOSBalance div.summaryValues',
                                   1))
            if balance in (u'Indisponible',
                           u'Indisponible Facturation en cours', ''):
                a.balance = NotAvailable
            else:
                a.currency = a.get_currency(balance)
                a.balance = -abs(
                    CleanDecimal(
                        replace_dots=a.currency == 'EUR').filter(balance))
            a._link = self.parser.select(box,
                                         'div.summaryTitles a.summaryLink',
                                         1).attrib['href']

            yield a
Beispiel #16
0
 def populate(self, accounts):
     cards = []
     for account in accounts:
         for li in  self.doc.xpath('//li[@class="nav-category"]'):
             title = CleanText().filter(li.xpath('./h3'))
             for a in li.xpath('./ul/li//a'):
                 label = CleanText().filter(a.xpath('.//span[@class="nav-category__name"]'))
                 balance_el = a.xpath('.//span[@class="nav-category__value"]')
                 balance = CleanDecimal(replace_dots=True, default=NotAvailable).filter(balance_el)
                 if 'CARTE' in label and balance:
                     acc = Account()
                     acc.balance = balance
                     acc.label = label
                     acc.currency = FrenchTransaction.Currency().filter(balance_el)
                     acc._link = Link().filter(a.xpath('.'))
                     acc._history_page = acc._link
                     acc.id = acc._webid = Regexp(pattern='([^=]+)$').filter(Link().filter(a.xpath('.')))
                     acc.type = Account.TYPE_CARD
                     if not acc in cards:
                         cards.append(acc)
                 elif account.label == label and account.balance == balance:
                     if not account.type:
                         account.type = AccountsPage.ACCOUNT_TYPES.get(title, Account.TYPE_UNKNOWN)
                     if account.type == Account.TYPE_LOAN:
                         account._history_page = None
                     elif account.type in (Account.TYPE_LIFE_INSURANCE, Account.TYPE_MARKET):
                         account._history_page = re.sub('/$', '', Link().filter(a.xpath('.')))
                     elif '/compte/cav' in a.attrib['href'] or not 'titulaire' in self.url:
                         account._history_page = self.browser.other_transactions
                     else:
                         account._history_page = self.browser.budget_transactions
                     account._webid = Attr(None, 'data-account-label').filter(a.xpath('.//span[@class="nav-category__name"]'))
     accounts.extend(cards)
Beispiel #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
Beispiel #18
0
    def get_accounts(self):
        for el in self.doc.getroot().cssselect('div#content tr.row'):
            account = Account()

            balance = el.cssselect('td.Balance')[0].text
            account.balance = Decimal(Transaction.clean_amount(balance))
            account.id = el.cssselect('span')[0].text.strip()
            account.currency = u'NZD'  # TODO: handle other currencies

            if el.cssselect('td.AccountName > a'):
                label_el = el.cssselect('td.AccountName > a')[0]
                account._link = label_el.get('href')
            else:
                label_el = el.cssselect('td.AccountName')[0]
                account._link = None

            account.label = unicode(label_el.text.strip())

            yield account
Beispiel #19
0
    def get_accounts(self):
        for el in self.doc.getroot().cssselect('div#content tr.row'):
            account = Account()

            balance = el.cssselect('td.Balance')[0].text
            account.balance = Decimal(Transaction.clean_amount(balance))
            account.id = el.cssselect('span')[0].text.strip()
            account.currency = u'NZD'  # TODO: handle other currencies

            if el.cssselect('td.AccountName > a'):
                label_el = el.cssselect('td.AccountName > a')[0]
                account._link = label_el.get('href')
            else:
                label_el = el.cssselect('td.AccountName')[0]
                account._link = None

            account.label = unicode(label_el.text.strip())

            yield account
Beispiel #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
Beispiel #21
0
 def get_list(self):
     names = set()
     for li in self.document.xpath('//div[@class="affichMontant"]/ul/li/a'):
         account = Account()
         account.label = unicode(li.cssselect('div.row-lib u')[0].text.strip())
         account.id = re.sub('[ \.\-]+', '', account.label)
         while account.id in names:
             account.id = account.id + '1'
         names.add(account.id)
         account.balance = Decimal(li.cssselect('p.row-right')[0].text.strip().replace(' ', '').replace(u'\xa0', '').replace(',', ''))
         account._link = li.attrib['href']
         yield account
Beispiel #22
0
    def get_list(self):
        for div in self.doc.xpath('.//div[@id="card-details"]'):
            a = Account()
            a.id = CleanText().filter(div.xpath('.//span[@class="acc-num"]'))
            a.label = CleanText().filter(div.xpath('.//span[@class="card-desc"]'))
            if "carte" in a.label.lower():
                a.type = Account.TYPE_CARD
            balance = CleanText().filter(div.xpath('.//span[@class="balance-data"]'))
            if balance in (u'Indisponible', u'Indisponible Facturation en cours', ''):
                a.balance = NotAvailable
            else:
                a.currency = a.get_currency(balance)
                a.balance = - abs(CleanDecimal(replace_dots=a.currency == 'EUR').filter(balance))

            # Cancel card don't have a link to watch history
            link = self.doc.xpath('.//div[@class="wide-bar"]/h3/a')
            if len(link) == 1:
                a._link = link[0].attrib['href']
            else:
                a._link = None

            yield a
Beispiel #23
0
    def get_list(self):
        rib = None
        currency = None
        for script in self.document.xpath('//script'):
            if script.text is None:
                continue

            m = re.search('var rib = "(\d+)"', script.text)
            if m:
                rib = m.group(1)
            m = re.search("var devise='(\w+)'", script.text)
            if m:
                currency = m.group(1)

            if all((rib, currency)):
                break

        if not all((rib, currency)):
            self.logger.error('Unable to find rib or currency')

        for tr in self.document.xpath('//table[@id="tab-corps"]//tr'):
            tds = tr.findall('td')

            if len(tds) != 3:
                continue

            account = Account()
            account.type = Account.TYPE_CARD
            account.label = self.parser.tocleanstring(tds[self.COL_LABEL])
            if len(account.label) == 0:
                continue

            link = tds[self.COL_ID].xpath('.//a')[0]
            m = re.match(r"changeCarte\('(\d+)','(\d+)','([^']+)'\);.*",
                         link.attrib['onclick'])
            if not m:
                self.logger.error('Unable to parse link %r' %
                                  link.attrib['onclick'])
                continue
            account._link_num = m.group(1)  #useless
            account._link = m.group(2)
            account.id = m.group(2) + account._link_num
            account._link_date = urllib.quote(m.group(3))
            account._link_rib = rib
            account._link_currency = currency
            account._is_card = True
            tdbalance = self.parser.tocleanstring(tds[self.COL_BALANCE])
            account.balance = -Decimal(Transaction.clean_amount(tdbalance))
            account.currency = account.get_currency(tdbalance)
            yield account
Beispiel #24
0
    def get_list(self):
        for box in self.document.getroot().cssselect('div.roundedBox div.contentBox'):
            a = Account()
            a.id = self.parser.tocleanstring(box.xpath('.//tr[@id="summaryImageHeaderRow"]//div[@class="summaryTitles"]')[0])
            a.label = self.parser.tocleanstring(box.xpath('.//span[@class="cardTitle"]')[0])
            balance = self.parser.tocleanstring(self.parser.select(box, 'td#colOSBalance div.summaryValues', 1))
            if balance in (u'Indisponible', u'Indisponible Facturation en cours', ''):
                a.balance = NotAvailable
            else:
                a.balance = - abs(Decimal(Transaction.clean_amount(balance)))
                a.currency = a.get_currency(balance)
            a._link = self.parser.select(box, 'div.summaryTitles a.summaryLink', 1).attrib['href']

            yield a
Beispiel #25
0
    def get_list(self):
        for div in self.document.xpath('.//div[@id="card-details"]'):
            a = Account()
            a.id = self.parser.tocleanstring(div.xpath('.//span[@class="acc-num"]')[0])
            a.label = self.parser.tocleanstring(div.xpath('.//span[@class="card-desc"]')[0])
            balance = self.parser.tocleanstring(div.xpath('.//span[@class="balance-data"]')[0])
            if balance in (u"Indisponible", u"Indisponible Facturation en cours", ""):
                a.balance = NotAvailable
            else:
                a.balance = -abs(Decimal(Transaction.clean_amount(balance)))
                a.currency = a.get_currency(balance)
            a._link = self.document.xpath('.//div[@class="wide-bar"]/h3/a')[0].attrib["href"]

            yield a
Beispiel #26
0
    def get_list(self):
        account_type = Account.TYPE_UNKNOWN
        accounts = []

        for tr in self.document.xpath('//table[@class="ecli"]/tr'):
            if tr.attrib.get('class', '') == 'entete':
                account_type = self.ACCOUNT_TYPES.get(
                    tr.find('th').text.strip(), Account.TYPE_UNKNOWN)
                continue

            tds = tr.findall('td')

            balance = tds[-1].text.strip()
            if balance == '':
                continue

            account = Account()
            account.label = u' '.join(
                [txt.strip() for txt in tds[0].itertext()])
            account.label = re.sub(u'[ \xa0\u2022\r\n\t]+', u' ',
                                   account.label).strip()
            account.id = re.findall('(\d+)', account.label)[0]
            account.balance = Decimal(FrenchTransaction.clean_amount(balance))
            account.currency = account.get_currency(balance)
            account.type = account_type
            m = re.search(r"javascript:submitForm\(([\w_]+),'([^']+)'\);",
                          tds[0].find('a').attrib['onclick'])
            if not m:
                self.logger.warning('Unable to find link for %r' %
                                    account.label)
                account._link = None
            else:
                account._link = m.group(2)

            accounts.append(account)

        return accounts
Beispiel #27
0
    def get_av_accounts(self):
        for tr in self.document.xpath('//table[@class="datas"]/tr[not(@class)]'):
            cols = tr.findall('td')
            if len(cols) != 4:
                continue

            a = Account()
            a.label = self.parser.tocleanstring(cols[self.COL_LABEL])
            a.type = Account.TYPE_LIFE_INSURANCE
            a.balance = Decimal(FrenchTransaction.clean_amount(self.parser.tocleanstring(cols[self.COL_BALANCE])))
            a._link, a._args = self.get_params(cols[self.COL_LABEL].find('span/a').attrib['href'])
            a.id = '%s%s' % (a._args['IndiceSupport'], a._args['NumPolice'])
            a._acc_nb = None
            a._inv = True
            yield a
Beispiel #28
0
    def get_av_accounts(self):
        for tr in self.doc.xpath('//table[@class="datas"]/tr[not(@class)]'):
            cols = tr.findall('td')
            if len(cols) != 4:
                continue

            a = Account()
            a.label = CleanText('.')(cols[self.COL_LABEL])
            a.type = Account.TYPE_LIFE_INSURANCE
            a.balance = MyDecimal('.')(cols[self.COL_BALANCE])
            a._link, a._args = self.get_params(cols[self.COL_LABEL].find('span/a').attrib['href'])
            a.id = a._args['IndiceSupport'] + a._args['NumPolice']
            a._acc_nb = None
            a._inv = True
            yield a
Beispiel #29
0
    def get_list(self):

        no_accounts_message = self.doc.xpath(
            u'//span/b[contains(text(),"Votre abonnement est clôturé. Veuillez contacter votre conseiller.")]/text()'
        )
        if no_accounts_message:
            raise ActionNeeded(no_accounts_message[0])

        for tr in self.doc.xpath('//table[has-class("datas")]//tr'):
            if tr.attrib.get('class', '') == 'entete':
                continue

            cols = tr.findall('td')

            a = Account()
            a.label = unicode(cols[self.COL_ID].xpath(
                './/span[@class="left-underline"] | .//span[@class="left"]/a')
                              [0].text.strip())
            a.type = self.get_account_type(a.label)
            balance = CleanText('.')(cols[self.COL_BALANCE])
            if balance == '':
                continue
            a.balance = CleanDecimal(replace_dots=True).filter(balance)
            a.currency = a.get_currency(balance)
            if cols[self.COL_ID].find('a'):
                a._link, a._args = self.params_from_js(
                    cols[self.COL_ID].find('a').attrib['href'])
            a._acc_nb = cols[self.COL_ID].xpath(
                './/span[@class="right-underline"] | .//span[@class="right"]'
            )[0].text.replace(' ', '').strip()

            if hasattr(a, '_args') and a._args:
                a.id = '%s%s%s' % (a._acc_nb, a._args['IndiceCompte'],
                                   a._args['Indiceclassement'])
            else:
                a.id = a._acc_nb
            # This account can be multiple life insurance accounts
            if any(a.label.startswith(lab) for lab in ['ASS.VIE-BONS CAPI-SCPI-DIVERS', 'BONS CAPI-SCPI-DIVERS']) or \
               u'Aucun d\\351tail correspondant pour ce compte' in tr.xpath('.//a/@href')[0]:
                continue

            if a.type is Account.TYPE_CARD:
                a.coming = a.balance
                a.balance = Decimal('0.0')

            a._inv = False

            yield a
Beispiel #30
0
    def get_list(self):
        rib = None
        currency = None
        for script in self.document.xpath('//script'):
            if script.text is None:
                continue

            m = re.search('var rib = "(\d+)"', script.text)
            if m:
                rib = m.group(1)
            m = re.search("var devise='(\w+)'", script.text)
            if m:
                currency = m.group(1)

            if all((rib, currency)):
                break

        if not all((rib, currency)):
            self.logger.error('Unable to find rib or currency')

        for tr in self.document.xpath('//table[@id="tab-corps"]//tr'):
            tds = tr.findall('td')

            if len(tds) != 3:
                continue

            account = Account()
            account.type = Account.TYPE_CARD
            account.label = self.parser.tocleanstring(tds[self.COL_LABEL])
            if len(account.label) == 0:
                continue

            link = tds[self.COL_ID].xpath('.//a')[0]
            m = re.match(r"changeCarte\('(\d+)','(\d+)','([^']+)'\);.*", link.attrib['onclick'])
            if not m:
                self.logger.error('Unable to parse link %r' % link.attrib['onclick'])
                continue
            account._link_num = m.group(1) #useless
            account._link = m.group(2)
            account.id = m.group(2) + account._link_num
            account._link_date = urllib.quote(m.group(3))
            account._link_rib = rib
            account._link_currency = currency
            account._is_card = True
            tdbalance = self.parser.tocleanstring(tds[self.COL_BALANCE])
            account.balance = - Decimal(Transaction.clean_amount(tdbalance))
            account.currency = account.get_currency(tdbalance)
            yield account
Beispiel #31
0
 def populate(self, accounts):
     cards = []
     for account in accounts:
         for li in self.doc.xpath('//li[@class="nav-category"]'):
             title = CleanText().filter(li.xpath('./h3'))
             for a in li.xpath('./ul/li//a'):
                 label = CleanText().filter(
                     a.xpath('.//span[@class="nav-category__name"]'))
                 balance_el = a.xpath(
                     './/span[@class="nav-category__value"]')
                 balance = CleanDecimal(
                     replace_dots=True,
                     default=NotAvailable).filter(balance_el)
                 if 'CARTE' in label and balance:
                     acc = Account()
                     acc.balance = balance
                     acc.label = label
                     acc.currency = FrenchTransaction.Currency().filter(
                         balance_el)
                     acc._link = Link().filter(a.xpath('.'))
                     acc._history_page = acc._link
                     acc.id = acc._webid = Regexp(
                         pattern='([^=]+)$').filter(Link().filter(
                             a.xpath('.')))
                     acc.type = Account.TYPE_CARD
                     if not acc in cards:
                         cards.append(acc)
                 elif account.label == label and account.balance == balance:
                     if not account.type:
                         account.type = AccountsPage.ACCOUNT_TYPES.get(
                             title, Account.TYPE_UNKNOWN)
                     if account.type == Account.TYPE_LOAN:
                         account._history_page = None
                     elif account.type in (Account.TYPE_LIFE_INSURANCE,
                                           Account.TYPE_MARKET):
                         account._history_page = re.sub(
                             '/$', '',
                             Link().filter(a.xpath('.')))
                     elif '/compte/cav' in a.attrib[
                             'href'] or not 'titulaire' in self.url:
                         account._history_page = self.browser.other_transactions
                     else:
                         account._history_page = self.browser.budget_transactions
                     account._webid = Attr(
                         None, 'data-account-label').filter(
                             a.xpath(
                                 './/span[@class="nav-category__name"]'))
     accounts.extend(cards)
Beispiel #32
0
    def get_av_accounts(self):
        for tr in self.document.xpath('//table[@class="datas"]/tr[not(@class)]'):
            cols = tr.findall('td')
            if len(cols) != 4:
                continue

            a = Account()
            a.label = self.parser.tocleanstring(cols[self.COL_LABEL])
            a.type = Account.TYPE_LIFE_INSURANCE
            a.balance = Decimal(FrenchTransaction.clean_amount(self.parser.tocleanstring(cols[self.COL_BALANCE])))
            a._link, a._args = self.get_params(cols[self.COL_LABEL].find('span/a').attrib['href'])
            a.id = '%s%s' % (a._args['IndiceSupport'], a._args['NumPolice'])
            a._acc_nb = None
            a._card_ids = []
            a._inv = True
            yield a
Beispiel #33
0
    def get_list(self):
        accounts = []

        txt = self.get_from_js('_data = new Array(', ');', is_list=True)

        if txt is None:
            raise BrokenPageError('Unable to find accounts list in scripts')

        data = json.loads('[%s]' % txt.replace("'", '"'))

        for line in data:
            a = Account()
            a.id = line[self.COL_ID].replace(' ', '')
            fp = StringIO(
                unicode(line[self.COL_LABEL]).encode(self.browser.ENCODING))
            a.label = self.parser.tocleanstring(
                self.parser.parse(fp, self.browser.ENCODING).xpath(
                    '//div[@class="libelleCompteTDB"]')[0])
            a.balance = Decimal(
                FrenchTransaction.clean_amount(line[self.COL_BALANCE]))
            a.currency = a.get_currency(line[self.COL_BALANCE])
            a.type = self.get_account_type(a.label)
            a._link = self.get_history_link()
            if line[self.COL_HISTORY] == 'true':
                a._args = {
                    '_eventId': 'clicDetailCompte',
                    '_ipc_eventValue': '',
                    '_ipc_fireEvent': '',
                    'deviseAffichee': 'DEVISE',
                    'execution': self.get_execution(),
                    'idCompteClique': line[self.COL_ID],
                }
            else:
                a._args = None

            if a.id.find('_CarteVisa') >= 0:
                accounts[-1]._card_ids.append(a._args)
                if not accounts[-1].coming:
                    accounts[-1].coming = Decimal('0.0')
                accounts[-1].coming += a.balance
                continue

            a._card_ids = []
            accounts.append(a)

        return iter(accounts)
Beispiel #34
0
    def get_list(self):
        for box in self.document.getroot().cssselect("div.roundedBox div.contentBox"):
            a = Account()
            a.id = self.parser.tocleanstring(
                box.xpath('.//tr[@id="summaryImageHeaderRow"]//div[@class="summaryTitles"]')[0]
            )
            a.label = self.parser.tocleanstring(box.xpath('.//span[@class="cardTitle"]')[0])
            a.balance = Decimal("0.0")
            coming = self.parser.tocleanstring(self.parser.select(box, "td#colOSBalance div.summaryValues", 1))
            if coming in (u"Indisponible", ""):
                a.coming = NotAvailable
            else:
                a.coming = -abs(Decimal(Transaction.clean_amount(coming)))
                a.currency = a.get_currency(coming)
            a._link = self.parser.select(box, "div.summaryTitles a.summaryLink", 1).attrib["href"]

            yield a
Beispiel #35
0
    def get_av_accounts(self):
        for table in self.doc.xpath('//table[@class="datas"]'):
            head_cols = table.xpath('./tr[@class="entete"]/td')
            for tr in table.xpath('./tr[not(@class)]'):
                cols = tr.findall('td')
                if len(cols) != 4:
                    continue

                a = Account()
                a.label = CleanText('.')(cols[self.COL_LABEL])
                a.type = Account.TYPE_LIFE_INSURANCE
                a.balance = MyDecimal('.')(cols[self.COL_BALANCE])
                a.currency = a.get_currency(CleanText('.')(head_cols[self.COL_BALANCE]))
                a._link, a._args = self.get_params(cols[self.COL_LABEL].find('span/a').attrib['href'])
                a.id = a._args['IndiceSupport'] + a._args['NumPolice']
                a._acc_nb = None
                a._inv = True
                yield a
Beispiel #36
0
    def get_list(self):
        for tr in self.document.xpath('//table[@class="datas"]//tr'):
            if tr.attrib.get('class', '') == 'entete':
                continue

            cols = tr.findall('td')

            a = Account()
            a.id = cols[self.COL_ID].xpath('.//span[@class="right-underline"]')[0].text.strip()
            a.label = unicode(cols[self.COL_ID].xpath('.//span[@class="left-underline"]')[0].text.strip())
            balance = self.parser.tocleanstring(cols[self.COL_BALANCE])
            a.balance = Decimal(FrenchTransaction.clean_amount(balance))
            a.currency = a.get_currency(balance)
            a._link, a._args = self.params_from_js(cols[self.COL_ID].find('a').attrib['href'])

            a._card_ids = []

            yield a
Beispiel #37
0
    def get_list(self):
        for tr in self.document.xpath('//table[@class="datas"]//tr'):
            if tr.attrib.get('class', '') == 'entete':
                continue

            cols = tr.findall('td')

            a = Account()
            a.id = cols[self.COL_ID].xpath('.//span[@class="right-underline"]')[0].text.strip()
            a.label = unicode(cols[self.COL_ID].xpath('.//span[@class="left-underline"]')[0].text.strip())
            balance = self.parser.tocleanstring(cols[self.COL_BALANCE])
            a.balance = Decimal(FrenchTransaction.clean_amount(balance))
            a.currency = a.get_currency(balance)
            a._link, a._args = self.params_from_js(cols[self.COL_ID].find('a').attrib['href'])

            a._card_ids = []

            yield a
Beispiel #38
0
    def get_list(self):
        for div in self.document.xpath('.//div[@id="card-details"]'):
            a = Account()
            a.id = self.parser.tocleanstring(
                div.xpath('.//span[@class="acc-num"]')[0])
            a.label = self.parser.tocleanstring(
                div.xpath('.//span[@class="card-desc"]')[0])
            balance = self.parser.tocleanstring(
                div.xpath('.//span[@class="balance-data"]')[0])
            if balance in (u'Indisponible',
                           u'Indisponible Facturation en cours', ''):
                a.balance = NotAvailable
            else:
                a.balance = -abs(Decimal(Transaction.clean_amount(balance)))
                a.currency = a.get_currency(balance)
            a._link = self.document.xpath(
                './/div[@class="wide-bar"]/h3/a')[0].attrib['href']

            yield a
Beispiel #39
0
    def get_list(self):
        accounts = []

        txt = self.get_from_js('_data = new Array(', ');', is_list=True)

        if txt is None:
            raise BrokenPageError('Unable to find accounts list in scripts')

        data = json.loads('[%s]' % txt.replace("'", '"'))

        for line in data:
            a = Account()
            a.id = line[self.COL_ID].replace(' ', '')
            fp = StringIO(unicode(line[self.COL_LABEL]).encode(self.browser.ENCODING))
            a.label = self.parser.tocleanstring(self.parser.parse(fp, self.browser.ENCODING).xpath('//div[@class="libelleCompteTDB"]')[0])
            a.balance = Decimal(FrenchTransaction.clean_amount(line[self.COL_BALANCE]))
            a.currency = a.get_currency(line[self.COL_BALANCE])
            a.type = self.get_account_type(a.label)
            a._link = self.get_history_link()
            if line[self.COL_HISTORY] == 'true':
                a._args = {'_eventId':         'clicDetailCompte',
                           '_ipc_eventValue':  '',
                           '_ipc_fireEvent':   '',
                           'deviseAffichee':   'DEVISE',
                           'execution':        self.get_execution(),
                           'idCompteClique':   line[self.COL_ID],
                          }
            else:
                a._args = None

            if a.id.find('_CarteVisa') >= 0:
                accounts[-1]._card_ids.append(a._args)
                if not accounts[-1].coming:
                    accounts[-1].coming = Decimal('0.0')
                accounts[-1].coming += a.balance
                continue

            a._card_ids = []
            accounts.append(a)

        return iter(accounts)
Beispiel #40
0
    def get_list(self):
        for box in self.document.getroot().cssselect(
                'div.roundedBox div.contentBox'):
            a = Account()
            a.id = self.parser.tocleanstring(
                box.xpath(
                    './/tr[@id="summaryImageHeaderRow"]//div[@class="summaryTitles"]'
                )[0])
            a.label = self.parser.tocleanstring(
                box.xpath('.//span[@class="cardTitle"]')[0])
            balance = self.parser.tocleanstring(
                self.parser.select(box, 'td#colOSBalance div.summaryValues',
                                   1))
            if balance in (u'Indisponible', ''):
                a.balance = NotAvailable
            else:
                a.balance = -abs(Decimal(Transaction.clean_amount(balance)))
                a.currency = a.get_currency(balance)
            a._link = self.parser.select(box,
                                         'div.summaryTitles a.summaryLink',
                                         1).attrib['href']

            yield a
Beispiel #41
0
    def get_list(self):
        account_type = Account.TYPE_UNKNOWN

        for tr in self.document.xpath('//table[@class="ca-table"]/tr'):
            try:
                title = tr.xpath('.//h3/text()')[0].lower().strip()
            except IndexError:
                pass
            else:
                account_type = self.TYPES.get(title, Account.TYPE_UNKNOWN)

            if not tr.attrib.get('class', '').startswith('colcelligne'):
                continue

            cols = tr.findall('td')
            if not cols or len(cols) < self.NB_COLS:
                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) or account_type
            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

            self.set_link(account, cols)

            account._perimeter = self.browser.current_perimeter
            yield account
Beispiel #42
0
    def get_list(self):
        for tr in self.document.xpath('//table[@class="datas"]//tr'):
            if tr.attrib.get('class', '') == 'entete':
                continue

            cols = tr.findall('td')

            a = Account()
            a.label = unicode(cols[self.COL_ID].xpath('.//span[@class="left-underline"]')[0].text.strip())
            a.type = self.get_account_type(a.label)
            balance = self.parser.tocleanstring(cols[self.COL_BALANCE])
            a.balance = Decimal(FrenchTransaction.clean_amount(balance))
            a.currency = a.get_currency(balance)
            a._link, a._args = self.params_from_js(cols[self.COL_ID].find('a').attrib['href'])
            a._acc_nb = cols[self.COL_ID].xpath('.//span[@class="right-underline"]')[0].text.replace(' ', '').strip()
            if a._args:
                a.id = '%s%s%s' % (a._acc_nb, a._args['IndiceCompte'], a._args['Indiceclassement'])
            else:
                a.id = a._acc_nb

            a._card_ids = []
            a._inv = False

            yield a
Beispiel #43
0
 def populate(self, accounts):
     cards = []
     for account in accounts:
         for li in self.doc.xpath('//li[@class="nav-category"]'):
             title = CleanText().filter(li.xpath('./h3'))
             for a in li.xpath('./ul/li//a'):
                 label = CleanText().filter(
                     a.xpath('.//span[@class="nav-category__name"]'))
                 balance_el = a.xpath(
                     './/span[@class="nav-category__value"]')
                 balance = CleanDecimal(
                     replace_dots=True,
                     default=NotAvailable).filter(balance_el)
                 if 'CARTE' in label and balance:
                     acc = Account()
                     acc.balance = balance
                     acc.label = label
                     acc.currency = FrenchTransaction.Currency().filter(
                         balance_el)
                     acc._link = Link().filter(a.xpath('.'))
                     acc._history_page = acc._link
                     acc.id = acc._webid = Regexp(
                         pattern='carte/(.*)$').filter(Link().filter(
                             a.xpath('.')))
                     acc.type = Account.TYPE_CARD
                     if not acc in cards:
                         cards.append(acc)
                 elif account.label == label and account.balance == balance:
                     if not account.type:
                         account.type = AccountsPage.ACCOUNT_TYPES.get(
                             title, Account.TYPE_UNKNOWN)
                     account._webid = Attr(
                         None, 'data-account-label').filter(
                             a.xpath(
                                 './/span[@class="nav-category__name"]'))
     accounts.extend(cards)
Beispiel #44
0
    def get_av_accounts(self):
        for table in self.doc.xpath('//table[@class="datas"]'):
            head_cols = table.xpath('./tr[@class="entete"]/td')
            for tr in table.xpath('./tr[not(@class)]'):
                cols = tr.findall('td')
                if len(cols) != 4:
                    continue

                a = Account()

                # get acc_nb like on accounts page
                a._acc_nb = Regexp(
                    CleanText('//div[@id="v1-cadre"]//b[contains(text(), "Compte N")]', replace=[(' ', '')]),
                    r'(\d+)'
                )(self.doc)[5:]

                a.label = CleanText('.')(cols[self.COL_LABEL])
                a.type = Account.TYPE_LIFE_INSURANCE
                a.balance = MyDecimal('.')(cols[self.COL_BALANCE])
                a.currency = a.get_currency(CleanText('.')(head_cols[self.COL_BALANCE]))
                a._link, a._args = self.get_params(cols[self.COL_LABEL].find('span/a').attrib['href'])
                a.id = '%s%s%s' % (a._acc_nb, a._args['IndiceSupport'], a._args['NumPolice'])
                a._inv = True
                yield a
Beispiel #45
0
    def get_av_accounts(self):
        for table in self.doc.xpath('//table[@class="datas"]'):
            head_cols = table.xpath('./tr[@class="entete"]/td')
            for tr in table.xpath('./tr[not(@class)]'):
                cols = tr.findall('td')
                if len(cols) != 4:
                    continue

                a = Account()

                # get acc_nb like on accounts page
                a._acc_nb = Regexp(
                    CleanText('//div[@id="v1-cadre"]//b[contains(text(), "Compte N")]', replace=[(' ', '')]),
                    r'(\d+)'
                )(self.doc)[5:]

                a.label = CleanText('.')(cols[self.COL_LABEL])
                a.type = Account.TYPE_LIFE_INSURANCE
                a.balance = MyDecimal('.')(cols[self.COL_BALANCE])
                a.currency = a.get_currency(CleanText('.')(head_cols[self.COL_BALANCE]))
                a._link, a._args = self.get_params(cols[self.COL_LABEL].find('span/a').attrib['href'])
                a.id = '%s%s%s' % (a._acc_nb, a._args['IndiceSupport'], a._args['NumPolice'])
                a._inv = True
                yield a
Beispiel #46
0
    def get_list(self):
        no_accounts_message = self.doc.xpath(u'//span/b[contains(text(),"Votre abonnement est clôturé. Veuillez contacter votre conseiller.")]/text()')
        if no_accounts_message:
            raise ActionNeeded(no_accounts_message[0])

        previous_checking_account = None
        # Several deposit accounts ('Compte à terme') have the same id and the same label
        # So a number is added to distinguish them
        previous_deposit_account = None
        deposit_count = 1
        for tr in self.doc.xpath('//table[has-class("datas")]//tr'):
            if tr.attrib.get('class', '') == 'entete':
                continue

            cols = tr.findall('td')

            a = Account()
            a.label = unicode(cols[self.COL_ID].xpath('.//span[@class="left-underline"] | .//span[@class="left"]/a')[0].text.strip())
            a.type = self.get_account_type(a.label)
            balance = CleanText('.')(cols[self.COL_BALANCE])
            if balance == '':
                continue
            a.balance = CleanDecimal(replace_dots=True).filter(balance)
            a.currency = a.get_currency(balance)
            if cols[self.COL_ID].find('a'):
                a._link, a._args = self.params_from_js(cols[self.COL_ID].find('a').attrib['href'])
            # There may be a href with 'javascript:NoDetail();'
            # The _link and _args should be None
            else:
                a._link, a._args = None, None
            a._acc_nb = cols[self.COL_ID].xpath('.//span[@class="right-underline"] | .//span[@class="right"]')[0].text.replace(' ', '').strip()

            a.id = a._acc_nb
            if hasattr(a, '_args') and a._args:
                if a._args['IndiceCompte'].isdigit():
                    a.id = '%s%s' % (a.id, a._args['IndiceCompte'])
                if a._args['Indiceclassement'].isdigit():
                    a.id = '%s%s' % (a.id, a._args['Indiceclassement'])

            # This account can be multiple life insurance accounts
            if (any(a.label.startswith(lab) for lab in ['ASS.VIE-BONS CAPI-SCPI-DIVERS', 'BONS CAPI-SCPI-DIVERS'])
                or (u'Aucun d\\351tail correspondant pour ce compte' in tr.xpath('.//a/@href')[0])
                    and 'COMPTE A TERME' not in tr.xpath('.//span[contains(@class, "left")]/text()')[0]):
                continue

            if a.type is Account.TYPE_CARD:
                a.coming = a.balance
                a.balance = Decimal('0.0')

                # Take the predecessiong checking account as parent
                if previous_checking_account:
                    a.parent = previous_checking_account
                else:
                    self.logger.warning('The card account %s has no parent account' % a.id)

            a._inv = True

            if a.type == Account.TYPE_CHECKING:
                previous_checking_account = a

            if previous_deposit_account and previous_deposit_account.id == a.id:
                a.id = a.id + '_%s' % deposit_count
                deposit_count += 1
                previous_deposit_account = a

            if a.type == Account.TYPE_DEPOSIT:
                previous_deposit_account = a

            yield a
Beispiel #47
0
    def get_list(self):
        TABLE_XPATH = '//table[caption[@class="caption tdb-cartes-caption" or @class="ca-table caption"]]'

        cards_tables = self.document.xpath(TABLE_XPATH)

        if cards_tables:
            self.logger.debug('There are several cards')
            xpaths = {
                '_id': './caption/span[@class="tdb-cartes-num"]',
                'label1':
                './caption/span[contains(@class, "tdb-cartes-carte")]',
                'label2': './caption/span[@class="tdb-cartes-prop"]',
                'balance': './/tr/td[@class="cel-num"]',
                'currency':
                '//table/caption//span/text()[starts-with(.,"Montants en ")]',
                'link': './/tr//a/@href[contains(., "fwkaction=Detail")]',
            }
        else:
            self.logger.debug('There is only one card')
            xpaths = {
                '_id':
                './/tr/td[@class="cel-texte"]',
                'label1':
                './/tr[@class="ligne-impaire ligne-bleu"]/th',
                'label2':
                './caption/span[@class="tdb-cartes-prop"]/b',
                'balance':
                './/tr[last()-1]/td[@class="cel-num"]',
                'currency':
                '//table/caption//span/text()[starts-with(.,"Montants en ")]',
            }
            TABLE_XPATH = '(//table[@class="ca-table"])[1]'
            cards_tables = self.document.xpath(TABLE_XPATH)

        for table in cards_tables:
            get = lambda name: self.parser.tocleanstring(
                table.xpath(xpaths[name])[0])

            account = Account()
            account.type = account.TYPE_CARD
            account.id = ''.join(get('_id').split()[1:])
            account.label = '%s - %s' % (get('label1'),
                                         re.sub('\s*-\s*$', '', get('label2')))
            try:
                account.balance = Decimal(
                    Transaction.clean_amount(
                        table.xpath(xpaths['balance'])[-1].text))
                account.currency = account.get_currency(
                    self.document.xpath(xpaths['currency'])[0].replace(
                        "Montants en ", ""))
            except IndexError:
                account.balance = Decimal('0.0')

            if 'link' in xpaths:
                try:
                    account._link = table.xpath(xpaths['link'])[-1]
                except IndexError:
                    account._link = None
                else:
                    account._link = re.sub('[\n\r\t]+', '', account._link)
            else:
                account._link = self.url

            yield account
Beispiel #48
0
    def get_list(self):
        account_type = Account.TYPE_UNKNOWN
        accounts = []

        for tr in self.doc.xpath(
                '//div[@class="finance"]/form/table[@class="ecli"]/tr'):
            if tr.attrib.get('class', '') == 'entete':
                account_type = self.ACCOUNT_TYPES.get(
                    tr.find('th').text.strip(), Account.TYPE_UNKNOWN)
                continue

            tds = tr.findall('td')
            a = tds[0].find('a')

            # Skip accounts that can't be accessed
            if a is None:
                continue

            balance = tds[-1].text.strip()

            account = Account()
            account.label = ' '.join(
                [txt.strip() for txt in tds[0].itertext()])
            account.label = re.sub(r'[\s\xa0\u2022]+', ' ',
                                   account.label).strip()

            # take "N° (FOO123 456)" but "N° (FOO123) MR. BAR"
            account.id = re.search(r'N° (\w+( \d+)*)',
                                   account.label).group(1).replace(' ', '')
            account.type = account_type

            for patt, type in self.ACCOUNT_TYPES2.items():
                if patt in account.label.lower():
                    account.type = type
                    break

            if balance:
                account.balance = Decimal(
                    FrenchTransaction.clean_amount(balance))
                account.currency = account.get_currency(balance)

            if 'onclick' in a.attrib:
                m = re.search(r"javascript:submitForm\(([\w]+),'([^']+)'\);",
                              a.attrib['onclick'])
                if not m:
                    self.logger.warning('Unable to find link for %r',
                                        account.label)
                    account._link = None
                else:
                    account._link = m.group(2)
            else:
                account._link = a.attrib['href'].strip()

            if accounts and accounts[
                    -1].label == account.label and account.type == Account.TYPE_PEA:
                self.logger.warning(
                    '%s seems to be a duplicate of %s, skipping', account,
                    accounts[-1])
                continue
            accounts.append(account)
        return accounts
Beispiel #49
0
    def get_list(self):
        accounts = []

        for block in self.document.xpath('//div[@class="pave"]/div'):
            head_type = block.xpath('./div/span[@class="accGroupLabel"]')[0].text.strip()
            account_type = self.ACCOUNT_TYPES.get(head_type, Account.TYPE_UNKNOWN)
            for tr in block.cssselect('ul li.tbord_account'):
                id = tr.attrib.get('id', '')
                if id.find('contratId') != 0:
                    self.logger.warning('Unable to parse contract ID: %r' % id)
                    continue
                id = id[id.find('contratId')+len('contratId'):]

                link = tr.cssselect('span.accountLabel a')[0]
                balance = Decimal(FrenchTransaction.clean_amount(tr.cssselect('span.accountTotal')[0].text))

                if id.endswith('CRT'):
                    account = accounts[-1]
                    account._card_links.append(link.attrib['href'])
                    if not account.coming:
                        account.coming = Decimal('0.0')
                    account.coming += balance
                    continue

                account = Account()
                account.id = id
                account.label = unicode(link.text.strip())
                account.type = account_type
                account.balance = balance
                account.currency = account.get_currency(tr.cssselect('span.accountDev')[0].text)
                account._link = link.attrib['href']
                account._card_links = []
                accounts.append(account)

        if len(accounts) == 0:
            # Sometimes, accounts are only in javascript...
            for script in self.document.xpath('//script'):
                text = script.text
                if text is None:
                    continue
                if 'remotePerso' not in text:
                    continue

                account = None
                card_account = None
                attribs = {}
                account_type = Account.TYPE_UNKNOWN
                for line in text.split('\n'):
                    line = line.strip()
                    m = re.match("data.libelle = '(.*)';", line)
                    if m:
                        account_type = self.ACCOUNT_TYPES.get(m.group(1), Account.TYPE_UNKNOWN)
                    elif line == 'var remotePerso = new Object;':
                        account = Account()
                    elif account is not None:
                        m = re.match("remotePerso.(\w+) = '?(.*?)'?;", line)
                        if m:
                            attribs[m.group(1)] = m.group(2)
                        elif line.startswith('listProduitsGroup'):
                            account.id = attribs['refContrat']

                            account.label = attribs['libelle']
                            account.type = account_type
                            account.balance = Decimal(FrenchTransaction.clean_amount(attribs['soldeDateOpeValeurFormatted']))
                            account.currency = account.get_currency(attribs['codeDevise'])
                            account._link = 'tbord.do?id=%s&%s' % (attribs['id'], self.browser.SESSION_PARAM)
                            account._card_links = []

                            if account.id.endswith('CRT'):
                                if not len(accounts):
                                    card_account = account
                                else:
                                    a = accounts[-1]
                                    a._card_links.append(account._link)
                                    if not a.coming:
                                        a.coming = Decimal('0.0')
                                    a.coming += account.balance
                            else:
                                if 'COURANT' in account.label:
                                    account.type = account.TYPE_CHECKING
                                elif account.id.endswith('TTR'):
                                    account.type = account.TYPE_MARKET
                                elif re.match('^\d+C$', account.id):
                                    account.type = account.TYPE_LIFE_INSURANCE
                                elif re.match('^\d+PRT$', account.id):
                                    account.type = account.TYPE_LOAN
                                elif not account.type:
                                    account.type = account.TYPE_SAVINGS

                                if card_account:
                                    account._card_links.append(card_account._link)
                                    if not account.coming:
                                        account.coming = Decimal('0.0')
                                    account.coming += card_account.balance
                                    card_account = None
                                accounts.append(account)
                            account = None

        return accounts
Beispiel #50
0
    def get_list(self):
        no_accounts_message = self.doc.xpath(u'//span/b[contains(text(),"Votre abonnement est clôturé. Veuillez contacter votre conseiller.")]/text()')
        if no_accounts_message:
            raise ActionNeeded(no_accounts_message[0])

        previous_checking_account = None
        # Several deposit accounts ('Compte à terme') have the same id and the same label
        # So a number is added to distinguish them
        previous_deposit_account = None
        deposit_count = 1
        for tr in self.doc.xpath('//table[has-class("datas")]//tr'):
            if tr.attrib.get('class', '') == 'entete':
                owner = CleanText('.')(tr.findall('td')[0])
                continue

            cols = tr.findall('td')

            a = Account()
            a.label = unicode(cols[self.COL_ID].xpath('.//span[@class="left-underline"] | .//span[@class="left"]/a')[0].text.strip())
            a.type = self.get_account_type(a.label)
            a.ownership = self.get_account_ownership(owner)
            balance = CleanText('.')(cols[self.COL_BALANCE])
            if balance == '':
                continue
            a.balance = CleanDecimal(replace_dots=True).filter(balance)
            a.currency = a.get_currency(balance)
            if cols[self.COL_ID].find('a'):
                a._link, a._args = self.params_from_js(cols[self.COL_ID].find('a').attrib['href'])
            # There may be a href with 'javascript:NoDetail();'
            # The _link and _args should be None
            else:
                a._link, a._args = None, None
            a._acc_nb = cols[self.COL_ID].xpath('.//span[@class="right-underline"] | .//span[@class="right"]')[0].text.replace(' ', '').strip()

            a.id = a._acc_nb

            # If available we add 'IndiceCompte' and 'IndiceClassement' to the id due to the lack of information
            # on the website. This method is not enough because on some connections, if there are multiple account with the
            # same id and the same label, but with different currencies, we will add an index at the end of the id relative to the
            # order the accounts appear on the website. This will cause the accounts to be shifted when the user will add a new account
            # with same label/id, if this happens the new account will appear first on the website and it will take the index of '1'
            # previously used by the first account. the already gathered transactions of the previously first account will appear on
            # the new first account, the already gathered transactions of the previously second account will appear on the new
            # second account (the previous one), etc.

            if hasattr(a, '_args') and a._args:
                if a._args['IndiceCompte'].isdigit():
                    a.id = '%s%s' % (a.id, a._args['IndiceCompte'])
                if a._args['Indiceclassement'].isdigit():
                    a.id = '%s%s' % (a.id, a._args['Indiceclassement'])

            # This account can be multiple life insurance accounts
            if (any(a.label.startswith(lab) for lab in ['ASS.VIE-BONS CAPI-SCPI-DIVERS', 'BONS CAPI-SCPI-DIVERS'])
                or (u'Aucun d\\351tail correspondant pour ce compte' in tr.xpath('.//a/@href')[0])
                    and 'COMPTE A TERME' not in tr.xpath('.//span[contains(@class, "left")]/text()')[0]):
                continue

            if a.type is Account.TYPE_CARD:
                a.coming = a.balance
                a.balance = Decimal('0.0')

                # Take the predecessiong checking account as parent
                if previous_checking_account:
                    a.parent = previous_checking_account
                else:
                    self.logger.warning('The card account %s has no parent account' % a.id)

            a._inv = True

            if a.type == Account.TYPE_CHECKING:
                previous_checking_account = a

            if previous_deposit_account and previous_deposit_account.id == a.id:
                a.id = a.id + '_%s' % deposit_count
                deposit_count += 1
                previous_deposit_account = a

            if a.type == Account.TYPE_DEPOSIT:
                previous_deposit_account = a

            yield a
Beispiel #51
0
    def get_list(self):
        no_accounts_message = self.doc.xpath(u'//span/b[contains(text(),"Votre abonnement est clôturé. Veuillez contacter votre conseiller.")]/text()')
        if no_accounts_message:
            raise ActionNeeded(no_accounts_message[0])

        previous_checking_account = None
        # Several deposit accounts ('Compte à terme') have the same id and the same label
        # So a number is added to distinguish them
        previous_deposit_account = None
        deposit_count = 1
        for tr in self.doc.xpath('//table[has-class("datas")]//tr'):
            if tr.attrib.get('class', '') == 'entete':
                continue

            cols = tr.findall('td')

            a = Account()
            a.label = unicode(cols[self.COL_ID].xpath('.//span[@class="left-underline"] | .//span[@class="left"]/a')[0].text.strip())
            a.type = self.get_account_type(a.label)
            balance = CleanText('.')(cols[self.COL_BALANCE])
            if balance == '':
                continue
            a.balance = CleanDecimal(replace_dots=True).filter(balance)
            a.currency = a.get_currency(balance)
            if cols[self.COL_ID].find('a'):
                a._link, a._args = self.params_from_js(cols[self.COL_ID].find('a').attrib['href'])
            # There may be a href with 'javascript:NoDetail();'
            # The _link and _args should be None
            else:
                a._link, a._args = None, None
            a._acc_nb = cols[self.COL_ID].xpath('.//span[@class="right-underline"] | .//span[@class="right"]')[0].text.replace(' ', '').strip()

            if hasattr(a, '_args') and a._args:
                a.id = '%s%s%s' % (a._acc_nb, a._args['IndiceCompte'], a._args['Indiceclassement'])
            else:
                a.id = a._acc_nb
            # This account can be multiple life insurance accounts
            if (any(a.label.startswith(lab) for lab in ['ASS.VIE-BONS CAPI-SCPI-DIVERS', 'BONS CAPI-SCPI-DIVERS'])
                or (u'Aucun d\\351tail correspondant pour ce compte' in tr.xpath('.//a/@href')[0])
                    and 'COMPTE A TERME' not in tr.xpath('.//span[contains(@class, "left")]/text()')[0]):
                continue

            if a.type is Account.TYPE_CARD:
                a.coming = a.balance
                a.balance = Decimal('0.0')

                # Take the predecessiong checking account as parent
                if previous_checking_account:
                    a.parent = previous_checking_account
                else:
                    self.logger.warning('The card account %s has no parent account' % a.id)

            a._inv = False

            if a.type == Account.TYPE_CHECKING:
                previous_checking_account = a

            if previous_deposit_account and previous_deposit_account.id == a.id:
                a.id = a.id + '_%s' % deposit_count
                deposit_count += 1
                previous_deposit_account = a

            if a.type == Account.TYPE_DEPOSIT:
                previous_deposit_account = a

            yield a
Beispiel #52
0
    def get_list(self):
        accounts = []

        for block in self.document.xpath('//div[@class="pave"]/div'):
            head_type = block.xpath(
                './div/span[@class="accGroupLabel"]')[0].text.strip()
            account_type = self.ACCOUNT_TYPES.get(head_type,
                                                  Account.TYPE_UNKNOWN)
            for tr in block.cssselect('ul li.tbord_account'):
                id = tr.attrib.get('id', '')
                if id.find('contratId') != 0:
                    self.logger.warning('Unable to parse contract ID: %r' % id)
                    continue
                id = id[id.find('contratId') + len('contratId'):]

                link = tr.cssselect('span.accountLabel a')[0]
                balance = Decimal(
                    FrenchTransaction.clean_amount(
                        tr.cssselect('span.accountTotal')[0].text))

                if id.endswith('CRT'):
                    account = accounts[-1]
                    account._card_links.append(link.attrib['href'])
                    if not account.coming:
                        account.coming = Decimal('0.0')
                    account.coming += balance
                    continue

                account = Account()
                account.id = id
                account.label = unicode(link.text.strip())
                account.type = account_type
                account.balance = balance
                account.currency = account.get_currency(
                    tr.cssselect('span.accountDev')[0].text)
                account._link = link.attrib['href']
                account._card_links = []
                accounts.append(account)

        if not accounts:
            # Sometimes, accounts are only in javascript...
            for script in self.document.xpath('//script'):
                text = script.text
                if text is None:
                    continue
                if 'remotePerso' not in text:
                    continue

                account = None
                attribs = {}
                account_type = Account.TYPE_UNKNOWN
                for line in text.split('\n'):
                    line = line.strip()
                    m = re.match("data.libelle = '(.*)';", line)
                    if m:
                        account_type = self.ACCOUNT_TYPES.get(
                            m.group(1), Account.TYPE_UNKNOWN)
                    elif line == 'var remotePerso = new Object;':
                        account = Account()
                    elif account is not None:
                        m = re.match("remotePerso.(\w+) = '?(.*?)'?;", line)
                        if m:
                            attribs[m.group(1)] = m.group(2)
                        elif line.startswith('listProduitsGroup'):
                            account.id = attribs['refContrat']

                            account.label = attribs['libelle']
                            account.type = account_type
                            account.balance = Decimal(
                                FrenchTransaction.clean_amount(
                                    attribs['soldeDateOpeValeurFormatted']))
                            account.currency = account.get_currency(
                                attribs['codeDevise'])
                            account._link = 'tbord.do?id=%s' % attribs['id']
                            account._card_links = []

                            if account.id.endswith('CRT'):
                                a = accounts[-1]
                                a._card_links.append(account._link)
                                if not a.coming:
                                    a.coming = Decimal('0.0')
                                a.coming += account.balance
                            else:
                                accounts.append(account)
                            account = None

        return accounts
Beispiel #53
0
    def get_list(self):
        accounts = []

        for block in self.doc.xpath('//div[@class="pave"]/div'):
            head_type = block.xpath(
                './div/span[@class="accGroupLabel"]')[0].text.strip()
            account_type = self.ACCOUNT_TYPES.get(head_type,
                                                  Account.TYPE_UNKNOWN)
            for tr in block.cssselect('ul li.tbord_account'):
                id = tr.attrib.get('id', '')
                if id.find('contratId') != 0:
                    self.logger.warning('Unable to parse contract ID: %r' % id)
                    continue
                id = id[id.find('contratId') + len('contratId'):]

                link = tr.cssselect('span.accountLabel a')[0]

                balance = CleanDecimal('.//span[@class="accountTotal"]',
                                       replace_dots=True)(tr)

                account = Account()
                account._attached_acc = None
                account.id = id
                account.label = unicode(link.text.strip())
                account.type = account_type
                account.balance = balance
                account.currency = account.get_currency(
                    tr.cssselect('span.accountDev')[0].text)
                account._link = link.attrib['href']
                if id.endswith('CRT'):
                    self.populate_cards(account)

                accounts.append(account)

        if len(accounts) == 0:
            # Sometimes, accounts are only in javascript...
            for script in self.doc.xpath('//script'):
                text = script.text
                if text is None:
                    continue
                if 'remotePerso' not in text:
                    continue

                account = None
                attribs = {}
                account_type = Account.TYPE_UNKNOWN
                for line in text.split('\n'):
                    line = line.strip()
                    m = re.match("data.libelle = '(.*)';", line)
                    if m:
                        account_type = self.ACCOUNT_TYPES.get(
                            m.group(1), Account.TYPE_UNKNOWN)
                    elif line == 'var remotePerso = new Object;':
                        account = Account()
                    elif account is not None:
                        m = re.match("remotePerso.(\w+) = '?(.*?)'?;", line)
                        if m:
                            attribs[m.group(1)] = m.group(2)
                        elif line.startswith('listProduitsGroup'):
                            account.id = attribs['refContrat']

                            account.label = attribs['libelle']
                            account.type = account_type
                            account.balance = Decimal(
                                FrenchTransaction.clean_amount(
                                    attribs['soldeDateOpeValeurFormatted']))
                            account.currency = account.get_currency(
                                attribs['codeDevise'])
                            account._link = 'tbord.do?id=%s&%s' % (
                                attribs['id'], self.browser.SESSION_PARAM)
                            account._attached_acc = None

                            if account.id.endswith('CRT'):
                                self.populate_cards(account)
                            elif any([
                                    word in account.label.lower()
                                    for word in ['courant', 'joint', 'perso']
                            ]):
                                account.type = account.TYPE_CHECKING
                            elif account.id.endswith('TTR'):
                                account.type = account.TYPE_MARKET
                            elif re.match('^\d+C$', account.id):
                                account.type = account.TYPE_LIFE_INSURANCE
                            elif re.match('^\d+PRT$', account.id):
                                account.type = account.TYPE_LOAN
                            elif not account.type:
                                account.type = account.TYPE_SAVINGS

                            accounts.append(account)
                            account = None

        return accounts