Ejemplo n.º 1
0
    def get_coming(self, account):
        if account.type != account.TYPE_CARD:
            return []

        trs = []

        if not hasattr(account.parent, '_info'):
            raise NotImplementedError()

        # We are on the old website
        if hasattr(account, '_coming_eventargument'):

            if not self.cards_old.is_here():
                self.home.go()
                self.page.go_list()
                self.page.go_cards()
            self.page.go_card_coming(account._coming_eventargument)

            return sorted_transactions(self.page.iter_coming())

        # We are on the new website.
        info = account.parent._card_links
        # if info is empty, that mean there are no coming yet
        if info:
            for tr in self._get_history(info.copy(), account):
                tr.type = tr.TYPE_DEFERRED_CARD
                trs.append(tr)

        return sorted_transactions(trs)
Ejemplo n.º 2
0
    def iter_history(self, account, coming=False):
        # The accounts from the "Assurances Vie" space have no available history:
        if hasattr(account, '_details'):
            return []
        if account.type == Account.TYPE_PEA and account.label.endswith(
                'Espèces'):
            return []
        if account.type == account.TYPE_LIFE_INSURANCE:
            return self.iter_lifeinsurance_history(account, coming)
        elif account.type in (account.TYPE_MARKET,
                              Account.TYPE_PEA) and not coming:
            try:
                self.market_list.go(json={}, method='POST')
            except ServerError:
                self.logger.warning("An Internal Server Error occurred")
                return iter([])
            for market_acc in self.page.get_list():
                if account.number[-4:] == market_acc['securityAccountNumber'][
                        -4:]:
                    self.page = self.market_history.go(
                        json={
                            "securityAccountNumber":
                            market_acc['securityAccountNumber'],
                        })
                    return self.page.iter_history()
            return iter([])
        else:
            if not self.card_to_transaction_type:
                self.list_detail_card.go()
                self.card_to_transaction_type = self.page.get_card_to_transaction_type(
                )
            data = {
                "ibanCrypte":
                account.id,
                "pastOrPending":
                1,
                "triAV":
                0,
                "startDate":
                (datetime.now() - relativedelta(years=1)).strftime('%d%m%Y'),
                "endDate":
                datetime.now().strftime('%d%m%Y')
            }
            try:
                self.history.go(json=data)
            except BrowserUnavailable:
                # old url is still used for certain connections bu we don't know which one is,
                # so the same HistoryPage is attained by the old url in another URL object
                data[1]['startDate'] = (
                    datetime.now() - relativedelta(years=3)).strftime('%d%m%Y')
                # old url authorizes up to 3 years of history
                self.history_old.go(data=data)

            if coming:
                return sorted_transactions(self.page.iter_coming())
            else:
                return sorted_transactions(self.page.iter_history())
Ejemplo n.º 3
0
 def get_ti_transactions(self, account):
     self.ti_card_go()
     self.page.expand(account=account)
     for tr in sorted_transactions(self.page.get_history()):
         yield tr
     self.ti_histo_go()
     self.page.expand(self.page.get_periods()[0], account=account)
     for period in self.page.get_periods():
         self.page.expand(period, account=account)
         for tr in sorted_transactions(self.page.get_history()):
             yield tr
Ejemplo n.º 4
0
 def get_ti_transactions(self, account):
     self.ti_card_go()
     self.page.expand(account=account)
     for tr in sorted_transactions(self.page.get_history()):
         yield tr
     self.ti_histo_go()
     self.page.expand(self.page.get_periods()[0], account=account)
     for period in self.page.get_periods():
         self.page.expand(period, account=account)
         for tr in sorted_transactions(self.page.get_history()):
             yield tr
Ejemplo n.º 5
0
    def iter_history(self, account, coming=False):
        # The accounts from the "Assurances Vie" space have no available history:
        if hasattr(account, '_details'):
            return []
        if account.type == Account.TYPE_PEA and account.label.endswith(
                'Espèces'):
            return []
        if account.type == account.TYPE_LIFE_INSURANCE:
            return self.iter_lifeinsurance_history(account, coming)
        elif account.type in (account.TYPE_MARKET,
                              Account.TYPE_PEA) and not coming:
            try:
                self.market_list.go(data=JSON({}))
            except ServerError:
                self.logger.warning("An Internal Server Error occurred")
                return iter([])
            for market_acc in self.page.get_list():
                if account.number[-4:] == market_acc['securityAccountNumber'][
                        -4:]:
                    self.page = self.market_history.go(data=JSON({
                        "securityAccountNumber":
                        market_acc['securityAccountNumber'],
                    }))
                    return self.page.iter_history()
            return iter([])
        else:
            if not self.card_to_transaction_type:
                self.list_detail_card.go()
                self.card_to_transaction_type = self.page.get_card_to_transaction_type(
                )

            self.history.go(data=JSON({
                "ibanCrypte":
                account.id,
                "pastOrPending":
                1,
                "triAV":
                0,
                "startDate": (datetime.now() -
                              relativedelta(years=2)).strftime('%d%m%Y'),
                "endDate":
                datetime.now().strftime('%d%m%Y')
            }))

            if coming:
                return sorted_transactions(self.page.iter_coming())
            else:
                return sorted_transactions(self.page.iter_history())
Ejemplo n.º 6
0
    def _iter_history_base(self, account):
        dformat = "%Y%m%d"

        # We ask for more 12 months by default, but it may not be supported for somme account types.
        # To avoid duplicated transactions we exit as soon a transaction is not within the expected timeframe
        for date in rrule(MONTHLY,
                          dtstart=(datetime.now() - relativedelta(months=11)),
                          until=datetime.now())[::-1]:

            params = dict(identifiant=account.iban,
                          type_solde='C',
                          type_releve='Previsionnel',
                          type_date='O',
                          date_min=(date + relativedelta(days=1) -
                                    relativedelta(months=1)).strftime(dformat),
                          date_max=date.strftime(dformat))

            self.account_history_view.go(**params)
            self.account_history.go(**params)

            for transaction in sorted_transactions(self.page.iter_history()):
                if transaction._coming:
                    self.logger.debug('skipping coming %r',
                                      transaction.to_dict())
                    continue

                if transaction.date > date:
                    self.logger.debug(
                        'transaction not within expected timeframe, stop iterating history: %r',
                        transaction.to_dict())
                    return

                yield transaction
Ejemplo n.º 7
0
    def get_history(self, account):
        self.location(account._history_link)
        if not account.type == Account.TYPE_LOAN:
            if self.page.select_period():
                return sorted_transactions(self.page.get_operations())

        return []
Ejemplo n.º 8
0
    def get_card_transactions(self, account, coming):
        self.location(account.url)
        if self.home.is_here():
            # for some cards, the site redirects us to '/'...
            return

        for t in self.page.iter_history(is_card=True):
            yield t

        # For card old history, the page doesn't show the real debit date,
        # so we need to parse a csv page
        if not coming:
            if self.deferred_card_calendar is None:
                self.location(self.page.get_calendar_link())
            params = {}
            params['movementSearch[toDate]'] = self.get_closing_date().strftime('%d/%m/%Y')
            params['movementSearch[fromDate]'] = (date.today() - relativedelta(years=3)).strftime('%d/%m/%Y')
            params['fullSearch'] = 1

            self.location(account.url, params=params)
            csv_link = self.page.get_csv_link()
            if csv_link:
                self.location(csv_link)
                for t in sorted_transactions(self.page.iter_history(account_number=account.number)):
                    yield t
        return
