Beispiel #1
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
Beispiel #2
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
Beispiel #3
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.balance = Decimal("".join(tmp_balance.replace(".", "").replace(",", ".").split()))
            self.account_list.append(account)
Beispiel #4
0
    def get_cards(self, account_id):
        divs = self.doc.xpath('//div[@class="content-boxed"]')
        assert len(divs)
        msgs = re.compile(u'Vous avez fait opposition sur cette carte bancaire.' +
                           '|Votre carte bancaire a été envoyée.' +
                           '|BforBank a fait opposition sur votre carte' +
                           '|Pour des raisons de sécurité, la demande de réception du code confidentiel de votre carte par SMS est indisponible')
        divs = [d for d in divs if not msgs.search(CleanText('.//div[has-class("alert")]', default='')(d))]
        divs = [d.xpath('.//div[@class="m-card-infos"]')[0] for d in divs]
        divs = [d for d in divs if not d.xpath('.//div[@class="m-card-infos-body-text"][text()="Débit immédiat"]')]

        if not len(divs):
            self.logger.warning('all cards are cancelled, acting as if there is no card')
            return []

        cards = []
        for div in divs:
            label = CleanText('.//div[@class="m-card-infos-body-title"]')(div)
            number = CleanText('.//div[@class="m-card-infos-body-num"]', default='')(div)
            number = re.sub('[^\d*]', '', number).replace('*', 'x')
            debit = CleanText(u'.//div[@class="m-card-infos-body-text"][contains(text(),"Débit")]')(div)
            assert debit == u'Débit différé', 'unrecognized card type %s: %s' % (number, debit)

            card = Account()
            card.id = '%s.%s' % (account_id, number)
            card.label = label
            card.number = number
            card.type = Account.TYPE_CARD
            cards.append(card)

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

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

            tds = tr.findall('td')

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

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

            accounts.append(account)

        return accounts
Beispiel #6
0
    def get_accounts_list(self):

        #Parse CCP
        compte_table = self.document.xpath("//table[@id='comptes']", smart_strings=False)[0]
        compte_ligne = compte_table.xpath("./tbody/tr")

        for compte in compte_ligne:
            account = Account()
            tp = compte.xpath("./td/a")[0]
            account.label = tp.text
            account.link_id = tp.get("href")
            account.id = compte.xpath("./td")[1].text
            account.balance = float(''.join( compte.xpath("./td/span")[0].text.replace('.','').replace(',','.').split() ))
            self.Account_List.append(account)

        #Parse epargne
        epargne_table = self.document.xpath("//table[@id='comptesEpargne']", smart_strings=False)[0]
        epargne_ligne = epargne_table.xpath("./tbody/tr")

        for epargne in epargne_ligne:
            account = Account()
            tp = epargne.xpath("./td/a")[0]
            account.label = tp.text
            account.link_id = tp.get("href")
            account.id = epargne.xpath("./td")[1].text
            account.balance = float(''.join( epargne.xpath("./td/span")[0].text.replace('.','').replace(',','.').split() ) )
            self.Account_List.append(account)

        return self.Account_List
Beispiel #7
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
Beispiel #8
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
Beispiel #9
0
 def get_list(self):
     for line in self.document.xpath('//li[@id="menu-n2-mesproduits"]//li//a'):
         if line.get('onclick') is None:
             continue
         account = Account()
         account.id = line.get('onclick').split("'")[1]
         account.label = self.parser.tocleanstring(line)
         yield account
Beispiel #10
0
 def get_accounts_list(self):
     self.location('%s://%s/summarySearch.do?reqCode=search' % (self.PROTOCOL, self.DOMAIN))
     account = Account()
     account.id = u'1'
     account.currency = 'EUR'
     account.balance = self.page.get_balance()
     account.label = u'Synthèse financière'
     return [account]
Beispiel #11
0
 def get_accounts_list(self):
     self.location("%s://%s/summarySearch.do?reqCode=search" % (self.PROTOCOL, self.DOMAIN))
     account = Account()
     account.id = u"1"
     account.currency = Account.CUR_EUR
     account.balance = self.page.get_balance()
     account.label = u"Synthèse financière"
     return [account]
Beispiel #12
0
 def get_accounts_list(self):
     balance = self.index.stay_or_go().get_balance()
     account = Account()
     account.id = self.username
     account.label = u'Carte Oney'
     account.balance = balance
     account.currency = u'EUR'
     return [account]
