Пример #1
0
    def get_loan_list(self):
        accounts = OrderedDict()

        # Old website
        for tr in self.doc.xpath(
                '//table[@cellpadding="1"]/tr[not(@class) and td[a]]'):
            tds = tr.findall('td')

            account = Account()
            account.id = CleanText('./a')(tds[2]).split('-')[0].strip()
            account.label = CleanText('./a')(tds[2]).split('-')[-1].strip()
            account.type = Account.TYPE_LOAN
            account.balance = -CleanDecimal('./a', replace_dots=True)(tds[4])
            account.currency = account.get_currency(CleanText('./a')(tds[4]))
            accounts[account.id] = account

        if len(accounts) == 0:
            # New website
            for table in self.doc.xpath('//div[@class="panel"]'):
                title = table.getprevious()
                if title is None:
                    continue
                account_type = self.ACCOUNT_TYPES.get(
                    CleanText('.')(title), Account.TYPE_UNKNOWN)
                for tr in table.xpath(
                        './table/tbody/tr[contains(@id,"MM_SYNTHESE_CREDITS") and contains(@id,"IdTrGlobal")]'
                ):
                    tds = tr.findall('td')
                    if len(tds) == 0:
                        continue
                    for i in tds[0].xpath('.//a/strong'):
                        label = i.text.strip()
                        break
                    if len(tds) == 3 and Decimal(
                            FrenchTransaction.clean_amount(
                                CleanText('.')(tds[-2]))) and any(
                                    cls in Attr('.', 'id')(tr)
                                    for cls in ['dgImmo', 'dgConso']) == False:
                        # in case of Consumer credit or revolving credit, we substract avalaible amount with max amout
                        # to get what was spend
                        balance = Decimal(
                            FrenchTransaction.clean_amount(
                                CleanText('.')(tds[-2]))) - Decimal(
                                    FrenchTransaction.clean_amount(
                                        CleanText('.')(tds[-1])))
                    else:
                        balance = Decimal(
                            FrenchTransaction.clean_amount(
                                CleanText('.')(tds[-1])))
                    account = Account()
                    account.id = label.split(' ')[-1]
                    account.label = unicode(label)
                    account.type = account_type
                    account.balance = -abs(balance)
                    account.currency = account.get_currency(
                        CleanText('.')(tds[-1]))
                    account._card_links = []
                    accounts[account.id] = account

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

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

            cols = tr.findall('td')

            if len(cols) < 2:
                continue

            try:
                amount = sum([
                    Decimal(FrenchTransaction.clean_amount(txt))
                    for txt in cols[-1].itertext() if len(txt.strip()) > 0
                ])
            except InvalidOperation:
                continue

            a = cols[0].find('a')
            if a is None:
                for a in cols[0].xpath('.//li/a'):
                    args = self.js2args(a.attrib['href'])
                    if 'numero_compte' not in args or 'numero_poste' not in args:
                        self.logger.warning('Card link with strange args: %s' %
                                            args)
                        continue

                    account = Account()
                    account.id = '%s.%s' % (args['numero_compte'],
                                            args['numero_poste'])
                    account.label = u'Carte %s' % CleanText().filter(a)
                    account.balance = amount
                    account.type = account.TYPE_CARD
                    account.currency = [
                        account.get_currency(txt)
                        for txt in cols[-1].itertext() if len(txt.strip()) > 0
                    ][0]
                    yield account
                continue

            args = self.js2args(a.attrib['href'])

            if 'numero_compte' not in args or 'numero_poste' not in args:
                self.logger.warning(
                    'Account link for %r with strange args: %s' %
                    (a.attrib.get('alt', a.text), args))
                continue

            account = Account()
            account.id = u'%s.%s' % (args['numero_compte'],
                                     args['numero_poste'])
            account.label = to_unicode(a.attrib.get('alt', a.text.strip()))
            account.balance = amount
            account.currency = [
                account.get_currency(txt) for txt in cols[-1].itertext()
                if len(txt.strip()) > 0
            ][0]
            account.type = self.ACCOUNT_TYPES.get(account.label,
                                                  Account.TYPE_UNKNOWN)
            yield account
Пример #4
0
    def get_list(self):
        table = self.find_table()
        for tr in self.parser.select(table, 'tr', 'many'):
            tds = self.parser.select(tr, 'td')
            if len(tds) != 6:
                continue
            tdlabel, tdid, tdcur, tdupdated, tdbal, tdbalcur = tds

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

        # Old website
        for tr in self.doc.xpath('//table[@cellpadding="1"]/tr[not(@class) and td[a]]'):
            tds = tr.findall('td')

            account = Account()
            account.id = CleanText('./a')(tds[2]).split('-')[0].strip()
            account.label = CleanText('./a')(tds[2]).split('-')[-1].strip()
            account.type = Account.TYPE_LOAN
            account.balance = -CleanDecimal('./a', replace_dots=True)(tds[4])
            account.currency = account.get_currency(CleanText('./a')(tds[4]))
            accounts[account.id] = account

        if len(accounts) == 0:
            # New website
            for table in self.doc.xpath('//div[@class="panel"]'):
                title = table.getprevious()
                if title is None:
                    continue
                account_type = self.ACCOUNT_TYPES.get(CleanText('.')(title), Account.TYPE_UNKNOWN)
                for tr in table.xpath('./table/tbody/tr[contains(@id,"MM_SYNTHESE_CREDITS") and contains(@id,"IdTrGlobal")]'):
                    tds = tr.findall('td')
                    if len(tds) == 0 :
                        continue
                    for i in tds[0].xpath('.//a/strong'):
                        label = i.text.strip()
                        break
                    if len(tds) == 3 and Decimal(FrenchTransaction.clean_amount(CleanText('.')(tds[-2]))) and any(cls in Attr('.', 'id')(tr) for cls in ['dgImmo', 'dgConso']) == False:
                        # in case of Consumer credit or revolving credit, we substract avalaible amount with max amout
                        # to get what was spend
                        balance = Decimal(FrenchTransaction.clean_amount(CleanText('.')(tds[-2]))) - Decimal(FrenchTransaction.clean_amount(CleanText('.')(tds[-1])))
                    else:
                        balance = Decimal(FrenchTransaction.clean_amount(CleanText('.')(tds[-1])))
                    account = Loan()
                    account.id = label.split(' ')[-1]
                    account.label = unicode(label)
                    account.type = account_type
                    account.balance = -abs(balance)
                    account.currency = account.get_currency(CleanText('.')(tds[-1]))
                    account._card_links = []
                    if "immobiliers" in CleanText('.')(title):
                        xp = './/div[contains(@id, "IdDivDetail")]/table/tbody/tr[contains(@id, "%s")]/td'
                        account.maturity_date = Date(CleanText(xp % 'IdDerniereEcheance'), dayfirst=True, default=NotAvailable)(tr)
                        account.total_amount = CleanDecimal(CleanText(xp % 'IdCapitalEmprunte'), replace_dots=True, default=NotAvailable)(tr)
                        account.subscription_date = Date(CleanText(xp % 'IdDateOuverture'), dayfirst=True, default=NotAvailable)(tr)
                        account.next_payment_date = Date(CleanText(xp % 'IdDateProchaineEcheance'), dayfirst=True, default=NotAvailable)(tr)
                        account.rate = CleanDecimal(CleanText(xp % 'IdTaux'), replace_dots=True, default=NotAvailable)(tr)
                        account.next_payment_amount = CleanDecimal(CleanText(xp % 'IdMontantEcheance'), replace_dots=True, default=NotAvailable)(tr)
                    elif "renouvelables" in CleanText('.')(title):
                        self.go_loans_conso(tr)
                        d = self.browser.loans_conso()
                        if d:
                            account.total_amount = d['contrat']['creditMaxAutorise']
                            account.available_amount = d['situationCredit']['disponible']
                            account.next_payment_amount = d['situationCredit']['mensualiteEnCours']
                    accounts[account.id] = account
        return accounts.values()