Ejemplo n.º 9
0
    def get_history(self, account, coming=False):
        if account.type is Account.TYPE_LOAN or not account._consultable:
            raise NotImplementedError()

        if account._univers != self.current_univers:
            self.move_to_univers(account._univers)

        today = date.today()
        seen = set()
        offset = 0
        next_page = True
        while next_page:
            operation_list = self._make_api_call(
                account=account,
                start_date=date(day=1, month=1, year=2000), end_date=date.today(),
                offset=offset, max_length=50,
            )
            transactions = []
            for op in reversed(operation_list):
                t = Transaction()
                t.id = op['id']
                if op['id'] in seen:
                    raise ParseError('There are several transactions with the same ID, probably an infinite loop')

                seen.add(t.id)
                d = date.fromtimestamp(op.get('dateDebit', op.get('dateOperation'))/1000)
                op['details'] = [re.sub('\s+', ' ', i).replace('\x00', '') for i in op['details'] if i]  # sometimes they put "null" elements...
                label = re.sub('\s+', ' ', op['libelle']).replace('\x00', '')
                raw = ' '.join([label] + op['details'])
                vdate = date.fromtimestamp(op.get('dateValeur', op.get('dateDebit', op.get('dateOperation')))/1000)
                t.parse(d, raw, vdate=vdate)
                t.amount = Decimal(str(op['montant']))
                t.rdate = date.fromtimestamp(op.get('dateOperation', op.get('dateDebit'))/1000)
                if 'categorie' in op:
                    t.category = op['categorie']
                t.label = label
                t._coming = op['intraday']
                if t._coming:
                    # coming transactions have a random uuid id (inconsistent between requests)
                    t.id = ''
                t._coming |= (t.date > today)

                if t.type == Transaction.TYPE_CARD and account.type == Account.TYPE_CARD:
                    t.type = Transaction.TYPE_DEFERRED_CARD

                transactions.append(t)

            # Transactions are unsorted
            for t in sorted_transactions(transactions):
                if coming == t._coming:
                    yield t
                elif coming and not t._coming:
                    # coming transactions are at the top of history
                    self.logger.debug('stopping coming after %s', t)
                    return

            next_page = bool(transactions)
            offset += 50

            assert offset < 30000, 'the site may be doing an infinite loop'
Ejemplo n.º 10
0
 def get_coming(self):
     transactions = list(
         self.groupamaes_page.go(
             page='&_pid=OperationsTraitees&_fid=GoWaitingOperations').
         get_history(date_guesser=LinearDateGuesser(), coming=True))
     transactions = sorted_transactions(transactions)
     return transactions
Ejemplo n.º 11
0
    def get_history(self, account, coming=False):
        if account.type is Account.TYPE_LOAN or not account._consultable:
            raise NotImplementedError()

        if account._univers != self.current_univers:
            self.move_to_univers(account._univers)

        today = date.today()
        seen = set()
        offset = 0
        next_page = True
        while next_page:
            operation_list = self._make_api_call(
                account=account,
                start_date=date(day=1, month=1, year=2000), end_date=date.today(),
                offset=offset, max_length=50,
            )
            transactions = []
            for op in reversed(operation_list):
                t = Transaction()
                t.id = op['id']
                if op['id'] in seen:
                    raise ParseError('There are several transactions with the same ID, probably an infinite loop')

                seen.add(t.id)
                d = date.fromtimestamp(op.get('dateDebit', op.get('dateOperation'))/1000)
                op['details'] = [re.sub('\s+', ' ', i).replace('\x00', '') for i in op['details'] if i]  # sometimes they put "null" elements...
                label = re.sub('\s+', ' ', op['libelle']).replace('\x00', '')
                raw = ' '.join([label] + op['details'])
                vdate = date.fromtimestamp(op.get('dateValeur', op.get('dateDebit', op.get('dateOperation')))/1000)
                t.parse(d, raw, vdate=vdate)
                t.amount = Decimal(str(op['montant']))
                t.rdate = date.fromtimestamp(op.get('dateOperation', op.get('dateDebit'))/1000)
                if 'categorie' in op:
                    t.category = op['categorie']
                t.label = label
                t._coming = op['intraday']
                if t._coming:
                    # coming transactions have a random uuid id (inconsistent between requests)
                    t.id = ''
                t._coming |= (t.date > today)

                if t.type == Transaction.TYPE_CARD and account.type == Account.TYPE_CARD:
                    t.type = Transaction.TYPE_DEFERRED_CARD

                transactions.append(t)

            # Transactions are unsorted
            for t in sorted_transactions(transactions):
                if coming == t._coming:
                    yield t
                elif coming and not t._coming:
                    # coming transactions are at the top of history
                    self.logger.debug('stopping coming after %s', t)
                    return

            next_page = bool(transactions)
            offset += 50

            assert offset < 30000, 'the site may be doing an infinite loop'
Ejemplo n.º 12
0
 def get_history(self):
     transactions = list(
         self.groupamaes_page.go(
             page='&_pid=MenuOperations&_fid=GoOperationsTraitees').
         get_history(date_guesser=LinearDateGuesser()))
     transactions = sorted_transactions(transactions)
     return transactions
Ejemplo n.º 13
0
    def get_history(self, account, coming=False):
        if account.type in (Account.TYPE_LOAN, Account.TYPE_LIFE_INSURANCE) or not account._consultable:
            raise NotImplementedError()

        if account._univers != self.current_univers:
            self.move_to_univers(account._univers)

        today = date.today()
        seen = set()
        offset = 0
        next_page = True
        while next_page:
            operation_list = self._make_api_call(
                account=account,
                start_date=date(day=1, month=1, year=2000), end_date=date.today(),
                offset=offset, max_length=50,
            )

            transactions = self.page.iter_history(account=account, operation_list=operation_list, seen=seen, today=today, coming=coming)

            # Transactions are unsorted
            for t in sorted_transactions(transactions):
                if coming == t._coming:
                    yield t
                elif coming and not t._coming:
                    # coming transactions are at the top of history
                    self.logger.debug('stopping coming after %s', t)
                    return

            next_page = len(transactions) == 50
            offset += 50

            # This assert supposedly prevents infinite loops,
            # but some customers actually have a lot of transactions.
            assert offset < 100000, 'the site may be doing an infinite loop'
Ejemplo n.º 14
0
    def _get_history_invests(self, account):
        if self.home.is_here():
            self.page.go_list()
        else:
            self.home.go()

        self.page.go_history(account._info)

        if account.type == Account.TYPE_LIFE_INSURANCE:
            if "MILLEVIE" in account.label:
                self.page.go_life_insurance(account)
                return sorted_transactions(self.natixis_life_ins_his.go(id=account.id).get_history())

            if "NUANCES 3D" in account.label:
                self.page.go_life_insurance(account)

            try:
                if not self.market.is_here() and not self.message.is_here():
                    # life insurance website is not always available
                    raise BrowserUnavailable()

                self.page.submit()
                self.location('https://www.extranet2.caisse-epargne.fr%s' % self.page.get_cons_histo())

            except (IndexError, AttributeError) as e:
                self.logger.error(e)
                return iter([])
        return self.page.iter_history()
Ejemplo n.º 15
0
    def get_card_transactions(self, account, coming):
        self.location(account.url)
        if self.home.is_here():
            # for some cards, the site redirects us to '/'...
            return

        for t in self.page.iter_history(is_card=True):
            yield t

        # For card old history, the page doesn't show the real debit date,
        # so we need to parse a csv page
        if not coming:
            if self.deferred_card_calendar is None:
                self.location(self.page.get_calendar_link())
            params = {}
            params['movementSearch[toDate]'] = self.get_closing_date(
            ).strftime('%d/%m/%Y')
            params['movementSearch[fromDate]'] = (
                date.today() - relativedelta(years=3)).strftime('%d/%m/%Y')
            params['fullSearch'] = 1

            self.location(account.url, params=params)
            csv_link = self.page.get_csv_link()
            if csv_link:
                self.location(csv_link)
                for t in sorted_transactions(
                        self.page.iter_history(account_number=account.number)):
                    yield t
        return