Beispiel #13
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
Beispiel #14
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
Beispiel #15
0
    def get_list(self):
        l = []

        for cpt in self.document.xpath(".//*[@class='synthese_id_compte']"):
            account = Account()

            # account.id
            account.id = (
                cpt.xpath("./span[1]/text()")[0]
                .replace(u"\xa0", "")
                .replace(",", ".")
                .replace("EUR", "")
                .replace("\n", "")
                .replace("\t", "")
                .replace(u"\xb0", "")
                .replace(" ", "")
                .replace("N", "")
            )

            # account balance
            account.balance = Decimal(
                cpt.xpath("./span[2]/text()")[0]
                .replace("+", "")
                .replace(u"\xa0", "")
                .replace(",", ".")
                .replace("EUR", "")
                .replace("\n", "")
                .replace("\t", "")
                .replace(" ", "")
            )

            # account coming TODO
            # mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]/a[@class='lien_synthese_encours']/span/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "")
            # mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]")[0]
            # mycomingval = cpt.xpath("./../../../a[@class='lien_synthese_encours']/span[@class='synthese_encours']/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "")

            # if mycomingval == '-':
            #    account.coming = Decimal(0)
            # else:
            #    account.coming = Decimal(mycomingval)

            # account._link_id
            url_to_parse = cpt.xpath("@href")[0].replace("\n", "")  # link
            compte_id_re = re.compile(r"/prive/mes-comptes/([^/]+/).*COMPTE_ACTIF=([^\&]+)\&?")
            account._link_id = "/fr/prive/mes-comptes/%sconsulter-situation/consulter-solde.jsp?COMPTE_ACTIF=%s" % (
                compte_id_re.search(url_to_parse).groups()[0],
                compte_id_re.search(url_to_parse).groups()[1],
            )

            # account.label
            temp_label = cpt.xpath("./text()")[1].replace(u"-\xa0", "").replace("\n", "").replace("\t", "")
            account.label = " ".join(temp_label.split(" ")[:2])

            l.append(account)

        return l
Beispiel #16
0
    def _parse_account(self, tr):
        account = Account()

        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.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
Beispiel #17
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
Beispiel #18
0
    def get_list(self):
        account_type = Account.TYPE_UNKNOWN

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

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

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

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

            self.set_link(account, cols)

            account._perimeter = self.browser.current_perimeter
            yield account
Beispiel #19
0
    def get_list(self):
        for tr in self.document.xpath('//table[@class="ca-table"]/tr'):
            if not tr.attrib.get('class', '').startswith('colcelligne'):
                continue

            cols = tr.findall('td')
            if not cols:
                continue

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

            a = cols[0].find('a')
            if a is not None:
                account._link = a.attrib['href'].replace(' ', '%20')

            yield account
Beispiel #20
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()
Beispiel #21
0
    def get_account(self):
        if not self.is_on_page(IndexPage):
            self.home()

        account = Account()
        account.id = '0'
        account.label = self.page.get_card_name()

        self.location('/site/s/detailcompte/ongletdetailcompte.html')
        account.balance = self.page.get_balance()

        return account
Beispiel #22
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)
Beispiel #23
0
    def get_list(self):
        """
            Returns the list of available bank accounts
        """
        l = []

        for div in self.document.getiterator('div'):
            if div.attrib.get('class', '') == 'dv' and div.getchildren()[0].tag in ('a', 'br'):
                account = Account()
                if div.getchildren()[0].tag == 'a':
                    # This is at least present on CA Nord-Est
                    account.label = ' '.join(div.find('a').text.split()[:-1])
                    account.link_id = div.find('a').get('href', '')
                    account.id = div.find('a').text.split()[-1]
                    s = div.find('div').find('b').find('span').text
                else:
                    # This is at least present on CA Toulouse
                    account.label = div.find('a').text.strip()
                    account.link_id = div.find('a').get('href', '')
                    account.id = div.findall('br')[1].tail.strip()
                    s = div.find('div').find('span').find('b').text
                balance = u''
                for c in s:
                    if c.isdigit():
                        balance += c
                    if c == ',':
                        balance += '.'
                account.balance = float(balance)
                l.append(account)
        return l
Beispiel #24
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
Beispiel #25
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
Beispiel #26
0
    def get_list(self):
        accounts = []

        for tr in self.document.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(txt.strip(' EUR').replace(' ', '').replace(',', '.')) for txt in cols[-1].itertext() if len(txt.strip()) > 0])
            except InvalidOperation:
                continue

            a = cols[0].find('a')
            if a is None:
                # this line is a cards line. attach it on the first account.
                if len(accounts) == 0:
                    self.logger.warning('There is a card link but no accounts!')
                    continue

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

                    accounts[0]._card_links.append('%s.%s' % (args['numero_compte'], args['numero_poste']))
                    if not accounts[0].coming:
                        accounts[0].coming = Decimal('0.0')
                    accounts[0].coming += amount
                continue

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

            if not 'numero_compte' in args or not 'numero_poste' 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._card_links = []
            accounts.append(account)

        return accounts