Пример #7
0
    def get_accounts(self):
        accounts = {}
        content = self.document.xpath('//div[@id="main"]//div[@class="col first"]')[0]

        # Total currency balance.
        # If there are multiple currencies, this balance is all currencies
        # converted to the main currency.
        balance = content.xpath('.//h3/span[@class="balance"]')
        if not balance:
            balance = content.xpath('.//li[@class="balance"]//span/strong')
        balance = balance[0].text_content().strip()

        # Primary currency account
        primary_account = Account()
        primary_account.type = Account.TYPE_CHECKING
        primary_account.balance = clean_amount(balance)
        primary_account.currency = Account.get_currency(balance)
        primary_account.id = unicode(primary_account.currency)
        primary_account.label = u'%s %s*' % (self.browser.username, balance.split()[-1])
        accounts[primary_account.id] = primary_account

        # The following code will only work if the user enabled multiple currencies.
        balance = content.xpath('.//div[@class="body"]//ul/li[@class="balance"]/span')
        table = content.xpath('.//table[@id="balanceDetails"]//tbody//tr')

        # sanity check
        if bool(balance) is not bool(table):
            raise BrokenPageError('Unable to find all required multiple currency entries')

        # Primary currency balance.
        # If the user enabled multiple currencies, we get this one instead.
        # An Account object has only one currency; secondary currencies should be other accounts.
        if balance:
            balance = balance[0].text_content().strip()
            primary_account.balance = clean_amount(balance)
            # The primary currency of the "head balance" is the same; ensure we got the right one
            assert primary_account.currency == primary_account.get_currency(balance)

        for row in table:
            balance = row.xpath('.//td')[-1].text_content().strip()
            account = Account()
            account.type = Account.TYPE_CHECKING
            # XXX it ignores 5+ devises, so it's bad, but it prevents a crash, cf #1216
            try:
                account.balance = clean_amount(balance)
            except InvalidOperation:
                continue
            account.currency = Account.get_currency(balance)
            account.id = unicode(account.currency)
            account.label = u'%s %s' % (self.browser.username, balance.split()[-1])
            if account.id == primary_account.id:
                assert account.balance == primary_account.balance
                assert account.currency == primary_account.currency
            elif account.currency:
                accounts[account.id] = account

        return accounts