Ejemplo n.º 16
0
    def iter_history(self, account):
        if account._history_url.startswith('javascript:') or account._history_url == '#':
            raise NotImplementedError()

        account = find_object(self.iter_accounts(), id=account.id)

        # this url (reached with a GET) return some transactions, but not in same format than POST method
        # and some transactions are duplicated and other are missing, don't take them from GET
        # because we don't want to manage both way in iter_history
        self.location(account._history_url)
        date_range_list = self.page.get_date_range_list()

        # a date_range is a couple of date like '01/03/201831/03/2018' but current month is often missing and we have to rebuild it
        # from first one to get very recent transaction without scrap them from 1st page (reached with GET url)
        if len(date_range_list):
            date_range_list = [self._build_next_date_range(date_range_list[0])] + date_range_list


        for date_range in date_range_list:
            date_guesser = LinearDateGuesser(datetime.datetime.strptime(date_range[10:], "%d/%m/%Y"))
            try:
                self.location(account._history_url, data={'date': date_range})
            except ServerError as error:
                if error.response.status_code == 500:
                    if 'RELEVE NON DISPONIBLE A CETTE PERIODE' in error.response.text:
                        continue
                        # just skip because it's still possible to have transactions next months
                        # Yes, they really did that heresy...
                    else:
                        raise
            for tr in sorted_transactions(self.page.iter_history(date_guesser=date_guesser)):
                yield tr
Ejemplo n.º 17
0
 def iter_history(self, account):
     if hasattr(self.browser, 'get_cb_operations'):
         transactions = list(self.browser.iter_history(account))
     else:
         transactions = [tr for tr in self.browser.iter_history(account) if not tr._coming]
     transactions = sorted_transactions(transactions)
     return transactions
Ejemplo n.º 18
0
    def iter_history(self, account):
        '''
        Transactions are available 10 by 10 in a JSON.
        To access it, we need the account 'pid' and to increment
        'skip' for each transaction page until the JSON is empty.
        However, transactions are not always in the chronological order.
        '''
        self.go_wealth_pages(account)
        pid = self.page.get_pid()
        skip = 0
        if not pid:
            self.logger.warning(
                'No pid available for account %s, transactions cannot be retrieved.',
                account.id)
            return

        transactions = []
        self.go_to_transactions(pid, skip)
        # Pagination:
        while self.page.has_operations():
            for tr in self.page.iter_history():
                transactions.append(tr)
            skip += 10
            self.go_to_transactions(pid, skip)

        for tr in sorted_transactions(transactions):
            # Get investments for each transaction
            params = {'oid': tr._oid, 'pid': pid}
            self.history_investments.go(params=params)
            if self.page.has_investments():
                tr.investments = list(self.page.iter_transaction_investments())
            else:
                tr.investments = []
            yield tr
Ejemplo n.º 19
0
    def _get_history(self, info):
        if isinstance(info['link'], list):
            info['link'] = info['link'][0]
        if not info['link'].startswith('HISTORIQUE'):
            return
        if 'measure_id' in info:
            self.page.go_measure_list()
            self.page.go_measure_accounts_list(info['measure_id'])
        elif self.home.is_here():
            self.page.go_list()
        else:
            self.home_tache.go(tache='CPTSYNT0')

        self.page.go_history(info)

        info['link'] = [info['link']]

        for i in range(self.HISTORY_MAX_PAGE):

            assert self.home.is_here()

            # list of transactions on account page
            transactions_list = []
            list_form = []
            for tr in self.page.get_history():
                transactions_list.append(tr)
                if tr.type == tr.TYPE_CARD_SUMMARY:
                    list_form.append(self.page.get_form_to_detail(tr))

            # add detail card to list of transactions
            for form in list_form:
                form.submit()
                if self.home.is_here() and self.page.is_access_error():
                    self.logger.warning('Access to card details is unavailable for this user')
                    continue
                assert self.transaction_detail.is_here()
                for tr in self.page.get_detail():
                    tr.type = Transaction.TYPE_DEFERRED_CARD
                    transactions_list.append(tr)
                if self.new_website:
                    self.page.go_newsite_back_to_summary()
                else:
                    self.page.go_form_to_summary()

                # going back to summary goes back to first page
                for j in range(i):
                    assert self.page.go_next()

            #  order by date the transactions without the summaries
            transactions_list = sorted_transactions(transactions_list)

            for tr in transactions_list:
                yield tr

            assert self.home.is_here()

            if not self.page.go_next():
                return

        assert False, 'More than {} history pages'.format(self.HISTORY_MAX_PAGE)
Ejemplo n.º 20
0
    def get_history(self, account):
        self.location(account._history_link)
        if not account.type == Account.TYPE_LOAN:
            if self.page.select_period():
                return sorted_transactions(self.page.get_operations())

        return []
Ejemplo n.º 21
0
    def get_card_transactions(self, account, coming):
        # All card transactions can be found in the CSV (history and coming),
        # however the CSV shows a maximum of 1000 transactions from all accounts.
        self.location(account.url)
        if self.home.is_here():
            # for some cards, the site redirects us to '/'...
            return

        if self.deferred_card_calendar is None:
            self.location(self.page.get_calendar_link())
        params = {}
        params['movementSearch[fromDate]'] = (
            date.today() - relativedelta(years=3)).strftime('%d/%m/%Y')
        params['fullSearch'] = 1
        self.location(account.url, params=params)
        csv_link = self.page.get_csv_link()
        if csv_link:
            self.location(csv_link)
            # Yield past transactions as 'history' and
            # transactions in the future as 'coming':
            for tr in sorted_transactions(
                    self.page.iter_history(account_number=account.number)):
                if coming and tr.date > date.today():
                    tr._is_coming = True
                    yield tr
                elif not coming and tr.date <= date.today():
                    yield tr
Ejemplo n.º 22
0
    def _get_history(self, info):
        if isinstance(info['link'], list):
            info['link'] = info['link'][0]
        if not info['link'].startswith('HISTORIQUE'):
            return
        if 'measure_id' in info:
            self.page.go_measure_list()
            self.page.go_measure_accounts_list(info['measure_id'])
        elif self.home.is_here():
            self.page.go_list()
        else:
            self.home_tache.go(tache='CPTSYNT0')

        self.page.go_history(info)

        info['link'] = [info['link']]

        for i in range(100):

            assert self.home.is_here()

            # list of transactions on account page
            transactions_list = []
            list_form = []
            for tr in self.page.get_history():
                transactions_list.append(tr)
                if re.match('^CB [\d]{4}\*{6}[\d]{6} TOT DIF ([\w]{3,9})',
                            tr.label,
                            flags=re.IGNORECASE):
                    list_form.append(self.page.get_form_to_detail(tr))

            # add detail card to list of transactions
            for form in list_form:
                form.submit()
                assert self.transaction_detail.is_here()
                for tr in self.page.get_detail():
                    tr.type = Transaction.TYPE_DEFERRED_CARD
                    transactions_list.append(tr)
                if self.new_website:
                    self.page.go_newsite_back_to_summary()
                else:
                    self.page.go_form_to_summary()

                # going back to summary goes back to first page
                for j in range(i):
                    assert self.page.go_next()

            #  order by date the transactions without the summaries
            transactions_list = sorted_transactions(transactions_list)

            for tr in transactions_list:
                yield tr

            assert self.home.is_here()

            if not self.page.go_next():
                return

        assert False, 'More than 100 history pages'
Ejemplo n.º 23
0
 def get_ti_corporate_transactions(self, account):
     if account.id not in self.transactions_dict:
         self.transactions_dict[account.id] = []
         self.ti_histo_go()
         self.page.expand(self.page.get_periods()[0], account=account)
         for tr in sorted_transactions(self.page.get_history()):
             self.transactions_dict[account.id].append(tr)
     return self.transactions_dict[account.id]
Ejemplo n.º 24
0
 def get_ti_corporate_transactions(self, account):
     if account.id not in self.transactions_dict:
         self.transactions_dict[account.id] = []
         self.ti_histo_go()
         self.page.expand(self.page.get_periods()[0], account=account)
         for tr in sorted_transactions(self.page.get_history()):
             self.transactions_dict[account.id].append(tr)
     return self.transactions_dict[account.id]