Beispiel #27
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()
Beispiel #28
0
    def iter_accounts(self):
        if not self.islogged:
            self.login()

        data = self.browser.open("https://www.cmb.fr/domiweb/prive/particulier/releve/0-releve.act").content
        parser = etree.HTMLParser()
        tree = etree.parse(StringIO(data), parser)

        table = tree.xpath('/html/body/table')
        if len(table) == 0:
            title = tree.xpath('/html/head/title')[0].text
            if title == u"Utilisateur non identifié":
                self.login()
                data = self.browser.open("https://www.cmb.fr/domiweb/prive/particulier/releve/0-releve.act").content

                parser = etree.HTMLParser()
                tree = etree.parse(StringIO(data), parser)
                table = tree.xpath('/html/body/table')
                if len(table) == 0:
                    raise ParseError()
            else:
                raise ParseError()

        for tr in tree.xpath('/html/body//table[contains(@class, "Tb")]/tr'):
            if tr.get('class', None) not in ('LnTit', 'LnTot', 'LnMnTiers', None):
                account = Account()
                td = tr.xpath('td')

                a = td[1].xpath('a')
                account.label = unicode(a[0].text).strip()
                href = a[0].get('href')
                m = match(r"javascript:releve\((.*),'(.*)','(.*)'\)",
                             href)
                if not m:
                    continue
                account.id = unicode(m.group(1) + m.group(2) + m.group(3))
                account._cmbvaleur = m.group(1)
                account._cmbvaleur2 = m.group(2)
                account._cmbtype = m.group(3)

                balance = u''.join([txt.strip() for txt in td[2].itertext()])
                balance = balance.replace(',', '.').replace(u"\xa0", '')
                account.balance = Decimal(balance)

                span = td[4].xpath('a/span')
                if len(span):
                    coming = span[0].text.replace(' ', '').replace(',', '.')
                    coming = coming.replace(u"\xa0", '')
                    account.coming = Decimal(coming)
                else:
                    account.coming = NotAvailable

                yield account
Beispiel #29
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
Beispiel #30
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
Beispiel #31
0
    def get_loans_list(self):
        r = self.api_open('/transactionnel/services/applications/prets/liste')

        if 'content' in r.json():
            for content in r.json()['content']:
                a = Account()
                a.id = "%s.%s" % (content['comptePrets'].strip(),
                                  content['numeroDossier'].strip())
                a.type = Account.TYPE_LOAN
                a.label = ' '.join([
                    content['intitule'].strip(),
                    content['libellePrets'].strip()
                ])
                a.balance = -Decimal(str(
                    content['montantCapitalDu']['valeur']))
                a.currency = content['montantCapitalDu']['monnaie'][
                    'code'].strip()
                yield a
Beispiel #32
0
 def get_list(self):
     ids = set()
     for td in self.document.xpath('.//td[@nowrap="nowrap"]'):
         account = Account()
         link = td.xpath('.//a')[0]
         account._index = int(re.search('\d', link.attrib['href']).group(0))
         if not account._index in ids:
             ids.add(account._index)
             account.id = unicode(link.text.strip())
             account.label = account.id
             urltofind = './/a[@href="' + link.attrib['href'] + '"]'
             linkbis = self.document.xpath(urltofind).pop()
             if linkbis.text == link.text:
                 linkbis = self.document.xpath(urltofind)[1]
             account.balance = Decimal(linkbis.text.replace('.', '').\
                                       replace(' ', '').replace(',', '.'))
             account.coming = NotAvailable
             yield account
Beispiel #33
0
 def iter_accounts(self, ibans):
     for f in self.path('data.infoUdc.familleCompte.*'):
         for a in f.get('compte'):
             yield Account.from_dict({
                 'id':
                 a.get('key'),
                 'label':
                 a.get('libellePersoProduit') or a.get('libelleProduit'),
                 'currency':
                 a.get('devise'),
                 'type':
                 self.FAMILY_TO_TYPE.get(f.get('idFamilleCompte'))
                 or Account.TYPE_UNKNOWN,
                 'balance':
                 a.get('soldeDispo'),
                 'coming':
                 a.get('soldeAVenir'),
                 'iban':
                 ibans.get(a.get('key'))
             })
Beispiel #34
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')
                    account.label = unicode(a.find("span").text)
                    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':
                    balance = td.find('div').text
                    if balance != None:
                        balance = balance.replace(u'\xa0','').replace(',','.')
                        account.balance = Decimal(balance)
                    else:
                        account.balance = Decimal(0)

            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)
Beispiel #35
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.strip(' EUR'))
                    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 = []

                account.balance = balance

                accounts[account.id] = account

        return accounts.itervalues()