Пример #8
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
Пример #9
0
    def get_list(self):
        account_type = Account.TYPE_UNKNOWN

        params = {}
        for field in self.document.xpath('//input'):
            params[field.attrib['name']] = field.attrib.get('value', '')

        for div in self.document.xpath('//div[@class="btit"]'):
            account_type = self.ACCOUNT_TYPES.get(div.text.strip(), Account.TYPE_UNKNOWN)

            for tr in div.getnext().xpath('.//tbody/tr'):
                if not 'id' in tr.attrib:
                    continue

                args = dict(parse_qsl(tr.attrib['id']))
                tds = tr.findall('td')

                if len(tds) < 4 or not 'identifiant' in args:
                    self.logger.warning('Unable to parse an account')
                    continue

                account = Account()
                account.id = args['identifiant']
                account.label = u' '.join([u''.join([txt.strip() for txt in tds[1].itertext()]),
                                           u''.join([txt.strip() for txt in tds[2].itertext()])]).strip()
                account.type = account_type
                balance = u''.join([txt.strip() for txt in tds[3].itertext()])
                account.balance = Decimal(FrenchTransaction.clean_amount(balance))
                account.currency = account.get_currency(balance)
                account._params = params.copy()
                account._params['dialogActionPerformed'] = 'SOLDE'
                account._params['attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split('_', 1)[1]
                yield account

        return
Пример #10
0
 def get_loan_list(self):
     accounts = OrderedDict()
     # New website
     for table in self.document.xpath('//div[@class="panel"]'):
         title = table.getprevious()
         if title is None:
             continue
         account_type = self.ACCOUNT_TYPES.get(self.parser.tocleanstring(title), Account.TYPE_UNKNOWN)
         for tr in table.xpath('./table/tbody/tr[contains(@id,"MM_SYNTHESE_CREDITS") and contains(@id,"IdTrGlobal")]'):
             tds = tr.findall('td')
             if len(tds) == 0 :
                 continue
             for i in tds[0].xpath('.//a/strong'):
                 label = i.text.strip()
                 break
             balance = Decimal(FrenchTransaction.clean_amount(self.parser.tocleanstring(tds[-1])))
             account = Account()
             account.id = label.split(' ')[-1]
             account.label = unicode(label)
             account.type = account_type
             account.balance = -abs(balance)
             account.currency = account.get_currency(self.parser.tocleanstring(tds[-1]))
             account._card_links = []
             accounts[account.id] = account
     return accounts.itervalues()
Пример #11
0
    def _add_account(self, accounts, link, label, account_type, balance):
        info = self._get_account_info(link)
        if info is None:
            self.logger.warning('Unable to parse account %r: %r' % (label, link))
            return

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

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

        accounts[account.id] = account
Пример #12
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
Пример #13
0
    def get_account(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(parse_decimal(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.url = urljoin(self.url, link[0].attrib['href'])
            else:
                a.url = None

            return a
Пример #14
0
    def get_accounts_list(self):
        for table in self.doc.xpath('//div[@class="comptestabl"]/table'):
            try:
                account_type = self.ACCOUNT_TYPES[table.get('summary').lower()]
                if not account_type:
                    account_type = self.ACCOUNT_TYPES[table.xpath(
                        './caption/text()')[0].strip().lower()]
            except (IndexError, KeyError):
                account_type = Account.TYPE_UNKNOWN
            for tr in table.xpath('./tbody/tr'):
                cols = tr.findall('td')

                link = cols[0].find('a')
                if link is None:
                    continue

                a = Account()
                a.type = account_type
                a.id = unicode(
                    re.search('([A-Z\d]{4}[A-Z\d\*]{3}[A-Z\d]{4})',
                              link.attrib['title']).group(1))
                a.label = unicode(link.attrib['title'].replace(
                    '%s ' % a.id, ''))
                # We use '.text_content()' to avoid HTML comments like '<!-- ... -->'
                tmp_balance = CleanText(None).filter(cols[1].text_content())
                a.currency = a.get_currency(tmp_balance)
                if not a.currency:
                    a.currency = u'EUR'
                a.balance = Decimal(Transaction.clean_amount(tmp_balance))
                a._has_cards = False
                a.url = urljoin(self.url, link.attrib['href'])
                yield a
Пример #15
0
    def get_list(self, accounts_ids):
        l = []
        # Read the json data
        json_data = self.browser.readurl('/banque/PA_Autonomy-war/ProxyIAService?cleOutil=IA_SMC_UDC&service=getlstcpt&dashboard=true&refreshSession=true&cre=udc&poka=true')
        json_infos = json.loads(json_data)
        for famille in json_infos['smc']['data']['familleCompte']:
            id_famille = famille['idFamilleCompte']
            for compte in famille['compte']:
                account = Account()
                account.label = u''+compte['libellePersoProduit']
                account.currency = account.get_currency(compte['devise'])
                account.balance = Decimal(compte['soldeDispo'])
                account.coming = Decimal(compte['soldeAVenir'])
                account.type = self.ACCOUNT_TYPES.get(id_famille, Account.TYPE_UNKNOWN)
                account.id = 0
                account._link_id = 'KEY'+compte['key']

                # IBAN aren't in JSON
                # Fast method, get it from transfer page.
                for i,a in accounts_ids.items():
                    if a.label == account.label:
                        account.id = i
                # But it's doesn't work with LOAN and MARKET, so use slow method : Get it from transaction page.
                if account.id == 0:
                    account.id = self.browser.get_IBAN_from_account(account)
                l.append(account)

        if len(l) == 0:
            print 'no accounts'
            # oops, no accounts? check if we have not exhausted the allowed use
            # of this password
            for img in self.document.getroot().cssselect('img[align="middle"]'):
                if img.attrib.get('alt', '') == 'Changez votre code secret':
                    raise BrowserPasswordExpired('Your password has expired')
        return l
Пример #16
0
 def parse(self, el):
     page, url, data = self.page.get_changecompte(Link('.')(self)) if self.env['multi'] else (self.page, None, None)
     balance_xpath = '//div[contains(text(),"Solde")]/strong'
     self.env['balance'] = MyDecimal().filter(page.doc.xpath(balance_xpath))
     self.env['currency'] = Account.get_currency(CleanText().filter(page.doc.xpath(balance_xpath)))
     self.env['url'] = url
     self.env['data'] = data
Пример #17
0
    def get_list(self):
        div = self.document.xpath('//div[@id="descriptifdroite"]')[0]

        account = Account()

        account.id = re.search(
            u'(\d+)',
            div.xpath('.//div[@class="credithauttexte"]')[0].text).group(1)
        account.label = u'Carte PASS'
        account.balance = Decimal('0')

        for tr in div.xpath('.//table/tr'):
            tds = tr.findall('td')

            if len(tds) < 3:
                continue

            label = u''.join([txt.strip() for txt in tds[1].itertext()])
            value = u''.join([txt.strip() for txt in tds[2].itertext()])

            if 'encours depuis le dernier' in label.lower():
                coming = u'-' + value
                account.coming = Decimal(
                    FrenchTransaction.clean_amount(coming))
                account.currency = account.get_currency(coming)
            elif u'arrêté de compte' in label.lower():
                m = re.search(u'(\d+)/(\d+)/(\d+)', label)
                if m:
                    account._outstanding_date = datetime.date(
                        *reversed(map(int, m.groups())))
                    break

        yield account
Пример #18
0
 def get_loan_list(self):
     accounts = OrderedDict()
     # New website
     for table in self.document.xpath('//div[@class="panel"]'):
         title = table.getprevious()
         if title is None:
             continue
         account_type = self.ACCOUNT_TYPES.get(
             self.parser.tocleanstring(title), Account.TYPE_UNKNOWN)
         for tr in table.xpath(
                 './table/tbody/tr[contains(@id,"MM_SYNTHESE_CREDITS") and contains(@id,"IdTrGlobal")]'
         ):
             tds = tr.findall('td')
             if len(tds) == 0:
                 continue
             for i in tds[0].xpath('.//a/strong'):
                 label = i.text.strip()
                 break
             balance = Decimal(
                 FrenchTransaction.clean_amount(
                     self.parser.tocleanstring(tds[-1])))
             account = Account()
             account.id = label.split(' ')[-1]
             account.label = unicode(label)
             account.type = account_type
             account.balance = -abs(balance)
             account.currency = account.get_currency(
                 self.parser.tocleanstring(tds[-1]))
             account._card_links = []
             accounts[account.id] = account
     return accounts.itervalues()
Пример #19
0
    def parse_table(self, what):
        tables = self.document.xpath("//table[@id='%s']" % what, smart_strings=False)
        if len(tables) < 1:
            return

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

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

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

            if account.id in self.accounts:
                a = self.accounts[account.id]
                a._card_links.append(account._link_id)
                if not a.coming:
                    a.coming = Decimal("0.0")
                a.coming += account.balance
            else:
                account._card_links = []
                self.accounts[account.id] = account
Пример #20
0
    def _parse_account(self, tr):
        account = Account()

        # for pro usage
        account._stp = None

        account.id = tr.xpath('.//td[@class="libelleCompte"]/input')[0].attrib['id'][len('libelleCompte'):]
        if len(str(account.id)) == 23:
            account.id = str(account.id)[5:21]

        a = tr.xpath('.//td[@class="libelleCompte"]/a')[0]
        m = re.match(r'javascript:goToStatements\(\'(\d+)\'', a.get('onclick', ''))
        if m:
            account._link_id = m.group(1)
        else:
            # Can't get history for this account.
            account._link_id = None
            # To prevent multiple-IDs for CIF (for example), add an arbitrary char in ID.
            account.id += 'C'

        account.label = u''+a.text.strip()

        tds = tr.findall('td')
        account.currency = account.get_currency(tds[3].find('a').text)
        account.balance = self._parse_amount(tds[3].find('a'))
        if tds[4].find('a') is not None:
            account.coming = self._parse_amount(tds[4].find('a'))
        else:
            account.coming = NotAvailable

        return account
Пример #21
0
    def _parse_account(self, tr):
        account = Account()

        # for pro usage
        account._stp = None

        account.id = tr.xpath('.//td[@class="libelleCompte"]/input'
                              )[0].attrib['id'][len('libelleCompte'):]
        if len(str(account.id)) == 23:
            account.id = str(account.id)[5:21]

        a = tr.xpath('.//td[@class="libelleCompte"]/a')[0]
        m = re.match(r'javascript:goToStatements\(\'(\d+)\'',
                     a.get('onclick', ''))
        if m:
            account._link_id = m.group(1)
        else:
            # Can't get history for this account.
            account._link_id = None
            # To prevent multiple-IDs for CIF (for example), add an arbitrary char in ID.
            account.id += 'C'

        account.label = u'' + a.text.strip()

        tds = tr.findall('td')
        account.currency = account.get_currency(tds[3].find('a').text)
        account.balance = self._parse_amount(tds[3].find('a'))
        if tds[4].find('a') is not None:
            account.coming = self._parse_amount(tds[4].find('a'))
        else:
            account.coming = NotAvailable

        return account
Пример #22
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
Пример #23
0
    def get_list(self):
        for trCompte in self.document.xpath('//table[@id="compte"]/tbody/tr'):
            tds = trCompte.findall('td')

            account = Account()

            account.id = tds[self.CPT_ROW_ID].text.strip()
            account.label = unicode(tds[self.CPT_ROW_NAME].text.strip())

            account_type_str = "".join([
                td.text
                for td in tds[self.CPT_ROW_NATURE].xpath('.//td[@class="txt"]')
            ]).strip()

            account.type = self.ACCOUNT_TYPES.get(account_type_str,
                                                  Account.TYPE_UNKNOWN)

            account.balance = Decimal(
                FrenchTransaction.clean_amount(
                    self.parser.tocleanstring(tds[self.CPT_ROW_BALANCE])))
            account.coming = Decimal(
                FrenchTransaction.clean_amount(
                    self.parser.tocleanstring(tds[self.CPT_ROW_ENCOURS])))
            account.currency = account.get_currency(
                tds[self.CPT_ROW_BALANCE].find("a").text)
            yield account

        return
Пример #24
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
Пример #25
0
    def _add_account(self, accounts, link, label, account_type, balance):
        info = self._get_account_info(link)
        if info is None:
            self.logger.warning('Unable to parse account %r: %r' %
                                (label, link))
            return

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

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

        accounts[account.id] = account
Пример #26
0
 def account(self):
     label = u' '.join(self.doc.xpath(
         '//div[contains(@class,"myCreditCardDetails")]')[0]\
         .text_content().split())
     balance = self.amount(u'Balance')
     cardlimit = self.doc.xpath(
         u'//li[text()="Available to Spend"]')[0].text_content()\
         .replace(u'Available to Spend', u'').replace(u'Limit', u'').strip()
     paymin = self.amount(u'Payment Due')
     if self.doc.xpath(u'//li[@class="noPaymentDue"]'):
         # If payment date is not scheduled yet, set it somewhere in a
         # distant future, so that we always have a valid date.
         paydate = datetime.now() + timedelta(days=999)
     else:
         rawtext = self.doc.xpath(
             u'//li[contains(text(),"Due Date")]')[0].text_content()
         datetext = re.match('.*(\d\d/\d\d/\d\d\d\d).*', rawtext).group(1)
         paydate = datetime.strptime(datetext, '%m/%d/%Y')
     a = Account()
     a.id = label[-4:]
     a.label = label
     a.currency = Account.get_currency(balance)
     a.balance = -AmTr.decimal_amount(balance)
     a.type = Account.TYPE_CARD
     a.cardlimit = AmTr.decimal_amount(cardlimit)
     a.paymin = AmTr.decimal_amount(paymin)
     if paydate is not None:
         a.paydate = paydate
     return a
Пример #27
0
    def get_accounts_list(self):
        for table in self.doc.xpath('//div[@class="comptestabl"]/table'):
            try:
                account_type = self.ACCOUNT_TYPES[table.get('summary').lower()]
                if not account_type:
                    account_type = self.ACCOUNT_TYPES[table.xpath('./caption/text()')[0].strip().lower()]
            except (IndexError,KeyError):
                account_type = Account.TYPE_UNKNOWN
            for tr in table.xpath('./tbody/tr'):
                cols = tr.findall('td')

                link = cols[0].find('a')
                if link is None:
                    continue

                a = Account()
                a.type = account_type
                a.id = unicode(re.search('([A-Z\d]{4}[A-Z\d\*]{3}[A-Z\d]{4})', link.attrib['title']).group(1))
                a.label = unicode(link.attrib['title'].replace('%s ' % a.id, ''))
                tmp_balance = CleanText(None).filter(cols[1])
                a.currency = a.get_currency(tmp_balance)
                if not a.currency:
                    a.currency = u'EUR'
                a.balance = Decimal(Transaction.clean_amount(tmp_balance))
                a._has_cards = False
                a.url = urljoin(self.url, link.attrib['href'])
                yield a
Пример #28
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
Пример #29
0
 def account(self):
     label = u' '.join(
         self.doc.xpath('//div[contains(@class,"myCreditCardDetails")]')
         [0].text_content().split())
     balance = self.amount(u'Balance')
     cardlimit = self.doc.xpath(
         u'//li[text()="Available to Spend"]')[0].text_content()\
         .replace(u'Available to Spend', u'').replace(u'Limit', u'').strip()
     paymin = self.amount(u'Payment Due')
     if self.doc.xpath(u'//li[@class="noPaymentDue"]'):
         # If payment date is not scheduled yet, set it somewhere in a
         # distant future, so that we always have a valid date.
         paydate = datetime.now() + timedelta(days=999)
     else:
         rawtext = self.doc.xpath(
             u'//li[contains(text(),"Due Date")]')[0].text_content()
         datetext = re.match('.*(\d\d/\d\d/\d\d\d\d).*', rawtext).group(1)
         paydate = datetime.strptime(datetext, '%m/%d/%Y')
     a = Account()
     a.id = label[-4:]
     a.label = label
     a.currency = Account.get_currency(balance)
     a.balance = -AmTr.decimal_amount(balance)
     a.type = Account.TYPE_CARD
     a.cardlimit = AmTr.decimal_amount(cardlimit)
     a.paymin = AmTr.decimal_amount(paymin)
     if paydate is not None:
         a.paydate = paydate
     return a
Пример #30
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
Пример #31
0
    def get_accounts_list(self):
        for table in self.document.xpath('//div[@class="comptestabl"]/table'):
            try:
                account_type = self.ACCOUNT_TYPES[table.get('summary')]
                if not account_type:
                    account_type = self.ACCOUNT_TYPES[table.xpath(
                        './caption/text()')[0].strip()]
            except (IndexError, KeyError):
                account_type = Account.TYPE_UNKNOWN
            for tr in table.xpath('./tbody/tr'):
                cols = tr.findall('td')

                link = cols[0].find('a')
                if link is None:
                    continue

                a = Account()
                a.type = account_type
                a.id = unicode(
                    re.search('([A-Z\d]{4}[A-Z\d\*]{3}[A-Z\d]{4})',
                              link.attrib['title']).group(1))
                a.label = unicode(link.attrib['title'].replace(
                    '%s ' % a.id, ''))
                tmp_balance = self.parser.tocleanstring(cols[1])
                a.currency = a.get_currency(tmp_balance)
                a.balance = Decimal(Transaction.clean_amount(tmp_balance))
                a._card_links = []
                a._link_id = link.attrib['href']
                yield a
Пример #32
0
    def get_card_history(self, account, coming):
        if coming:
            debit_date = account._next_debit
        elif not hasattr(account, '_prev_balance'):
            return
        else:
            debit_date = account._prev_debit
            if 'ContinueTask.do' in self.url:
                t = Transaction()
                t.parse(debit_date, 'RELEVE CARTE')
                t.amount = -account._prev_balance
                yield t

        currency = Account.get_currency(self.document\
                                        .xpath('//table[@id="TabFact"]/thead//th')[self.COL_CARD_AMOUNT]\
                                        .text\
                                        .replace('(', ' ')\
                                        .replace(')', ' '))
        for i, tr in enumerate(self.document.xpath('//table[@id="TabFact"]/tbody/tr')):
            tds = tr.findall('td')

            if len(tds) < 3:
                continue

            t = Transaction()

            date = self.parser.tocleanstring(tds[self.COL_CARD_DATE])
            label = self.parser.tocleanstring(tds[self.COL_CARD_LABEL])
            amount = '-' + self.parser.tocleanstring(tds[self.COL_CARD_AMOUNT])

            t.parse(debit_date, re.sub(r'[ ]+', ' ', label))
            t.set_amount(amount)
            t.rdate = t.parse_date(date)
            t.original_currency = currency
            yield t
Пример #33
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
Пример #34
0
    def get_list(self, accounts_ids):
        l = []
        # Read the json data
        json_data = self.browser.readurl('/banque/PA_Autonomy-war/ProxyIAService?cleOutil=IA_SMC_UDC&service=getlstcpt&dashboard=true&refreshSession=true&cre=udc&poka=true')
        json_infos = json.loads(json_data)
        for famille in json_infos['smc']['data']['familleCompte']:
            id_famille = famille['idFamilleCompte']
            for compte in famille['compte']:
                account = Account()
                account.label = u''+compte['libellePersoProduit']
                account.currency = account.get_currency(compte['devise'])
                account.balance = Decimal(str(compte['soldeDispo']))
                account.coming = Decimal(str(compte['soldeAVenir']))
                account.type = self.ACCOUNT_TYPES.get(id_famille, Account.TYPE_UNKNOWN)
                account.id = 0
                account._link_id = 'KEY'+compte['key']

                # IBAN aren't in JSON
                # Fast method, get it from transfer page.
                for i,a in accounts_ids.items():
                    if a.label == account.label:
                        account.id = i
                # But it's doesn't work with LOAN and MARKET, so use slow method : Get it from transaction page.
                if account.id == 0:
                    account.id = self.browser.get_IBAN_from_account(account)
                l.append(account)

        if len(l) == 0:
            print 'no accounts'
            # oops, no accounts? check if we have not exhausted the allowed use
            # of this password
            for img in self.document.getroot().cssselect('img[align="middle"]'):
                if img.attrib.get('alt', '') == 'Changez votre code secret':
                    raise BrowserPasswordExpired('Your password has expired')
        return l
Пример #35
0
    def get_accounts(self):
        accounts = {}
        content = self.doc.xpath('//div[@id="moneyPage"]')[0]

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

        accounts[primary_account.id] = primary_account

        return accounts
Пример #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.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
Пример #37
0
 def parse(self, el):
     page, url, data = self.page.get_changecompte(Link('.')(self)) if self.env['multi'] else (self.page, None, None)
     balance_xpath = '//div[contains(text(),"Solde")]/strong'
     self.env['balance'] = MyDecimal().filter(page.doc.xpath(balance_xpath))
     self.env['currency'] = Account.get_currency(CleanText().filter(page.doc.xpath(balance_xpath)))
     self.env['url'] = url
     self.env['data'] = data
Пример #38
0
    def get_list(self):
        div = self.document.xpath('//div[@id="descriptifdroite"]')[0]

        account = Account()

        account.id = re.search(u'(\d+)', div.xpath('.//div[@class="credithauttexte"]')[0].text).group(1)
        account.label = u'Carte PASS'
        account.balance = Decimal('0')

        for tr in div.xpath('.//table/tr'):
            tds = tr.findall('td')

            if len(tds) < 3:
                continue

            label = u''.join([txt.strip() for txt in tds[1].itertext()])
            value = u''.join([txt.strip() for txt in tds[2].itertext()])

            if 'encours depuis le dernier' in label.lower():
                coming = u'-' + value
                account.coming = Decimal(FrenchTransaction.clean_amount(coming))
                account.currency = account.get_currency(coming)
            elif u'arrêté de compte' in label.lower():
                m = re.search(u'(\d+)/(\d+)/(\d+)', label)
                if m:
                    account._outstanding_date = datetime.date(*reversed(map(int, m.groups())))
                    break

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

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

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

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

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

        accounts[account.id] = account
Пример #40
0
                def parse(self, el):
                    try:
                        self.env['raw'] = "%s %s" % (CleanText().filter(
                            TableCell('commerce')
                            (self)[0].text), CleanText().filter(
                                TableCell('ville')(self)[0].text))
                    except (ColumnNotFound, AttributeError):
                        self.env['raw'] = "%s" % (CleanText().filter(
                            TableCell('commerce')(self)[0].text))

                    self.env['type'] = Transaction.TYPE_DEFERRED_CARD \
                                       if CleanText(u'//a[contains(text(), "Prélevé fin")]', default=None) else Transaction.TYPE_CARD
                    self.env['differed_date'] = parse_french_date(
                        Regexp(CleanText(u'//*[contains(text(), "Achats")]'),
                               'au[\s]+(.*)')(self)).date()
                    amount = TableCell('credit')(self)[0]
                    if self.page.browser.is_new_website:
                        amount = amount.xpath('./div')[0] if len(
                            amount.xpath('./div')) else TableCell('debit')(
                                self)[0].xpath('./div')[0]
                    self.env['amount'] = CleanDecimal(
                        replace_dots=True).filter(amount.text)
                    original_amount = None if self.page.browser.is_new_website else amount.xpath(
                        './span')[0].text
                    self.env['original_amount'] = CleanDecimal(replace_dots=True).filter(original_amount) \
                                                  if original_amount is not None else NotAvailable
                    self.env['original_currency'] = Account.get_currency(original_amount[1:-1]) \
                                                  if original_amount is not None else NotAvailable
Пример #41
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
Пример #42
0
 def account(self):
     id_ = self.doc.xpath(
         u'//strong[contains(text(),'
         '"credit card account ending in")]/text()')[0].strip()[-4:]
     balance = self.doc.xpath(
         u'//section[@id=" account_summary"]'
         '//span[text()="Current Balance"]/../span[2]/text()')[0].strip()
     cardlimit = self.doc.xpath(u'//span[contains(text(),"Credit limit")]'
                                '/text()')[0].split()[-1]
     paymin = self.doc.xpath(
         u'//section[@id=" account_summary"]'
         '//strong[text()="Minimum Payment Due"]/../../span[2]/text()'
     )[0].strip()
     a = Account()
     a.id = id_
     a.label = u'ACCOUNT ENDING IN %s' % id_
     a.currency = Account.get_currency(balance)
     a.balance = -AmTr.decimal_amount(balance)
     a.type = Account.TYPE_CARD
     a.cardlimit = AmTr.decimal_amount(cardlimit)
     a.paymin = AmTr.decimal_amount(paymin)
     #TODO: Add paydate.
     #Oleg: I don't have an account with scheduled payment.
     #      Need to wait for a while...
     return a
Пример #43
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
Пример #44
0
    def get_list(self):
        accounts = OrderedDict()

        for tr in self.document.getiterator('tr'):
            first_td = tr.getchildren()[0]
            if (first_td.attrib.get('class', '') == 'i g' or first_td.attrib.get('class', '') == 'p g') \
               and first_td.find('a') is not None:

                a = first_td.find('a')
                link = a.get('href', '')
                if link.startswith('POR_SyntheseLst'):
                    continue

                url = urlparse(link)
                p = parse_qs(url.query)
                if not 'rib' in p:
                    continue

                for i in (2,1):
                    balance = FrenchTransaction.clean_amount(tr.getchildren()[i].text)
                    currency = Account.get_currency(tr.getchildren()[i].text)
                    if len(balance) > 0:
                        break
                balance = Decimal(balance)

                id = p['rib'][0]
                if id in accounts:
                    account = accounts[id]
                    if not account.coming:
                        account.coming = Decimal('0.0')
                    account.coming += balance
                    account._card_links.append(link)
                    continue

                account = Account()
                account.id = id
                account.label = unicode(a.text).strip().lstrip(' 0123456789').title()
                account._link_id = link
                account._card_links = []

                # Find accounting amount
                page = self.browser.get_document(self.browser.openurl(link))
                coming = self.find_amount(page, u"Opérations à venir")
                accounting = self.find_amount(page, u"Solde comptable")

                if accounting is not None and accounting + (coming or Decimal('0')) != balance:
                    self.logger.warning('%s + %s != %s' % (accounting, coming, balance))

                if accounting is not None:
                    balance = accounting

                if coming is not None:
                    account.coming = coming
                account.balance = balance
                account.currency = currency

                accounts[account.id] = account

        return accounts.itervalues()
Пример #45
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
Пример #46
0
    def iter_accounts(self, next_pages):
        account_type = Account.TYPE_UNKNOWN

        params = {}
        for field in self.document.xpath('//input'):
            params[field.attrib['name']] = field.attrib.get('value', '')

        for div in self.document.getroot().cssselect('div.btit'):
            if div.text is None:
                continue
            account_type = self.ACCOUNT_TYPES.get(div.text.strip(), Account.TYPE_UNKNOWN)

            if account_type is None:
                # ignore services accounts
                continue

            currency = None
            for th in div.getnext().xpath('.//thead//th'):
                m = re.match('.*\((\w+)\)$', th.text)
                if m and currency is None:
                    currency = Account.get_currency(m.group(1))

            for tr in div.getnext().xpath('.//tbody/tr'):
                if 'id' not in tr.attrib:
                    continue

                args = dict(parse_qsl(tr.attrib['id']))
                tds = tr.findall('td')

                if len(tds) < 4 or 'identifiant' not in args:
                    self.logger.warning('Unable to parse an account')
                    continue

                account = Account()
                account.id = args['identifiant'].replace(' ', '')
                account.label = u' '.join([u''.join([txt.strip() for txt in tds[1].itertext()]),
                                           u''.join([txt.strip() for txt in tds[2].itertext()])]).strip()
                account.type = account_type

                balance = FrenchTransaction.clean_amount(u''.join([txt.strip() for txt in tds[3].itertext()]))
                account.balance = Decimal(balance or '0.0')
                account.currency = currency
                if account.type == account.TYPE_LOAN:
                    account.balance = - abs(account.balance)

                account._prev_debit = None
                account._next_debit = None
                account._params = None
                account._coming_params = None
                if balance != u'' and len(tds[3].xpath('.//a')) > 0:
                    account._params = params.copy()
                    account._params['dialogActionPerformed'] = 'SOLDE'
                    account._params['attribute($SEL_$%s)' % tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split('_', 1)[1]

                if len(tds) >= 5 and len(tds[self.COL_COMING].xpath('.//a')) > 0:
                    _params = account._params.copy()
                    _params['dialogActionPerformed'] = 'ENCOURS_COMPTE'
                    next_pages.append(_params)
                yield account
Пример #47
0
    def get_list(self):
        """
            Returns the list of available bank accounts
        """
        for div in self.document.getiterator('div'):
            if div.attrib.get('class', '') in (
                    'dv', 'headline') and div.getchildren()[0].tag in ('a',
                                                                       'br'):
                self.logger.debug("Analyzing div %s" % div)
                # Step 1: extract text tokens
                tokens = []
                required_tokens = {}
                optional_tokens = {}
                token_extractor = TokenExtractor()
                for token in token_extractor.extract_tokens(div):
                    self.logger.debug('Extracted text token: "%s"' % token)
                    tokens.append(token)
                # Step 2: analyse tokens
                for token in tokens:
                    if self.look_like_account_number(token):
                        required_tokens['account_number'] = token
                    elif self.look_like_amount(token):
                        required_tokens['account_amount'] = token
                    elif self.look_like_account_name(token):
                        required_tokens['account_name'] = token
                    elif self.look_like_account_owner(token):
                        if 'account_owner' in optional_tokens and 'account_name' not in required_tokens:
                            required_tokens['account_name'] = optional_tokens[
                                'account_owner']
                        optional_tokens['account_owner'] = token
                # Step 3: create account objects
                if len(required_tokens) >= 3:
                    account = Account()
                    account.label = required_tokens['account_name']
                    account.id = required_tokens['account_number']
                    account.balance = FrenchTransaction.clean_amount(
                        required_tokens['account_amount'])
                    account.currency = account.get_currency(
                        required_tokens['account_amount'])
                    # we found almost all required information to create an account object
                    self.logger.debug(
                        'Found account %s with number %s and balance = %.2f' %
                        (account.label, account.id, account.balance))
                    # we may have found the owner name too
                    if optional_tokens.get('account_owner') is not None:
                        # well, we could add it to the label, but is this really required?
                        self.logger.debug('  the owner appears to be %s' %
                                          optional_tokens['account_owner'])
                    # we simply lack the link to the account history... which remains optional
                    first_link = div.find('a')
                    if first_link is not None:
                        account._link_id = first_link.get('href')
                        self.logger.debug(
                            '  the history link appears to be %s' %
                            account._link_id)
                    else:
                        account._link_id = None

                    yield account
Пример #48
0
 def parse(self, el):
     page = self.page.get_changecompte(Link('.')(self)) if self.page.multi else self.page
     self.env['accid'] = CleanText('.')(self).strip().replace(' ', '').split('-')[0]
     self.env['label'] = CleanText('.')(self).split("-")[-1].strip()
     balance_xpath = '//div[contains(text(),"Solde")]/strong'
     self.env['balance'] = MyDecimal().filter(page.doc.xpath(balance_xpath))
     self.env['currency'] = Account.get_currency(CleanText().filter(page.doc.xpath(balance_xpath)))
     self.env['page'] = page
Пример #49
0
    def get_list(self):
        l = []
        ids = set()
        for a in self.document.getiterator('a'):
            link = a.attrib.get('href')
            if link is None:
                continue
            if link.startswith("/outil/UWLM/ListeMouvements"):
                account = Account()
                account._link_id = link + "&mode=45"
                account._coming_links = []
                parameters = link.split("?").pop().split("&")
                for parameter in parameters:
                    list = parameter.split("=")
                    value = list.pop()
                    name = list.pop()
                    if name == "agence":
                        account.id = value
                    elif name == "compte":
                        account.id += value
                    elif name == "nature":
                        # TODO parse this string to get the right Account.TYPE_* to
                        # store in account.type.
                        account._type = value

                if account.id in ids:
                    continue

                ids.add(account.id)
                div = a.getparent().getprevious()
                if not div.text.strip():
                    div = div.find('div')
                account.label = u'' + div.text.strip()
                balance = FrenchTransaction.clean_amount(a.text)
                if '-' in balance:
                    balance = '-' + balance.replace('-', '')
                account.balance = Decimal(balance)
                account.currency = account.get_currency(a.text)
                self.logger.debug('%s Type: %s' %
                                  (account.label, account._type))
                l.append(account)
            if link.startswith('/outil/UWCB/UWCBEncours'):
                if len(l) == 0:
                    self.logger.warning(
                        'There is a card account but not any check account')
                    continue

                account = l[-1]

                coming = FrenchTransaction.clean_amount(a.text)
                if '-' in coming:
                    coming = '-' + coming.replace('-', '')
                if not account.coming:
                    account.coming = Decimal('0')
                account.coming += Decimal(coming)
                account._coming_links.append(link)

        return l
Пример #50
0
    def get_list(self):
        for tr in self.doc.xpath('//table[@class="compteTable"]/tr'):
            if not tr.attrib.get('class', '').startswith('ligne_'):
                continue

            cols = tr.findall('td')

            if len(cols) < 2:
                continue

            try:
                amount = sum([Decimal(FrenchTransaction.clean_amount(txt)) for txt in cols[-1].itertext() if len(txt.strip()) > 0])
            except InvalidOperation:
                continue

            a = cols[0].find('a')
            if a is None:
                for a in cols[0].xpath('.//li/a'):
                    args = self.js2args(a.attrib['href'])
                    if 'numero_compte' not in args or 'numero_poste' not in args:
                        self.logger.warning('Card link with strange args: %s' % args)
                        continue

                    account = Account()
                    account.id = '%s.%s' % (args['numero_compte'], args['numero_poste'])
                    account.label = u'Carte %s' % CleanText().filter(a)
                    account.balance = amount
                    account.type = account.TYPE_CARD
                    account.currency = [account.get_currency(txt) for txt in cols[-1].itertext() if len(txt.strip()) > 0][0]
                    yield account
                continue

            args = self.js2args(a.attrib['href'])

            if 'numero_compte' not in args or 'numero_poste' not in args:
                self.logger.warning('Account link for %r with strange args: %s' % (a.attrib.get('alt', a.text), args))
                continue

            account = Account()
            account.id = u'%s.%s' % (args['numero_compte'], args['numero_poste'])
            account.label = to_unicode(a.attrib.get('alt', a.text.strip()))
            account.balance = amount
            account.currency = [account.get_currency(txt) for txt in cols[-1].itertext() if len(txt.strip()) > 0][0]
            account.type = self.ACCOUNT_TYPES.get(account.label, Account.TYPE_UNKNOWN)
            yield account
Пример #51
0
    def get_list(self):
        for table in self.document.getroot().cssselect('div#table-panorama table.table-produit'):
            tds = table.xpath('./tbody/tr')[0].findall('td')
            if len(tds) < 3:
                continue

            boxes = table.xpath('./tbody//tr')
            foot = table.xpath('./tfoot//tr')

            for box in boxes:
                account = Account()

                if len(box.xpath('.//a')) != 0 and 'onclick' in box.xpath('.//a')[0].attrib:
                    args = self.js2args(box.xpath('.//a')[0].attrib['onclick'])
                    account.label =  u'{0} {1}'.format(unicode(table.xpath('./caption')[0].text.strip()), unicode(box.xpath('.//a')[0].text.strip()))
                elif len(foot[0].xpath('.//a')) != 0 and 'onclick' in foot[0].xpath('.//a')[0].attrib:
                    args = self.js2args(foot[0].xpath('.//a')[0].attrib['onclick'])
                    account.label =  unicode(table.xpath('./caption')[0].text.strip())
                else:
                    continue

                self.logger.debug('Args: %r' % args)
                if 'paramNumCompte' not in args:
                    try:
                        label = unicode(table.xpath('./caption')[0].text.strip())
                    except Exception:
                        label = 'Unable to determine'
                    self.logger.warning('Unable to get account ID for %r' % label)
                    continue
                try:
                    account.id = args['paramNumCompte'] + args['paramNumContrat']
                    if 'Visa' in account.label:
                        card_id = re.search('(\d+)', box.xpath('./td[2]')[0].text.strip())
                        if card_id:
                            account.id += card_id.group(1)
                    if 'Valorisation' in account.label or u'Liquidités' in account.label:
                        account.id += args['idPanorama:_idcl'].split('Jsp')[-1]

                except KeyError:
                    account.id = args['paramNumCompte']
                account_type_str = table.attrib['class'].split(' ')[-1][len('tableaux-comptes-'):]
                account.type = self.ACCOUNT_TYPES.get(account_type_str, Account.TYPE_UNKNOWN)

                currency_title = table.xpath('./thead//th[@class="montant"]')[0].text.strip()
                m = re.match('Montant \((\w+)\)', currency_title)
                if not m:
                    self.logger.warning('Unable to parse currency %r' % currency_title)
                else:
                    account.currency = account.get_currency(m.group(1))

                try:
                    account.balance = Decimal(FrenchTransaction.clean_amount(self.parse_number(u''.join([txt.strip() for txt in box.cssselect("td.montant")[0].itertext()]))))
                except InvalidOperation:
                    #The account doesn't have a amount
                    pass
                account._args = args
                yield account
Пример #52
0
    def get_list(self):
        for table in self.document.getroot().cssselect('div#table-panorama table.table-produit'):
            tds = table.xpath('./tbody/tr')[0].findall('td')
            if len(tds) < 3:
                continue

            boxes = table.xpath('./tbody//tr')
            foot = table.xpath('./tfoot//tr')

            for box in boxes:
                account = Account()

                if len(box.xpath('.//a')) != 0 and 'onclick' in box.xpath('.//a')[0].attrib:
                    args = self.js2args(box.xpath('.//a')[0].attrib['onclick'])
                    account.label =  u'{0} {1}'.format(unicode(table.xpath('./caption')[0].text.strip()), unicode(box.xpath('.//a')[0].text.strip()))
                elif len(foot[0].xpath('.//a')) != 0 and 'onclick' in foot[0].xpath('.//a')[0].attrib:
                    args = self.js2args(foot[0].xpath('.//a')[0].attrib['onclick'])
                    account.label =  unicode(table.xpath('./caption')[0].text.strip())
                else:
                    continue

                self.logger.debug('Args: %r' % args)
                if 'paramNumCompte' not in args:
                    try:
                        label = unicode(table.xpath('./caption')[0].text.strip())
                    except Exception:
                        label = 'Unable to determine'
                    self.logger.warning('Unable to get account ID for %r' % label)
                    continue
                try:
                    account.id = args['paramNumCompte'] + args['paramNumContrat']
                    if 'Visa' in account.label:
                        card_id = re.search('(\d+)', box.xpath('./td[2]')[0].text.strip())
                        if card_id:
                            account.id += card_id.group(1)
                    if 'Valorisation' in account.label or u'Liquidités' in account.label:
                        account.id += args['idPanorama:_idcl'].split('Jsp')[-1]

                except KeyError:
                    account.id = args['paramNumCompte']
                account_type_str = table.attrib['class'].split(' ')[-1][len('tableaux-comptes-'):]
                account.type = self.ACCOUNT_TYPES.get(account_type_str, Account.TYPE_UNKNOWN)

                currency_title = table.xpath('./thead//th[@class="montant"]')[0].text.strip()
                m = re.match('Montant \((\w+)\)', currency_title)
                if not m:
                    self.logger.warning('Unable to parse currency %r' % currency_title)
                else:
                    account.currency = account.get_currency(m.group(1))

                try:
                    account.balance = Decimal(FrenchTransaction.clean_amount(u''.join([txt.strip() for txt in box.cssselect("td.montant")[0].itertext()])))
                except InvalidOperation:
                    #The account doesn't have a amount
                    pass
                account._args = args
                yield account
Пример #53
0
 def get_av_balance(self):
     balance_xpath = '//p[contains(text(), "montant de votre épargne")]'
     balance = CleanDecimal(Regexp(CleanText(balance_xpath),
                                   r'est de ([\s\d,]+)',
                                   default=NotAvailable),
                            replace_dots=True,
                            default=NotAvailable)(self.doc)
     currency = Account.get_currency(CleanText(balance_xpath)(self.doc))
     return balance, currency
Пример #54
0
    def get_list(self):
        l = []
        ids = set()
        for a in self.document.getiterator('a'):
            link=a.attrib.get('href')
            if link is None:
                continue
            if link.startswith("/outil/UWLM/ListeMouvements"):
                account = Account()
                #by default the website propose the last 7 days or last 45 days but we can force to have the last 55days
                account._link_id=link+"&mode=55"
                account._coming_links = []
                parameters=link.split("?").pop().split("&")
                for parameter in parameters:
                    list=parameter.split("=")
                    value=list.pop()
                    name=list.pop()
                    if name=="agence":
                        account.id=value
                    elif name=="compte":
                        account.id+=value
                    elif name=="nature":
                        # TODO parse this string to get the right Account.TYPE_* to
                        # store in account.type.
                        account._type=value

                if account.id in ids:
                    continue

                ids.add(account.id)
                div = a.getparent().getprevious()
                if not div.text.strip():
                    div = div.find('div')
                account.label=u''+div.text.strip()
                balance = FrenchTransaction.clean_amount(a.text)
                if '-' in balance:
                    balance='-'+balance.replace('-', '')
                account.balance=Decimal(balance)
                account.currency = account.get_currency(a.text)
                self.logger.debug('%s Type: %s' % (account.label, account._type))
                l.append(account)
            if link.startswith('/outil/UWCB/UWCBEncours'):
                if len(l) == 0:
                    self.logger.warning('There is a card account but not any check account')
                    continue

                account = l[-1]

                coming = FrenchTransaction.clean_amount(a.text)
                if '-' in coming:
                    coming = '-'+coming.replace('-', '')
                if not account.coming:
                    account.coming = Decimal('0')
                account.coming += Decimal(coming)
                account._coming_links.append(link)

        return l
Пример #55
0
    def _get_account(self, line):
        tds = line.findall('td')
        account = Account()
        account.id = self.parser.tocleanstring(tds[self.COL_ID])
        account.label = self.parser.tocleanstring(tds[self.COL_LABEL])

        balance_str = self.parser.tocleanstring(tds[self.COL_AMOUNT])
        account.balance = Decimal(FrenchTransaction.clean_amount(balance_str))
        account.currency = account.get_currency(balance_str)
        return account
Пример #56
0
    def _get_account(self, line):
        tds = line.findall('td')
        account = Account()
        account.id = self.parser.tocleanstring(tds[self.COL_ID])
        account.label = self.parser.tocleanstring(tds[self.COL_LABEL])

        balance_str = self.parser.tocleanstring(tds[self.COL_AMOUNT])
        account.balance = Decimal(FrenchTransaction.clean_amount(balance_str))
        account.currency = account.get_currency(balance_str)
        return account
Пример #57
0
 def iter_accounts(self):
     self.start()
     bal = self.wait('div.cT-valueItem span.cT-balanceIndicator1')[0].text
     account = Account()
     account.id = self._account_id()
     account.label = self._account_link().text
     account.currency = Account.get_currency(bal)
     account.balance = -AmTr.decimal_amount(bal)
     account.type = Account.TYPE_CARD
     self.finish()
     yield account
Пример #58
0
 def account(self):
     label = u' '.join(u''.join(self.doc.xpath(
         u'//text()[contains(.,"Account ending in")]')).split())
     balance = self.doc.xpath(
         '//span[@id="currentBalance"]/..')[0].text_content()
     a = Account()
     a.id = label[-4:]
     a.label = label
     a.currency = Account.get_currency(balance)
     a.balance = -AmTr.decimal_amount(balance)
     a.type = Account.TYPE_CARD
     return a
Пример #59
0
    def get_list(self):
        for div in self.document.getiterator('div'):
            if div.attrib.get('id', '') == 'synthese-list':
                for tr in div.getiterator('tr'):
                    account = Account()
                    account.id = None
                    account._link_id = None
                    for td in tr.getiterator('td'):
                        if td.attrib.get('class', '') == 'account-cb':
                            break

                        elif td.attrib.get('class', '') == 'account-name':
                            try:
                                span = td.xpath('./span[@class="label"]')[0]
                            except IndexError:
                                # ignore account
                                break
                            account.label = self.parser.tocleanstring(span)
                            try:
                                account._link_id = td.xpath('.//a')[0].attrib['href']
                            except KeyError:
                                pass

                        elif td.attrib.get('class', '') == 'account-more-actions':
                            for a in td.getiterator('a'):
                                # For normal account, two "account-more-actions"
                                # One for the account, one for the credit card. Take the good one
                                if "mouvements.phtml" in a.attrib['href'] and "/cartes/" not in a.attrib['href']:
                                    account._link_id = a.attrib['href']

                        elif td.attrib.get('class', '') == 'account-number':
                            id = td.text
                            id = id.strip(u' \n\t')
                            account.id = id

                        elif td.attrib.get('class', '') == 'account-total':
                            span = td.find('span')
                            if span is None:
                                balance = td.text
                            else:
                                balance = span.text
                            account.currency = account.get_currency(balance)
                            balance = FrenchTransaction.clean_amount(balance)
                            if balance != "":
                                account.balance = Decimal(balance)
                            else:
                                account.balance = Decimal(0)

                    else:
                        # because of some weird useless <tr>
                        if account.id is not None:
                            yield account
Пример #60
0
    def get_list(self):
        accounts = []
        for tr in self.document.getiterator('tr'):
            if not 'LGNTableRow' in tr.attrib.get('class', '').split():
                continue

            account = Account()
            for td in tr.getiterator('td'):
                if td.attrib.get('headers', '') == 'TypeCompte':
                    a = td.find('a')
                    if a is None:
                        break
                    account.label = unicode(a.find("span").text)
                    for pattern, actype in self.TYPES.iteritems():
                        if account.label.startswith(pattern):
                            account.type = actype
                    account._link_id = a.get('href', '')

                elif td.attrib.get('headers', '') == 'NumeroCompte':
                    id = td.text
                    id = id.replace(u'\xa0','')
                    account.id = id

                elif td.attrib.get('headers', '') == 'Libelle':
                    pass

                elif td.attrib.get('headers', '') == 'Solde':
                    div = td.xpath('./div[@class="Solde"]')
                    if len(div) > 0:
                        balance = self.parser.tocleanstring(div[0])
                        if len(balance) > 0 and balance not in ('ANNULEE', 'OPPOSITION'):
                            try:
                                account.balance = Decimal(FrenchTransaction.clean_amount(balance))
                            except InvalidOperation:
                                raise BrokenPageError('Unable to parse balance %r' % balance)
                            account.currency = account.get_currency(balance)
                        else:
                            account.balance = NotAvailable

            if not account.label or empty(account.balance):
                continue

            if 'CARTE_' in account._link_id:
                ac = accounts[0]
                ac._card_links.append(account._link_id)
                if not ac.coming:
                    ac.coming = Decimal('0.0')
                ac.coming += account.balance
            else:
                account._card_links = []
                accounts.append(account)
        return iter(accounts)