Ejemplo n.º 25
0
    def get_history(self, account):
        if account.type == Account.TYPE_LOAN:
            return []
        headers = {
            'Content-Type': 'application/json; charset=UTF-8',
            'Accept': 'application/json, text/javascript, */*; q=0.01'
        }

        data = {
            'contexte': '',
            'dateEntree': None,
            'filtreEntree': None,
            'donneesEntree': json.dumps(account._formated),
        }

        items = []
        self.cenet_account_history.go(data=json.dumps(data), headers=headers)
        # there might be some duplicate transactions regarding the card type ones
        # because some requests lead to the same transaction list
        # even with different parameters/data in the request
        card_tr_list = []
        while True:
            data_out = self.page.doc['DonneesSortie']
            for tr in self.page.get_history():
                items.append(tr)

                if tr.type is FrenchTransaction.TYPE_CARD_SUMMARY:
                    if find_object(card_tr_list, label=tr.label, amount=tr.amount, raw=tr.raw, date=tr.date, rdate=tr.rdate):
                        self.logger.warning('Duplicated transaction: %s', tr)
                        items.pop()
                        continue

                    card_tr_list.append(tr)
                    tr.deleted = True
                    tr_dict = [tr_dict for tr_dict in data_out if tr_dict['Libelle'] == tr.label]
                    donneesEntree = {}
                    donneesEntree['Compte'] = account._formated
                    donneesEntree['ListeOperations'] = [tr_dict[0]]
                    deferred_data = {
                        'contexte': '',
                        'dateEntree': None,
                        'donneesEntree': json.dumps(donneesEntree).replace('/', '\\/'),
                        'filtreEntree': json.dumps(tr_dict[0]).replace('/', '\\/')
                    }
                    tr_detail_page = self.cenet_tr_detail.open(data=json.dumps(deferred_data), headers=headers)
                    for tr in tr_detail_page.get_history():
                        items.append(tr)

            offset = self.page.next_offset()
            if not offset:
                break

            data['filtreEntree'] = json.dumps({
                'Offset': offset,
            })
            self.cenet_account_history.go(data=json.dumps(data), headers=headers)

        return sorted_transactions(items)
Ejemplo n.º 26
0
    def _get_history_invests(self, account):
        if self.home.is_here():
            self.page.go_list()
        else:
            self.home.go()

        self.page.go_history(account._info)
        if account.type in (Account.TYPE_LIFE_INSURANCE, Account.TYPE_PERP):
            if self.page.is_account_inactive(account.id):
                self.logger.warning('Account %s %s is inactive.' %
                                    (account.label, account.id))
                return []

            # There is (currently ?) no history for MILLEVIE PREMIUM accounts
            if "MILLEVIE" in account.label:
                try:
                    self.page.go_life_insurance(account)
                except ServerError as ex:
                    if ex.response.status_code == 500 and 'MILLEVIE PREMIUM' in account.label:
                        self.logger.info(
                            "Can not reach history page for MILLEVIE PREMIUM account"
                        )
                        return []
                    raise

                label = account.label.split()[-1]
                try:
                    self.natixis_life_ins_his.go(id1=label[:3],
                                                 id2=label[3:5],
                                                 id3=account.id)
                except BrowserHTTPError as e:
                    if e.response.status_code == 500:
                        error = json.loads(e.response.text)
                        raise BrowserUnavailable(error["error"])
                    raise
                return sorted_transactions(self.page.get_history())

            if account.label.startswith(
                    'NUANCES ') or account.label in self.insurance_accounts:
                self.page.go_life_insurance(account)
                if 'JSESSIONID' in self.session.cookies:
                    # To access the life insurance space, we need to delete the JSESSIONID cookie to avoid an expired session
                    del self.session.cookies['JSESSIONID']

            try:
                if not self.life_insurance.is_here(
                ) and not self.message.is_here():
                    # life insurance website is not always available
                    raise BrowserUnavailable()
                self.page.submit()
                self.location('https://www.extranet2.caisse-epargne.fr%s' %
                              self.page.get_cons_histo())

            except (IndexError, AttributeError) as e:
                self.logger.error(e)
                return []
        return self.page.iter_history()
Ejemplo n.º 27
0
    def iter_history(self, account):
        if account.type == Account.TYPE_LOAN:
            return
        elif account.type == Account.TYPE_PEA:
            self.go_account_pages(account, "history")

            # go on netfinca page to get pea history
            acc = self.get_netfinca_account(account)
            self.location(acc._market_link)
            self.bourse_history.go()

            if 'Liquidités' not in account.label:
                self.page.go_history_filter(cash_filter="market")
            else:
                self.page.go_history_filter(cash_filter="liquidity")

            for tr in self.page.iter_history():
                yield tr
            return

        if account.type == Account.TYPE_LIFE_INSURANCE and account._acctype == "bank":
            if not self.lifeinsurance_iframe.is_here():
                self.location(account._url)
            self.page.go_to_history()

            # Pass account investments to try to get isin code for transaction investments
            for tr in self.page.iter_history(investments=self.cache['invs'][account.id] if account.id in self.cache['invs'] else []):
                yield tr

        # Side investment's website
        if account._acctype == "investment":
            self.go_wealth_pages(account)
            pagination_url = self.page.get_pagination_url()
            try:
                self.location(pagination_url, params={'skip': 0})
            except ClientError as e:
                assert e.response.status_code == 406
                self.logger.info('not doing pagination for account %r, site seems broken', account)
                for tr in self.page.iter_history(no_pagination=True):
                    yield tr
                return
            self.skip = 0
            for tr in self.page.iter_history(pagination_url=pagination_url):
                yield tr
        # Main website withouth investments
        elif account._acctype == "bank" and not account._hasinv and account.type != Account.TYPE_CARD:
            self.go_account_pages(account, "history")

            if self.page.more_history():
                for tr in self.page.get_history():
                    yield tr
        # Get deferred card history
        elif account._acctype == "bank" and account.type == Account.TYPE_CARD:
            for tr in sorted_transactions(self.deferred_card_transactions(account)):
                if tr.date <= date.today():
                    yield tr
Ejemplo n.º 28
0
    def iter_history(self, account):
        account = self.get_account(account.id)

        if account.type in (Account.TYPE_LOAN, Account.TYPE_PEE):
            return iter([])

        if account.type == Account.TYPE_LIFE_INSURANCE:
            url = json.loads(
                self.lifeinsurance.go(accid=account._index).content)['url']
            url = self.location(url).page.get_link("opérations")

            return self.location(url).page.iter_history()
        elif account.type in (Account.TYPE_PEA, Account.TYPE_MARKET):
            self._go_market_history()
            if not self.page.go_account(account.label, account._owner):
                return []

            if not self.page.go_account_full():
                return []

            # Display code ISIN
            self.location(self.url,
                          params={
                              'reload': 'oui',
                              'convertirCode': 'oui'
                          })
            # don't rely on server-side to do the sorting, not only do you need several requests to do so
            # but the site just toggles the sorting, resulting in reverse order if you browse multiple accounts
            return sorted_transactions(self.page.iter_history())

        # Getting a year of history
        nbs = [
            "UN", "DEUX", "TROIS", "QUATRE", "CINQ", "SIX", "SEPT", "HUIT",
            "NEUF", "DIX", "ONZE", "DOUZE"
        ]
        trs = []

        self.history.go(data=json.dumps({"index": account._index}),
                        page="pendingListOperations",
                        headers=self.json_headers)

        has_deferred_cards = self.page.has_deferred_cards()

        self.history.go(data=json.dumps({'index': account._index}),
                        page="detailcompte",
                        headers=self.json_headers)

        self.trs = {'lastdate': None, 'list': []}

        for tr in self.page.iter_history(index=account._index, nbs=nbs):
            if has_deferred_cards and tr.type == Transaction.TYPE_CARD:
                tr.type = Transaction.TYPE_DEFERRED_CARD

            trs.append(tr)

        return trs