Beispiel #36
0
    def parse(self):
        for tr in self.document.xpath('//tbody/tr'):
            tlink = tr.xpath('./td[@class="desc"]/a[@class="rowClick"]')[0].attrib['href'].strip()
            t = FrenchTransaction(tlink[tlink.find('&id=')+4:])
            date = parse_french_date(tr.xpath('./td[@class="date"]')[0].text.strip())
            raw = tr.xpath('./td[@class="desc"]/a[@class="rowClick"]')[0].tail.strip()
            # Filter lines that do not actually modify the balance
            if raw.startswith('Autorisation ') or raw.endswith(' en attente  par PayPal'):
                continue
            t.parse(date=date, raw=raw)

            amount = tr.xpath('./td[@class="price-value net"]')[0].text.strip()
            t.set_amount(amount)
            commission = tr.xpath('./td[@class="price-value fee"]')[0].text.strip()
            t.commission = Decimal(t.clean_amount(commission))
            t.label = t.raw
            if t.commission:
                t.label += " (%s)" % tr.xpath('./td[@class="price-value gross"]')[0].text.strip()

            t._currency = Account.get_currency(amount)
            yield t
Beispiel #37
0
    def get_accounts(self):
        accounts = {}
        content = self.document.xpath('//div[@id="moneyPage"]')[0]

        # Primary currency account
        primary_account = Account()
        primary_account.type = Account.TYPE_CHECKING
        balance = self.parser.tocleanstring(
            content.xpath(
                '//div[contains(@class, "col-md-6")][contains(@class, "available")]'
            )[0])
        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
Beispiel #38
0
 def iter_accounts(self):
     for f in self.path('tableauSoldes.listeGroupes'):
         for g in f:
             for a in g.get('listeComptes'):
                 yield Account.from_dict({
                     'id':
                     a.get('numeroCompte'),
                     'iban':
                     a.get('numeroCompte'),
                     'type':
                     self.FAMILY_TO_TYPE.get(a.get('libelleType'))
                     or Account.TYPE_UNKNOWN,
                     'label':
                     '%s %s' %
                     (a.get('libelleType'), a.get('libelleTitulaire')),
                     'currency':
                     a.get('deviseTenue'),
                     'balance':
                     Decimal(a.get('soldeComptable')) / 100,
                     'coming':
                     Decimal(a.get('soldePrevisionnel')) / 100,
                 })
Beispiel #39
0
    def get_accounts_list(self):
        data = {
            'clang': self.LANG,
            'ctcc': self.CTCC,
            'login': self.username,
            'session': self.sessionId
        }

        for dispositif in self.accountsp.go(data=data).get_list():
            if dispositif['montantBrutDispositif'] == 0:
                continue

            a = Account()
            a.id = dispositif['codeDispositif']
            a.type = Account.TYPE_MARKET
            a.balance = Decimal(dispositif["montantBrutDispositif"]).quantize(
                Decimal('.01'))
            a.label = dispositif['titreDispositif']
            a.currency = u"EUR"  # Don't find any possbility to get that from configuration.
            a._investments = []
            for fund in dispositif['listeFonds']:
                if fund['montantValeurEuro'] == 0:
                    continue

                i = Investment()
                i.id = i.code = dispositif['codeEntreprise'] + dispositif[
                    "codeDispositif"] + fund["codeSupport"]
                i.label = fund['libelleSupport']
                i.unitvalue = Decimal(fund["montantValeur"]).quantize(
                    Decimal('.01'))
                i.valuation = Decimal(fund["montantValeurEuro"]).quantize(
                    Decimal('.01'))
                i.quantity = i.valuation / i.unitvalue
                i.vdate = parse_date(fund['dateValeur'], dayfirst=True)
                a._investments.append(i)
            yield a
Beispiel #40
0
 def populate(self, accounts):
     cards = []
     for account in accounts:
         for li in self.doc.xpath('//li[@class="nav-category"]'):
             title = CleanText().filter(li.xpath('./h3'))
             for a in li.xpath('./ul/li//a'):
                 label = CleanText().filter(
                     a.xpath('.//span[@class="nav-category__name"]'))
                 balance_el = a.xpath(
                     './/span[@class="nav-category__value"]')
                 balance = CleanDecimal(
                     replace_dots=True,
                     default=NotAvailable).filter(balance_el)
                 if 'CARTE' in label and balance:
                     acc = Account()
                     acc.balance = balance
                     acc.label = label
                     acc.currency = FrenchTransaction.Currency().filter(
                         balance_el)
                     acc._link = Link().filter(a.xpath('.'))
                     acc._history_page = acc._link
                     acc.id = acc._webid = Regexp(
                         pattern='carte/(.*)$').filter(Link().filter(
                             a.xpath('.')))
                     acc.type = Account.TYPE_CARD
                     if not acc in cards:
                         cards.append(acc)
                 elif account.label == label and account.balance == balance:
                     if not account.type:
                         account.type = AccountsPage.ACCOUNT_TYPES.get(
                             title, Account.TYPE_UNKNOWN)
                     account._webid = Attr(
                         None, 'data-account-label').filter(
                             a.xpath(
                                 './/span[@class="nav-category__name"]'))
     accounts.extend(cards)
Beispiel #41
0
    def get_list(self):
        l = []

        for cpt in self.document.xpath(".//*[@class='synthese_id_compte']"):
            account = Account()

            # account.id
            account.id = cpt.xpath("./span[1]/text()")[0].replace(
                u"\xa0", "").replace(',', '.').replace("EUR", "").replace(
                    "\n",
                    "").replace("\t",
                                "").replace(u"\xb0",
                                            '').replace(" ",
                                                        "").replace('N', '')

            # account balance
            account.balance = Decimal(
                cpt.xpath("./span[2]/text()")[0].replace("+", "").replace(
                    u"\xa0", "").replace(',', '.').replace("EUR", "").replace(
                        "\n", "").replace("\t", "").replace(" ", ""))

            # account coming TODO
            #mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]/a[@class='lien_synthese_encours']/span/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "")
            #mycomingval = cpt.xpath("../../following-sibling::*[1]/td[2]")[0]
            #mycomingval = cpt.xpath("./../../../a[@class='lien_synthese_encours']/span[@class='synthese_encours']/text()")[0].replace(',', '.').replace("EUR", "").replace("\n", "").replace("\t", "").replace(u"\xa0", "")

            #if mycomingval == '-':
            #    account.coming = Decimal(0)
            #else:
            #    account.coming = Decimal(mycomingval)

            # account._link_id
            url_to_parse = cpt.xpath('@href')[0].replace("\n", "")  # link
            compte_id_re = re.compile(
                r'/prive/mes-comptes/([^/]+/).*COMPTE_ACTIF=([^\&]+)\&?')
            account._link_id = '/fr/prive/mes-comptes/%sconsulter-situation/consulter-solde.jsp?COMPTE_ACTIF=%s' % \
                    (compte_id_re.search(url_to_parse).groups()[0], compte_id_re.search(url_to_parse).groups()[1])

            # account.label
            temp_label = cpt.xpath('./text()')[1].replace(
                u'-\xa0', '').replace("\n", "").replace("\t", "")
            account.label = " ".join(temp_label.split(" ")[:2])

            l.append(account)

        return l
Beispiel #42
0
 def add_por_accounts(self, accounts):
     for ele in self.doc.xpath(
             '//select[contains(@name, "POR_Synthese")]/option'):
         for a in accounts:
             if a.id.startswith(ele.attrib['value']):
                 a._is_inv = True
                 a.type = Account.TYPE_MARKET
                 self.fill(a)
                 break
         else:
             acc = Account()
             acc.id = ele.attrib['value']
             if acc.id == '9999':
                 # fake account
                 continue
             acc.label = unicode(re.sub("\d", '', ele.text).strip())
             acc._link_id = None
             acc.type = Account.TYPE_MARKET
             acc._is_inv = True
             self.fill(acc)
             accounts.append(acc)
Beispiel #43
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:
                        self.env['raw'] = "%s" % (CleanText().filter(
                            TableCell('commerce')(self)[0].text))

                    self.env['amount'] = CleanDecimal(
                        replace_dots=True).filter(
                            TableCell('credit')(self)[0].text)
                    original_amount = TableCell('credit')(self)[0].xpath(
                        './span')[0].text
                    if original_amount:
                        self.env['original_amount'] = CleanDecimal(
                            replace_dots=True).filter(original_amount)
                        self.env['original_currency'] = Account.get_currency(
                            original_amount[1:-1])
                    else:
                        self.env['original_amount'] = NotAvailable
                        self.env['original_currency'] = NotAvailable
Beispiel #44
0
    def get_cards(self, account_id):
        divs = self.doc.xpath('//div[@class="content-boxed"]')
        msgs = re.compile(
            'Vous avez fait opposition sur cette carte bancaire.' +
            '|Votre carte bancaire a été envoyée.' +
            '|Carte bancaire commandée.' +
            '|BforBank a fait opposition sur votre carte' +
            '|Pour des raisons de sécurité, la demande de réception du code confidentiel de votre carte par SMS est indisponible'
        )
        divs = [
            d for d in divs if not msgs.search(
                CleanText('.//div[has-class("alert")]', default='')(d))
        ]
        divs = [d.xpath('.//div[@class="m-card-infos"]')[0] for d in divs]
        divs = [
            d for d in divs if not d.xpath(
                './/div[@class="m-card-infos-body-text"][text()="Débit immédiat"]'
            )
        ]

        if not len(divs):
            self.logger.warning(
                'all cards are cancelled, acting as if there is no card')
            return []

        cards = []
        for div in divs:
            label = CleanText('.//div[@class="m-card-infos-body-title"]')(div)
            number = CleanText('.//div[@class="m-card-infos-body-num"]',
                               default='')(div)
            number = re.sub('[^\d*]', '', number).replace('*', 'x')
            debit = CleanText(
                u'.//div[@class="m-card-infos-body-text"][contains(text(),"Débit")]'
            )(div)
            assert debit == u'Débit différé', 'unrecognized card type %s: %s' % (
                number, debit)

            card = Account()
            card.id = '%s.%s' % (account_id, number)
            card.label = label
            card.number = number
            card.type = Account.TYPE_CARD
            cards.append(card)

        return cards