Ejemplo n.º 29
0
    def iter_history(self, account):
        if account.type == Account.TYPE_LOAN:
            return
        elif account.type == Account.TYPE_PEA:
            self.go_account_pages(account, "history")

            # go on netfinca page to get pea history
            acc = self.get_netfinca_account(account)
            self.location(acc._market_link)
            self.bourse_history.go()

            if 'Liquidités' not in account.label:
                self.page.go_history_filter(cash_filter="market")
            else:
                self.page.go_history_filter(cash_filter="liquidity")

            for tr in self.page.iter_history():
                yield tr
            return

        if account.type == Account.TYPE_LIFE_INSURANCE and account._acctype == "bank":
            if not self.lifeinsurance_iframe.is_here():
                self.location(account._url)
            self.page.go_to_history()

            # Pass account investments to try to get isin code for transaction investments
            for tr in self.page.iter_history(investments=self.cache['invs'][account.id] if account.id in self.cache['invs'] else []):
                yield tr

        # Side investment's website
        if account._acctype == "investment":
            self.go_wealth_pages(account)
            pagination_url = self.page.get_pagination_url()
            try:
                self.location(pagination_url, params={'skip': 0})
            except ClientError as e:
                assert e.response.status_code == 406
                self.logger.info('not doing pagination for account %r, site seems broken', account)
                for tr in self.page.iter_history(no_pagination=True):
                    yield tr
                return
            self.skip = 0
            for tr in self.page.iter_history(pagination_url=pagination_url):
                yield tr
        # Main website withouth investments
        elif account._acctype == "bank" and not account._hasinv and account.type != Account.TYPE_CARD:
            self.go_account_pages(account, "history")

            if self.page.more_history():
                for tr in self.page.get_history():
                    yield tr
        # Get deferred card history
        elif account._acctype == "bank" and account.type == Account.TYPE_CARD:
            for tr in sorted_transactions(self.deferred_card_transactions(account)):
                if tr.date <= date.today():
                    yield tr
Ejemplo n.º 30
0
    def get_coming(self, account):
        for cb_link in account._card_links:
            for _ in range(3):
                self.location(cb_link)
                if not self.page.is_loading():
                    break
                time.sleep(1)

            for tr in sorted_transactions(self.page.get_operations()):
                yield tr
Ejemplo n.º 31
0
    def get_coming(self, account):
        for cb_link in account._card_links:
            for _ in range(3):
                self.location(cb_link)
                if not self.page.is_loading():
                    break
                time.sleep(1)

            for tr in sorted_transactions(self.page.get_operations()):
                yield tr
Ejemplo n.º 32
0
    def get_coming(self, account):
        trs = []

        if not hasattr(account, '_info'):
            raise NotImplementedError()
        for info in account._card_links:
            for tr in self._get_history(info.copy()):
                tr.type = tr.TYPE_DEFERRED_CARD
                tr.nopurge = True
                trs.append(tr)

        return sorted_transactions(trs)
Ejemplo n.º 33
0
    def get_coming(self, account):
        trs = []

        if not hasattr(account, '_info'):
            raise NotImplementedError()
        for info in account._card_links:
            for tr in self._get_history(info.copy()):
                tr.type = tr.TYPE_DEFERRED_CARD
                tr.nopurge = True
                trs.append(tr)

        return sorted_transactions(trs)
Ejemplo n.º 34
0
    def get_history(self, account):
        if account.type == Account.TYPE_LOAN:
            return []
        elif account.type in (Account.TYPE_MARKET, Account.TYPE_PEA):
            bourse_account = self.get_bourse_account(account)
            if not bourse_account:
                return iter([])

            self.location(bourse_account._link_id)
            assert self.bourse.is_here()
            return self.page.iter_history()
        elif account.type == Account.TYPE_LIFE_INSURANCE:
            if not self.goto_spirica(account):
                return iter([])

            return self.spirica.iter_history(account)

        if account.type != Account.TYPE_CARD:
            self.location(account.url.replace('tableauDeBord', 'operations'))
            assert self.history.is_here() or self.loan_history.is_here()
            transactions_list = []
            if account.type == Account.TYPE_CHECKING:
                # transaction of the day
                for tr in self.page.get_today_operations():
                    transactions_list.append(tr)
            # history
            for tr in self.page.get_operations():
                transactions_list.append(tr)

            return sorted_transactions(transactions_list)
        else:
            # for summary transactions, the transactions must be on both accounts:
            # negative amount on checking account, positive on card account

            transactions = list(self._get_card_transactions(account))
            summary = self.page.create_summary()
            transactions = sorted_transactions(transactions)
            if summary.amount:
                transactions.insert(0, summary)
            return transactions
Ejemplo n.º 35
0
 def get_coming(self, account):
     if account.type == Account.TYPE_CHECKING:
         self.coming.go(account=account.id)
         return self.page.get_operations()
     elif account.type == Account.TYPE_CARD:
         self.location(account.url.replace('operations', 'encoursCarte') + '/%s' % account._index)
         transactions = list(self.page.get_operations())
         if self.page.get_debit_date().month == (datetime.date.today() + relativedelta(months=1)).month:
             self.location(account.url.replace('operations', 'encoursCarte') + '/%s?month=1' % account._index)
             transactions += list(self.page.get_operations())
         return sorted_transactions(transactions)
     else:
         raise NotImplementedError()
Ejemplo n.º 36
0
 def get_coming(self, account):
     if account.type == Account.TYPE_CHECKING:
         self.coming.go(account=account.id)
         return self.page.get_operations()
     elif account.type == Account.TYPE_CARD:
         self.location(account.url.replace('tableauDeBord', 'encoursCarte') + '/%s' % account._index)
         transactions = list(self.page.get_operations())
         if self.page.get_debit_date().month == (datetime.date.today() + relativedelta(months=1)).month:
             self.location(account.url.replace('tableauDeBord', 'encoursCarte') + '/%s?month=1' % account._index)
             transactions += list(self.page.get_operations())
         return sorted_transactions(transactions)
     else:
         raise NotImplementedError()
Ejemplo n.º 37
0
    def get_coming(self, account):
        if 'gestion-sous-mandat' in account.url:
            return []

        transactions = list(self._get_coming_transactions(account))

        for tr in self.iter_card_transactions(account):
            if tr._coming:
                transactions.append(tr)

        transactions = sorted_transactions(transactions)

        return transactions
Ejemplo n.º 38
0
    def get_history(self, account, coming=False):
        if account.type in (Account.TYPE_LOAN, Account.TYPE_LIFE_INSURANCE
                            ) or not account._consultable:
            raise NotImplementedError()

        if account._univers != self.current_univers:
            self.move_to_univers(account._univers)

        today = date.today()
        seen = set()
        offset = 0
        next_page = True
        end_date = date.today()
        last_date = None
        while next_page:
            if offset == 10000:
                offset = 0
                end_date = last_date
            operation_list = self._make_api_call(
                account=account,
                start_date=date(day=1, month=1, year=2000),
                end_date=end_date,
                offset=offset,
                max_length=50,
            )

            transactions = self.page.iter_history(
                account=account,
                operation_list=operation_list,
                seen=seen,
                today=today,
                coming=coming)

            transactions = sorted_transactions(transactions)
            if transactions:
                last_date = transactions[-1].date
            # Transactions are unsorted
            for t in transactions:
                if coming == t._coming:
                    yield t
                elif coming and not t._coming:
                    # coming transactions are at the top of history
                    self.logger.debug('stopping coming after %s', t)
                    return

            next_page = len(transactions) > 0
            offset += 50

            # This assert supposedly prevents infinite loops,
            # but some customers actually have a lot of transactions.
            assert offset < 100000, 'the site may be doing an infinite loop'
Ejemplo n.º 39
0
    def iter_history(self, account, coming=False):
        # The accounts from the "Assurances Vie" space have no available history:
        if hasattr(account, '_details'):
            return []
        if account.type == Account.TYPE_PEA and account.label.endswith('Espèces'):
            return []
        if account.type == account.TYPE_LIFE_INSURANCE:
            return self.iter_lifeinsurance_history(account, coming)
        elif account.type in (account.TYPE_MARKET, Account.TYPE_PEA) and not coming:
            try:
                self.market_list.go(data=JSON({}))
            except ServerError:
                self.logger.warning("An Internal Server Error occurred")
                return iter([])
            for market_acc in self.page.get_list():
                if account.number[-4:] == market_acc['securityAccountNumber'][-4:]:
                    self.page = self.market_history.go(data=JSON({
                        "securityAccountNumber": market_acc['securityAccountNumber'],
                    }))
                    return self.page.iter_history()
            return iter([])
        else:
            if not self.card_to_transaction_type:
                self.list_detail_card.go()
                self.card_to_transaction_type = self.page.get_card_to_transaction_type()

            self.history.go(data=JSON({
                "ibanCrypte": account.id,
                "pastOrPending": 1,
                "triAV": 0,
                "startDate": (datetime.now() - relativedelta(years=2)).strftime('%d%m%Y'),
                "endDate": datetime.now().strftime('%d%m%Y')
            }))

            if coming:
                return sorted_transactions(self.page.iter_coming())
            else:
                return sorted_transactions(self.page.iter_history())
Ejemplo n.º 40
0
    def get_coming(self, account):
        transactions = []
        data = {'accountExternalNumber': account.id}
        self.pre_comingpage.go(data=data)
        assert self.comingpage.is_here()
        # this page is "operations du jour" and may not have any date yet
        # so don't take transactions here, but it sets the "context"

        self.comingpage.go()
        assert self.comingpage.is_here()
        transactions += self.page.get_transactions(pattern='var jsonData =')
        self.deffered_transactionpage.go(data=data)
        transactions += self.page.get_transactions(pattern='var jsonData1 =', is_deffered=True)
        return sorted_transactions(transactions)
Ejemplo n.º 41
0
    def iter_transactions(self, account, coming=False):
        self.select_account(account.label)

        self.history.go()
        self.wait_until_is_here(self.history)

        if not self.date_list:
            self.date_list = self.page.fetch_date_list()

        for date_choice in self.date_list:
            if (coming and date_choice >= self.today) or (
                    not coming and date_choice < self.today):
                self.page.display_transactions(date_choice)
                for tr in sorted_transactions(
                        self.page.iter_history(date=date_choice)):
                    yield tr
Ejemplo n.º 42
0
    def get_history(self, account):
        if account.type == Account.TYPE_LOAN:
            return []
        elif account.type in (Account.TYPE_MARKET, Account.TYPE_PEA):
            bourse_account = self.get_bourse_account(account)
            if not bourse_account:
                return iter([])

            self.location(bourse_account._link_id)
            assert self.bourse.is_here()
            history = list(self.page.iter_history())
            self.leave_espace_bourse()

            return history
        elif account.type == Account.TYPE_LIFE_INSURANCE:
            if not self.goto_spirica(account):
                return iter([])

            return self.spirica.iter_history(account)

        if account.type != Account.TYPE_CARD:
            self.location(account.url)
            assert self.history.is_here() or self.loan_history.is_here()
            transactions_list = []
            if account.type == Account.TYPE_CHECKING:
                # transaction of the day
                for tr in self.page.get_today_operations():
                    transactions_list.append(tr)
            # history
            for tr in self.page.get_operations():
                transactions_list.append(tr)

            return sorted_transactions(transactions_list)
        else:
            # for summary transactions, the transactions must be on both accounts:
            # negative amount on checking account, positive on card account
            transactions = []
            self.location(
                account.url.replace('operations', 'encoursCarte') +
                '/%s?month=1' % account._index)
            if self.page.get_debit_date().month == (
                    datetime.date.today() - relativedelta(months=1)).month:
                transactions = list(self.page.get_operations())
                summary = self.page.create_summary()
                if summary:
                    transactions.insert(0, summary)
            return transactions
Ejemplo n.º 43
0
 def get_ge_transactions(self, account):
     transactions = []
     self.coming.go()
     self.page.expand(rib=account._rib)
     link = self.page.get_link(account)
     if link:
         self.location(link)
         transactions += self.page.get_history()
     self.history.go()
     for period in self.page.get_periods():
         self.page.expand(period, rib=account._rib)
         link = self.page.get_link(account)
         if link:
             self.location(link)
             transactions += self.page.get_history()
             self.history.go()
     return sorted_transactions(transactions)
Ejemplo n.º 44
0
    def iter_history(self, account):
        ''' There is now an API for the accounts history, however transactions are not
        sorted by date in the JSON. The website fetches 5 years of history maximum.
        For some accounts, the access to the transactions JSON is not available yet. '''
        params = {
            'startDate': (date.today() - relativedelta(years=2)).year,
            'endDate': date.today().year,
            'pid': account.id,
        }
        self.history.go(params=params)
        error_code = self.page.get_error_code()
        if error_code:
            self.logger.warning('Error when trying to access the history JSON, history will be skipped for this account.')
            return

        for tr in sorted_transactions(self.page.iter_history()):
            yield tr
Ejemplo n.º 45
0
    def _iter_history_base(self, account):
        history = []
        dformat = "%Y%m%d"

        for date in rrule(MONTHLY, dtstart=(datetime.now() - relativedelta(months=3)), until=datetime.now()):
            self.account_history_view.go(identifiant=account.iban, type_solde='C', type_releve='Comptable', \
                                         type_date='O', date_min=(date + relativedelta(days=1)).strftime(dformat), \
                                         date_max=(date + relativedelta(months=1)).strftime(dformat))
            self.account_history.go(identifiant=account.iban, date_min=(date + relativedelta(days=1)).strftime(dformat), \
                                    date_max=(date + relativedelta(months=1)).strftime(dformat))

            for transaction in self.page.iter_history():
                if transaction._coming:
                    self.logger.debug('skipping coming %r', transaction.to_dict())
                    continue
                history.append(transaction)
        return sorted_transactions(history)
Ejemplo n.º 46
0
    def get_history(self, account):
        transactions = []
        if not account._link_id:
            raise NotImplementedError()

        # need to refresh the months select
        if account._link_id.startswith('ENC_liste_oper'):
            self.location(account._pre_link)

        if not hasattr(account, '_card_pages'):
            for tr in self.list_operations(account._link_id):
                transactions.append(tr)

        coming_link = self.page.get_coming_link() if self.operations.is_here(
        ) else None
        if coming_link is not None:
            for tr in self.list_operations(coming_link):
                transactions.append(tr)

        differed_date = None
        cards = [page.select_card(account._card_number) for page in account._card_pages] if hasattr(account, '_card_pages') else \
                account._card_links if hasattr(account, '_card_links') else []
        for card in cards:
            card_trs = []
            for tr in self.list_operations(card):
                if hasattr(tr, '_differed_date') and (
                        not differed_date
                        or tr._differed_date < differed_date):
                    differed_date = tr._differed_date
                if tr.date >= datetime.now():
                    tr._is_coming = True
                elif hasattr(account, '_card_pages'):
                    card_trs.append(tr)
                transactions.append(tr)
            if card_trs:
                transactions.extend(self.get_monthly_transactions(card_trs))

        if differed_date is not None:
            # set deleted for card_summary
            for tr in transactions:
                tr.deleted = tr.type == FrenchTransaction.TYPE_CARD_SUMMARY and \
                             differed_date.month <= tr.date.month and \
                             not hasattr(tr, '_is_manualsum')

        transactions = sorted_transactions(transactions)
        return transactions