Beispiel #45
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.doc\
                                        .xpath('//table[@id="TabFact"]/thead//th')[self.COL_CARD_AMOUNT]\
                                        .text\
                                        .replace('(', ' ')\
                                        .replace(')', ' '))
        for i, tr in enumerate(
                self.doc.xpath('//table[@id="TabFact"]/tbody/tr')):
            tds = tr.findall('td')

            if len(tds) < 3:
                continue

            t = Transaction()

            cleaner = CleanText(None).filter
            date = cleaner(tds[self.COL_CARD_DATE])
            label = cleaner(tds[self.COL_CARD_LABEL])
            amount = '-' + cleaner(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
Beispiel #46
0
    def get_card(self, account_id):
        divs = self.doc.xpath('//div[@class="content-boxed"]')
        assert len(divs)

        msgs = re.compile(
            u'Vous avez fait opposition sur cette carte bancaire.|Votre carte bancaire a été envoyée.'
        )
        divs = [
            d for d in divs if not msgs.search(
                CleanText('.//div[has-class("alert")]', default='')(d))
        ]
        divs = [d.xpath('.//div[@class="m-card-infos"]')[0] for d in divs]

        if not len(divs):
            self.logger.warning(
                'all cards are cancelled, acting as if there is no card')
            return

        cards = []
        for div in divs:
            label = CleanText('.//div[@class="m-card-infos-body-title"]')(div)
            number = CleanText('.//div[@class="m-card-infos-body-num"]',
                               default='')(div)
            number = re.sub('[^\d*]', '', number).replace('*', 'x')
            debit = CleanText(
                u'.//div[@class="m-card-infos-body-text"][contains(text(),"Débit")]'
            )(div)
            if debit == u'Débit immédiat':
                self.logger.debug('immediate debit card %s', number)
                continue
            assert debit == u'Débit différé', 'unrecognized card type %s: %s' % (
                number, debit)

            card = Account()
            card.id = '%s.%s' % (account_id, number)
            card.label = label
            card.number = number
            card.type = Account.TYPE_CARD
            cards.append(card)

        # Crash on multiple cards if at least one is deferred
        assert (len(divs) > 1 and not cards) or len(divs) == 1
        return cards[0] if cards else None
Beispiel #47
0
    def iter_accounts(self):
        for line in self.doc.xpath(
                '//script[@id="initial-state"]')[0].text.split('\n'):
            m = re.search('window.__INITIAL_STATE__ = (.*);', line)
            if m:
                data = list(flatten(json.loads(literal_eval(m.group(1)))))
                break
        else:
            assert False, "data was not found"

        assert data.count(
            'display_account_number') == 1, 'there should be exactly one card'

        acc = Account()
        acc.id = 'XXX-%s' % data[1 + data.index('display_account_number')]
        acc.label = '%s %s' % (data[1 + data.index('description')],
                               data[1 + data.index('embossed_name')])
        acc._index = data[1 + data.index('sorted_index')]
        acc._token = data[1 + data.index('account_token')]
        yield acc
Beispiel #48
0
    def get_list(self):
        for table in self.document.xpath('//table[@cellpadding="1"]'):
            account_type = Account.TYPE_UNKNOWN
            for tr in table.xpath('./tr'):
                tds = tr.findall('td')
                if tr.attrib.get('class', '') == 'DataGridHeader':
                    account_type = self.ACCOUNT_TYPES.get(tds[1].text.strip(), Account.TYPE_UNKNOWN)
                else:
                    a = tds[1].find('a')
                    m = re.match("^javascript:__doPostBack\('.*','HISTORIQUE_COMPTE&(\d+)'\)", a.attrib.get('href', ''))

                    if not m:
                        self.logger.warning('Unable to parse account %s' % (a.text.strip() if a.text is not None else ''))
                        continue

                    account = Account()
                    account.id = m.group(1)
                    account.label = unicode(a.text.strip())
                    account.type = account_type
                    amount = u''.join([txt.strip() for txt in tds[-1].itertext()])
                    account.balance = Decimal(FrenchTransaction.clean_amount(amount.rstrip(' EUR')))
                    yield account
Beispiel #49
0
    def get_list(self):
        accounts = []

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            if (account.label, account.id, account.balance) not in [
                (a.label, a.id, a.balance) for a in accounts
            ]:
                accounts.append(account)
        return accounts
Beispiel #50
0
    def get_list(self):
        for table in self.has_accounts():
            tds = table.xpath('./tbody/tr')[0].findall('td')
            if len(tds) < 3:
                if tds[0].text_content() == u'Pr\xeat Personnel':

                    account = Account()
                    args = self.js2args(table.xpath('.//a')[0].attrib['onclick'])
                    account._args = args
                    account.label = CleanText().filter(tds[0].xpath('./ancestor::table[has-class("tableaux-pret-personnel")]/caption'))
                    account.id = account.label.split()[-1] + args['paramNumContrat']
                    loan_details = self.browser.open('/webapp/axabanque/jsp/panorama.faces', data=args).page
                    # Need to go back on home page after open
                    self.browser.bank_accounts.open()
                    account.balance = loan_details.get_loan_balance()
                    account.currency = loan_details.get_loan_currency()
                    # Skip loans without any balance (already fully reimbursed)
                    if empty(account.balance):
                        continue
                    account.type = Account.TYPE_LOAN
                    account._acctype = "bank"
                    account._hasinv = False
                    account._is_debit_card = False
                    yield account

                continue

            boxes = table.xpath('./tbody//tr[not(.//strong[contains(text(), "Total")])]')
            foot = table.xpath('./tfoot//tr')

            for box in boxes:
                account = Account()
                account._url = None

                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:
                    #The displaying of life insurances is very different from the other
                    if args.get('idPanorama:_idcl').split(":")[1] == 'tableaux-direct-solution-vie':
                        account_details = self.browser.open("#", data=args)
                        scripts = account_details.page.doc.xpath('//script[@type="text/javascript"]/text()')
                        script = filter(lambda x: "src" in x, scripts)[0]
                        iframe_url = re.search("src:(.*),", script).group()[6:-2]
                        account_details_iframe = self.browser.open(iframe_url, data=args)
                        account.id = CleanText('//span[contains(@id,"NumeroContrat")]/text()')(account_details_iframe.page.doc)
                        account._url = iframe_url
                        account.type = account.TYPE_LIFE_INSURANCE
                        account.balance = MyDecimal('//span[contains(@id,"MontantEpargne")]/text()')(account_details_iframe.page.doc)
                        account._acctype = "bank"
                        account._is_debit_card = False
                    else:
                        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

                if account.type != account.TYPE_LIFE_INSURANCE:
                    # get accounts type
                    account_type_str = ''
                    for l in table.attrib['class'].split(' '):
                        if 'tableaux-comptes-' in l:
                            account_type_str = l[len('tableaux-comptes-'):].lower()
                            break

                    account.type = Account.TYPE_UNKNOWN
                    for pattern, type in self.ACCOUNT_TYPES.items():
                        if pattern in account_type_str or pattern in account.label.lower():
                            account.type = type
                            break

                    # get accounts id
                    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 u'Valorisation' in account.label or u'Liquidités' in account.label:
                            account.id += args[next(k for k in args.keys() if "_idcl" in k)].split('Jsp')[-1]
                    except KeyError:
                        account.id = args['paramNumCompte']

                    # get accounts balance
                    try:
                        balance_value = CleanText('.//td[has-class("montant")]')(box)

                        # skip debit card
                        # some cards don't have information in balance tab, skip them
                        if balance_value == u'Débit immédiat' or balance_value == '':
                            account._is_debit_card = True
                        else:
                            account._is_debit_card = False

                        account.balance = Decimal(FrenchTransaction.clean_amount(self.parse_number(balance_value)))
                        if account.type == Account.TYPE_CARD:
                            account.coming = account.balance
                            account.balance = Decimal(0)

                    except InvalidOperation:
                        #The account doesn't have a amount
                        pass

                    account._url = self.doc.xpath('//form[contains(@action, "panorama")]/@action')[0]
                    account._acctype = "bank"

                # get accounts currency
                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))

                account._args = args
                account._hasinv = True if "Valorisation" in account.label else False

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

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

            yield a