Ejemplo n.º 47
0
 def get_ge_transactions(self, account):
     transactions = []
     self.coming.go()
     self.page.expand(rib=account._rib)
     link = self.page.get_link(account)
     if link:
         self.location(link)
         transactions += self.page.get_history()
     self.history.go()
     for period in self.page.get_periods():
         self.page.expand(period, rib=account._rib)
         link = self.page.get_link(account)
         if link:
             self.location(link)
             transactions += self.page.get_history()
             self.history.go()
     return sorted_transactions(transactions)
Ejemplo n.º 48
0
    def get_history(self, account):
        if account.type == Account.TYPE_LOAN:
            return []
        elif account.type in (Account.TYPE_MARKET, Account.TYPE_PEA):
            bourse_account = self.get_bourse_account(account)
            if not bourse_account:
                return iter([])

            self.location(bourse_account._link_id)
            assert self.bourse.is_here()
            history = list(self.page.iter_history())
            self.leave_espace_bourse()

            return history
        elif account.type == Account.TYPE_LIFE_INSURANCE:
            if not self.goto_spirica(account):
                return iter([])

            return self.spirica.iter_history(account)

        if account.type != Account.TYPE_CARD:
            self.location(account.url.replace('tableauDeBord', 'operations'))
            assert self.history.is_here() or self.loan_history.is_here()
            transactions_list = []
            if account.type == Account.TYPE_CHECKING:
                # transaction of the day
                for tr in self.page.get_today_operations():
                    transactions_list.append(tr)
            # history
            for tr in self.page.get_operations():
                transactions_list.append(tr)

            return sorted_transactions(transactions_list)
        else:
            # for summary transactions, the transactions must be on both accounts:
            # negative amount on checking account, positive on card account
            transactions = []
            self.location(account.url.replace('tableauDeBord', 'encoursCarte') + '/%s?month=1' % account._index)
            if self.page.get_debit_date().month == (datetime.date.today() - relativedelta(months=1)).month:
                transactions = list(self.page.get_operations())
                summary = self.page.create_summary()
                if summary:
                    transactions.insert(0, summary)
            return transactions
Ejemplo n.º 49
0
    def iter_history(self, account):
        account = self.get_account(account.id)

        if account.type is Account.TYPE_LOAN:
            return iter([])

        if account.type == Account.TYPE_LIFE_INSURANCE:
            url = json.loads(self.lifeinsurance.go(accid=account._index).content)['url']
            url = self.location(url).page.get_link(u"opérations")

            return self.location(url).page.iter_history()
        elif account.type in (Account.TYPE_PEA, Account.TYPE_MARKET):
            self._go_market_history()
            if not self.page.go_account(account.label, account._owner):
                return []

            if not self.page.go_account_full():
                return []

            # Display code ISIN
            self.location(self.url, params={'reload': 'oui', 'convertirCode': 'oui'})
            # don't rely on server-side to do the sorting, not only do you need several requests to do so
            # but the site just toggles the sorting, resulting in reverse order if you browse multiple accounts
            return sorted_transactions(self.page.iter_history())

        # Getting a year of history
        nbs = ["UN", "DEUX", "TROIS", "QUATRE", "CINQ", "SIX", "SEPT", "HUIT", "NEUF", "DIX", "ONZE", "DOUZE"]
        trs = []

        self.history.go(data=json.dumps({"index": account._index}), page="pendingListOperations", headers=self.json_headers)

        has_deferred_cards = self.page.has_deferred_cards()

        self.history.go(data=json.dumps({'index': account._index}), page="detailcompte", headers=self.json_headers)

        self.trs = {'lastdate': None, 'list': []}

        for tr in self.page.iter_history(index=account._index, nbs=nbs):
            if has_deferred_cards and tr.type == Transaction.TYPE_CARD:
                tr.type = Transaction.TYPE_DEFERRED_CARD

            trs.append(tr)

        return trs
Ejemplo n.º 50
0
    def get_history(self, account):
        transactions = []
        if not account._link_id:
            raise NotImplementedError()

        # need to refresh the months select
        if account._link_id.startswith('ENC_liste_oper'):
            self.location(account._pre_link)

        if not hasattr(account, '_card_pages'):
            for tr in self.list_operations(account._link_id, account):
                transactions.append(tr)

        coming_link = self.page.get_coming_link() if self.operations.is_here() else None
        if coming_link is not None:
            for tr in self.list_operations(coming_link, account):
                transactions.append(tr)

        differed_date = None
        cards = [page.select_card(account._card_number) for page in account._card_pages] if hasattr(account, '_card_pages') else \
                account._card_links if hasattr(account, '_card_links') else []
        for card in cards:
            card_trs = []
            for tr in self.list_operations(card, account):
                if hasattr(tr, '_differed_date') and (not differed_date or tr._differed_date < differed_date):
                    differed_date = tr._differed_date
                if tr.date >= datetime.now():
                    tr._is_coming = True
                elif hasattr(account, '_card_pages'):
                    card_trs.append(tr)
                transactions.append(tr)
            if card_trs:
                transactions.extend(self.get_monthly_transactions(card_trs))

        if differed_date is not None:
            # set deleted for card_summary
            for tr in transactions:
                tr.deleted = tr.type == FrenchTransaction.TYPE_CARD_SUMMARY and \
                             differed_date.month <= tr.date.month and \
                             not hasattr(tr, '_is_manualsum')

        transactions = sorted_transactions(transactions)
        return transactions
Ejemplo n.º 51
0
    def _iter_history_base(self, account):
        history = []
        dformat = "%Y%m%d"

        for date in rrule(MONTHLY,
                          dtstart=(datetime.now() - relativedelta(months=3)),
                          until=datetime.now()):
            self.account_history_view.go(identifiant=account.iban, type_solde='C', type_releve='Comptable', \
                                         type_date='O', date_min=(date + relativedelta(days=1)).strftime(dformat), \
                                         date_max=(date + relativedelta(months=1)).strftime(dformat))
            self.account_history.go(identifiant=account.iban, date_min=(date + relativedelta(days=1)).strftime(dformat), \
                                    date_max=(date + relativedelta(months=1)).strftime(dformat))

            for transaction in self.page.iter_history():
                if transaction._coming:
                    self.logger.debug('skipping coming %r',
                                      transaction.to_dict())
                    continue
                history.append(transaction)
        return sorted_transactions(history)
Ejemplo n.º 52
0
    def get_coming(self, account):
        trs = []

        headers = {
            'Content-Type': 'application/json; charset=UTF-8',
            'Accept': 'application/json, text/javascript, */*; q=0.01'
        }

        for card in account._cards:
            data = {
                'contexte': '',
                'dateEntree': None,
                'donneesEntree': json.dumps(card),
                'filtreEntree': None
            }

            for tr in self.cenet_account_coming.go(data=json.dumps(data), headers=headers).get_history():
                trs.append(tr)

        return sorted_transactions(trs)
Ejemplo n.º 53
0
    def _get_history_invests(self, account):
        if self.home.is_here():
            self.page.go_list()
        else:
            self.home.go()

        self.page.go_history(account._info)
        if account.type in (Account.TYPE_LIFE_INSURANCE, Account.TYPE_PERP):
            if self.page.is_account_inactive(account.id):
                self.logger.warning('Account %s %s is inactive.' % (account.label, account.id))
                return []
            if "MILLEVIE" in account.label:
                self.page.go_life_insurance(account)
                label = account.label.split()[-1]
                try:
                    self.natixis_life_ins_his.go(id1=label[:3], id2=label[3:5], id3=account.id)
                except BrowserHTTPError as e:
                    if e.response.status_code == 500:
                        error = json.loads(e.response.text)
                        raise BrowserUnavailable(error["error"])
                    raise
                return sorted_transactions(self.page.get_history())

            if account.label.startswith('NUANCES ') or account.label in self.insurance_accounts:
                self.page.go_life_insurance(account)
                if 'JSESSIONID' in self.session.cookies:
                    # To access the life insurance space, we need to delete the JSESSIONID cookie to avoid an expired session
                    del self.session.cookies['JSESSIONID']

            try:
                if not self.life_insurance.is_here() and not self.message.is_here():
                    # life insurance website is not always available
                    raise BrowserUnavailable()
                self.page.submit()
                self.location('https://www.extranet2.caisse-epargne.fr%s' % self.page.get_cons_histo())

            except (IndexError, AttributeError) as e:
                self.logger.error(e)
                return []
        return self.page.iter_history()
Ejemplo n.º 54
0
    def get_coming(self, account):
        if account.type == Account.TYPE_LOAN:
            return []
        trs = []

        headers = {
            'Content-Type': 'application/json; charset=UTF-8',
            'Accept': 'application/json, text/javascript, */*; q=0.01'
        }

        for card in account._cards:
            if card['CumulEnCours']['Montant']['Valeur'] != 0:
                data = {
                    'contexte': '',
                    'dateEntree': None,
                    'donneesEntree': json.dumps(card),
                    'filtreEntree': None
                }

                for tr in self.cenet_account_coming.go(data=json.dumps(data), headers=headers).get_history():
                    trs.append(tr)

        return sorted_transactions(trs)
Ejemplo n.º 55
0
    def get_transactions(self, account):
        if not self.accounts:
            self.iter_accounts()

        self.his_home.go()
        self.page.expand()
        for a in self.accounts:
            if a.id == account.id:
                link = self.get_link(a.number, a._owner)
                if link:
                    self.location(link)
                    assert self.transactions.is_here()

                    # We might not be on first page.
                    self.page.assert_first_page_or_go_there()

                    if self.page.is_not_sorted():
                        self.page.sort()

                    transactions = list(self.page.get_history())
                    transactions = sorted_transactions(transactions)
                    return transactions
        return iter([])
Ejemplo n.º 56
0
 def iter_history(self, account):
     transactions = sorted_transactions(self.browser.get_history(account))
     return transactions
Ejemplo n.º 57
0
    def get_history(self, account, coming=False, retry_li=True):
        self._quit_li_space()

        self.update_accounts_list(False)
        account = self.accounts_list[account.id]

        if account.url is None:
            return []

        if account.url.startswith('javascript') or '&Crd=' in account.url:
            raise NotImplementedError()

        if account.type == Account.TYPE_LIFE_INSURANCE:
            if coming is True:
                return []

            try:
                if not self._go_to_life_insurance(account):
                    self._quit_li_space()
                    return []
            except (XMLSyntaxError, HTTPNotFound):
                self._quit_li_space()
                return []
            except AccountNotFound:
                self.go_post(self.js_url)

                # often if we visit life insurance subsite multiple times too quickly, the site just returns an error
                # so we just retry (we might relogin...)
                # TODO find out how to avoid the error, or avoid relogin
                if retry_li:
                    self.logger.warning('life insurance seems unavailable for account %s', account.id)
                    return self.get_history(account, coming, False)

                self.logger.error('life insurance seems unavailable for account %s', account.id)
                return []

            self.life_insurances.go(data={'url_suivant': 'HISTORIQUECONTRATB2C', 'strMonnaie': 'EURO'})

            history = [t for t in self.page.iter_history()]

            self._quit_li_space()

            return history

        try:
            self.go_post(self.accounts_list[account.id].url)
        # sometime go to hsbc life insurance space do logout
        except HTTPNotFound:
            self.app_gone = True
            self.do_logout()
            self.do_login()

        # If we relogin on hsbc, all link have change
        if self.app_gone:
            self.app_gone = False
            self.update_accounts_list()
            self.location(self.accounts_list[account.id].url)

        if self.page is None:
            return []

        if self.cbPage.is_here():
            guesser = LinearDateGuesser(date_max_bump=timedelta(45))
            history = list(self.page.get_history(date_guesser=guesser))
            for url, params in self.page.get_params(self.url):
                self.location(url, params=params)
                if self.cbPage.is_here():
                    history.extend(self.page.get_history(date_guesser=guesser))

            for tr in history:
                if tr.type == tr.TYPE_UNKNOWN:
                    tr.type = tr.TYPE_DEFERRED_CARD

            history.extend(self.get_monthly_transactions(history))
            history = [tr for tr in history if (coming and tr.date > date.today()) or (not coming and tr.date <= date.today())]
            history = sorted_transactions(history)
            return history
        elif not coming:
            return self._get_history()
        else:
            raise NotImplementedError()
Ejemplo n.º 58
0
    def get_history(self, account, coming=False):
        if account.type == Account.TYPE_CARD:
            card_transactions = []
            self.go_to_account_space(account._contract)
            # Deferred cards transactions have a specific JSON.
            # Only three months of history available for cards.
            value = 0 if coming else 1
            params = {
                'grandeFamilleCode': int(account._category),
                'compteIdx': int(account.parent._index),
                'carteIdx': int(account._index),
                'rechercheEncoursDebite': value
            }
            self.card_history.go(params=params)
            for tr in self.page.iter_card_history():
                card_transactions.append(tr)

            # If the card if not unique on the parent id, it is impossible
            # to know which summary corresponds to which card.
            if not coming and card_transactions and account._unique:
                # Get card summaries from parent account
                # until we reach the oldest card transaction
                last_transaction = card_transactions[-1]
                before_last_transaction = False
                params = {
                    'compteIdx': int(account.parent._index),
                    'grandeFamilleCode': int(account.parent._category),
                    'idDevise': str(account.parent.currency),
                    'idElementContrat': str(account.parent._id_element_contrat),
                }
                self.history.go(params=params)
                for tr in self.page.iter_history():
                    if tr.date < last_transaction.date:
                        before_last_transaction = True
                        break
                    if tr.type == Transaction.TYPE_CARD_SUMMARY:
                        tr.amount = -tr.amount
                        card_transactions.append(tr)

                while self.page.has_next_page() and not before_last_transaction:
                    next_index = self.page.get_next_index()
                    params = {
                        'grandeFamilleCode': int(account.parent._category),
                        'compteIdx': int(account.parent._index),
                        'idDevise': str(account.parent.currency),
                        'startIndex': next_index,
                        'count': 100,
                    }
                    self.history.go(params=params)
                    for tr in self.page.iter_history():
                        if tr.date < last_transaction.date:
                            before_last_transaction = True
                            break
                        if tr.type == Transaction.TYPE_CARD_SUMMARY:
                            tr.amount = -tr.amount
                            card_transactions.append(tr)

            for tr in sorted_transactions(card_transactions):
                yield tr
            return

        # These three parameters are required to get the transactions for non_card accounts
        if empty(account._index) or empty(account._category) or empty(account._id_element_contrat):
            return

        self.go_to_account_space(account._contract)
        params = {
            'compteIdx': int(account._index),
            'grandeFamilleCode': int(account._category),
            'idDevise': str(account.currency),
            'idElementContrat': str(account._id_element_contrat),
        }
        self.history.go(params=params)
        for tr in self.page.iter_history():
            # For "Livret A", value dates of transactions are always
            # 1st or 15th of the month so we specify a valuation date.
            # Example: rdate = 21/02, date=01/02 then vdate = 01/02.
            if account.type == Account.TYPE_SAVINGS:
                tr.vdate = tr.date
            yield tr

        # Get other transactions 100 by 100:
        while self.page.has_next_page():
            next_index = self.page.get_next_index()
            params = {
                'grandeFamilleCode': int(account._category),
                'compteIdx': int(account._index),
                'idDevise': str(account.currency),
                'startIndex': next_index,
                'count': 100,
            }
            self.history.go(params=params)
            for tr in self.page.iter_history():
                yield tr
Ejemplo n.º 59
0
 def flush(self):
     # As transactions are unordered on the page, we flush only at end
     # the sorted list of them.
     return sorted_transactions(self.objects.values())
Ejemplo n.º 60
0
 def iter_coming(self, account):
     if hasattr(self.browser, 'get_cb_operations'):
         transactions = list(self.browser.get_cb_operations(account))
         return sorted_transactions(transactions)
     return self.browser.iter_coming(account)