Beispiel #53
0
 def account(self):
     detact = self.doc['accountDetailsAndActivity']
     details = detact['accountDetails']
     account = Account()
     account.type = Account.TYPE_CARD
     account.label = re.sub(r'<[^>]+>', '', detact['accountName'])
     account.id = account.label[-4:]
     for bal in details['accountBalances']:
         label, value = bal['label'], (bal['value'] or ['0'])[0]
         if label == u'Current Balance:':
             account.currency = Account.get_currency(value)
             account.balance = -AmTr.decimal_amount(value)
         elif label == u'Total Revolving Credit Line:':
             account.cardlimit = AmTr.decimal_amount(value)
         elif label.startswith(u'Minimum Payment Due'):
             d = re.match(r'.*(..-..-....):$', label).group(1)
             account.paydate = datetime.strptime(d, '%m-%d-%Y')
             account.paymin = AmTr.decimal_amount(value)
     return account
Beispiel #54
0
    def iter_accounts(self, next_pages):
        params = self.get_params()

        account = None
        currency = None
        for th in self.document.xpath('//table[@id="TabCtes"]//thead//th'):
            m = re.match('.*\((\w+)\)$', th.text)
            if m and currency is None:
                currency = Account.get_currency(m.group(1))

        for tr in self.document.xpath('//table[@id="TabCtes"]/tbody/tr'):
            cols = tr.xpath('./td')

            id = self.parser.tocleanstring(cols[self.COL_ID])
            if len(id) > 0:
                if account is not None:
                    yield account
                account = Account()
                account.id = id.replace(' ', '')
                account.type = Account.TYPE_CARD
                account.balance = account.coming = Decimal('0')
                account._next_debit = datetime.date.today()
                account._prev_debit = datetime.date(2000, 1, 1)
                account.label = u' '.join([
                    self.parser.tocleanstring(cols[self.COL_TYPE]),
                    self.parser.tocleanstring(cols[self.COL_LABEL])
                ])
                account.currency = currency
                account._params = None
                account._invest_params = None
                account._coming_params = params.copy()
                account._coming_params[
                    'dialogActionPerformed'] = 'SELECTION_ENCOURS_CARTE'
                account._coming_params[
                    'attribute($SEL_$%s)' %
                    tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split(
                        '_', 1)[1]
            elif account is None:
                raise BrokenPageError('Unable to find accounts on cards page')
            else:
                account._params = params.copy()
                account._params[
                    'dialogActionPerformed'] = 'SELECTION_ENCOURS_CARTE'
                account._params[
                    'attribute($SEL_$%s)' %
                    tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split(
                        '_', 1)[1]

            date_col = self.parser.tocleanstring(cols[self.COL_DATE])
            m = re.search('(\d+)/(\d+)/(\d+)', date_col)
            if not m:
                self.logger.warning('Unable to parse date %r' % date_col)
                continue

            date = datetime.date(*reversed(map(int, m.groups())))
            if date.year < 100:
                date = date.replace(year=date.year + 2000)

            amount = Decimal(
                FrenchTransaction.clean_amount(
                    self.parser.tocleanstring(cols[self.COL_AMOUNT])))

            if not date_col.endswith('(1)'):
                # debited
                account.coming += -abs(amount)
                account._next_debit = date
            elif date > account._prev_debit:
                account._prev_balance = -abs(amount)
                account._prev_debit = date

        if account is not None:
            yield account

        # Needed to preserve navigation.
        btn = self.document.xpath('.//button/span[text()="Retour"]')
        if len(btn) > 0:
            btn = btn[0].getparent()
            actions = self.get_button_actions()
            _params = params.copy()
            _params.update(actions[btn.attrib['id']])
            self.browser.openurl('/cyber/internet/ContinueTask.do',
                                 urllib.urlencode(_params))
Beispiel #55
0
 def filter(self, text):
     text = super(FrenchTransaction.Currency, self).filter(text)
     return Account.get_currency(text)
Beispiel #56
0
    def iter_accounts(self, next_pages):
        account_type = Account.TYPE_UNKNOWN

        params = self.get_params()
        actions = self.get_button_actions()

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

            if account_type is None:
                # ignore services accounts
                self.logger.debug('Ignore account type %s', div.text.strip())
                continue

            # Go to the full list of this kind of account, if any.
            btn = div.getparent().xpath('.//button/span[text()="Suite"]')
            if len(btn) > 0:
                btn = btn[0].getparent()
                _params = params.copy()
                _params.update(actions[btn.attrib['id']])
                next_pages.append(_params)
                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
                account._invest_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'

                    # If there is an action needed before going to the cards page, save it.
                    m = re.search('dialogActionPerformed=([\w_]+)', self.url)
                    if m and m.group(1) != 'EQUIPEMENT_COMPLET':
                        _params['prevAction'] = m.group(1)
                    next_pages.append(_params)

                if not account._params:
                    account._invest_params = params.copy()
                    account._invest_params['dialogActionPerformed'] = 'CONTRAT'
                    account._invest_params[
                        'attribute($SEL_$%s)' %
                        tr.attrib['id'].split('_')[0]] = tr.attrib['id'].split(
                            '_', 1)[1]

                yield account

        # Needed to preserve navigation.
        btn = self.document.xpath('.//button/span[text()="Retour"]')
        if len(btn) > 0:
            btn = btn[0].getparent()
            _params = params.copy()
            _params.update(actions[btn.attrib['id']])
            self.browser.openurl('/cyber/internet/ContinueTask.do',
                                 urllib.urlencode(_params))
Beispiel #57
0
    def get_list(self):
        accounts = []

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

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

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

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

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

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

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

        cards_tables = self.document.xpath(TABLE_XPATH)

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

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

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

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

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

            cols = tr.findall('td')

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

            a._card_ids = []
            a._inv = False

            yield a
Beispiel #60
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