Ejemplo n.º 1
0
    def iter_history(self, account):
        # Load i18n for type translation
        self.i18np.open(lang1=self.LANG, lang2=self.LANG).load_i18n()

        # For now detail for each account is not available. History is global for all accounts and very simplist
        data = {
            'clang': self.LANG,
            'ctcc': self.CTCC,
            'login': self.username,
            'session': self.sessionId
        }

        for trans in self.historyp.open(data=data).get_transactions():
            t = Transaction()
            t.id = trans["referenceOperationIndividuelle"]
            t.date = datetime.strptime(trans["dateHeureSaisie"], "%d/%m/%Y")
            t.rdate = datetime.strptime(trans["dateHeureSaisie"], "%d/%m/%Y")
            t.type = Transaction.TYPE_DEPOSIT if trans[
                "montantNetEuro"] > 0 else Transaction.TYPE_PAYBACK
            t.raw = trans["typeOperation"]
            try:
                t.label = self.i18n["OPERATION_TYPE_" + trans["casDeGestion"]]
            except KeyError:
                t.label = self.i18n["OPERATION_TYPE_TOTAL_" +
                                    trans["casDeGestion"]]
            t.amount = Decimal(trans["montantNetEuro"]).quantize(
                Decimal('.01'))
            yield t
Ejemplo n.º 2
0
    def get_history(self, account):
        if not account._consultable:
            raise NotImplementedError()

        offset = 0
        next_page = True
        while next_page:
            r = self.open('/transactionnel/services/applications/operations/get/%(number)s/%(nature)s/00/%(currency)s/%(startDate)s/%(endDate)s/%(offset)s/%(limit)s' %
                          {'number': account._number,
                           'nature': account._nature,
                           'currency': account.currency,
                           'startDate': '2000-01-01',
                           'endDate': date.today().strftime('%Y-%m-%d'),
                           'offset': offset,
                           'limit': 50
                          })
            next_page = False
            offset += 50
            for op in r.json()['content']['operations']:
                next_page = True
                t = Transaction()
                t.id = op['id']
                t.amount = Decimal(str(op['montant']))
                t.date = date.fromtimestamp(op.get('dateDebit', op.get('dateOperation'))/1000)
                t.rdate = date.fromtimestamp(op.get('dateOperation', op.get('dateDebit'))/1000)
                t.vdate = date.fromtimestamp(op.get('dateValeur', op.get('dateDebit', op.get('dateOperation')))/1000)
                if 'categorie' in op:
                    t.category = op['categorie']
                t.label = op['libelle']
                t.raw = ' '.join([op['libelle']] + op['details'])
                yield t
Ejemplo n.º 3
0
    def iter_history(self):
        for tr in self.doc.xpath(
                u'//table[@class="boursedetail"]/tbody/tr[td]'):
            t = Transaction()

            t.label = CleanText('.')(tr.xpath('./td[2]')[0])
            t.date = Date(dayfirst=True).filter(
                CleanText('.')(tr.xpath('./td[1]')[0]))
            t.amount = self.parse_decimal(tr.xpath('./td[3]')[0])

            yield t
Ejemplo n.º 4
0
    def get_history(self, account):
        if not account._consultable:
            raise NotImplementedError()

        if account._univers != self.current_univers:
            self.move_to_univers(account._univers)
        offset = 0
        next_page = True
        seen = set()
        while next_page:
            r = self.api_open(
                '/transactionnel/services/applications/operations/get/%(number)s/%(nature)s/00/%(currency)s/%(startDate)s/%(endDate)s/%(offset)s/%(limit)s'
                % {
                    'number': account._number,
                    'nature': account._nature,
                    'currency': account.currency,
                    'startDate': '2000-01-01',
                    'endDate': date.today().strftime('%Y-%m-%d'),
                    'offset': offset,
                    'limit': 50
                })
            next_page = False
            offset += 50
            transactions = []
            for op in reversed(r.json()['content']['operations']):
                next_page = True
                t = Transaction()
                if op['id'] in seen:
                    raise ParseError(
                        'There are several transactions with the same ID, probably an infinite loop'
                    )
                t.id = op['id']
                seen.add(t.id)
                t.amount = Decimal(str(op['montant']))
                t.date = date.fromtimestamp(
                    op.get('dateDebit', op.get('dateOperation')) / 1000)
                t.rdate = date.fromtimestamp(
                    op.get('dateOperation', op.get('dateDebit')) / 1000)
                t.vdate = date.fromtimestamp(
                    op.get('dateValeur',
                           op.get('dateDebit', op.get('dateOperation'))) /
                    1000)
                if 'categorie' in op:
                    t.category = op['categorie']
                t.label = op['libelle']
                t.raw = ' '.join([op['libelle']] + op['details'])
                transactions.append(t)

            # Transactions are unsorted
            for t in sorted(transactions, key=lambda t: t.rdate, reverse=True):
                yield t
Ejemplo n.º 5
0
    def iter_transactions(self):
        for row in self.doc.xpath('//tr/th[@headers='
                                  '"postedHeader transactionDateHeader"]/..'):
            tdate = row.xpath('th[@headers="postedHeader '
                              'transactionDateHeader"]/text()')[0]
            pdate = row.xpath('td[@headers="postedHeader '
                              'postingDateHeader"]/text()')[0]
            desc = row.xpath('td[@headers="postedHeader '
                             'descriptionHeader"]/span/text()')[0]
            ref = row.xpath('td[@headers="postedHeader '
                            'descriptionHeader"]/text()')[0]
            amount = row.xpath('td[@headers="postedHeader '
                               'amountHeader"]/text()')[0]

            tdate = datetime.datetime.strptime(tdate, '%m/%d/%y')
            pdate = datetime.datetime.strptime(pdate, '%m/%d/%y')

            desc = clean_label(desc)

            ref = re.match('.*<REFERENCE ([^>]+)>.*', ref).group(1)

            if amount.startswith('+'):
                amount = AmTr.decimal_amount(amount[1:])
            else:
                amount = -AmTr.decimal_amount(amount)

            trans = Transaction(ref)
            trans.date = tdate
            trans.rdate = pdate
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = amount
            yield trans
Ejemplo n.º 6
0
    def iter_transactions(self):
        for row in self.doc.xpath('//tr/th[@headers='
                                  '"postedHeader dateHeader"]/..'):
            date = row.xpath('th[@headers="postedHeader '
                             'dateHeader"]/text()')[0]
            desc = row.xpath('td[@headers="postedHeader descriptionHeader"]'
                             '//span[@class="OneLinkNoTx"]/text()')[0]
            deposit = row.xpath('td[@headers="postedHeader '
                                'depositsConsumerHeader"]/span/text()')[0]
            withdraw = row.xpath('td[@headers="postedHeader '
                                 'withdrawalsConsumerHeader"]/span/text()')[0]

            date = datetime.datetime.strptime(date, '%m/%d/%y')

            desc = clean_label(desc)

            deposit = deposit.strip()
            deposit = AmTr.decimal_amount(deposit or '0')
            withdraw = withdraw.strip()
            withdraw = AmTr.decimal_amount(withdraw or '0')

            amount = deposit - withdraw

            trans = Transaction(u'')
            trans.date = date
            trans.rdate = date
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = amount
            yield trans
Ejemplo n.º 7
0
    def read_transaction(self, pos, date_from, date_to):
        startPos = pos

        pos, tdate = self.read_date(pos)
        pos, pdate = self.read_date(pos)

        # Early check to call read_multiline_desc() only when needed.
        if tdate is None:
            return startPos, None

        pos, desc = self.read_multiline_desc(pos)
        pos, amount = self.read_amount(pos)

        if desc is None or amount is None:
            return startPos, None
        else:
            # Sometimes one date is missing.
            pdate = pdate or tdate

            tdate = closest_date(tdate, date_from, date_to)
            pdate = closest_date(pdate, date_from, date_to)

            trans = Transaction()
            trans.date = tdate
            trans.rdate = pdate
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = -amount
            return pos, trans
Ejemplo n.º 8
0
    def read_transaction(self, pos, date_from, date_to):
        startPos = pos
        pos, tdate = self.read_date(pos)
        pos, pdate_layout = self.read_layout_td(pos)
        pos, pdate = self.read_date(pos)
        pos, ref_layout = self.read_layout_td(pos)
        pos, ref = self.read_ref(pos)
        pos, desc_layout = self.read_layout_td(pos)
        pos, desc = self.read_text(pos)
        pos, amount_layout = self.read_layout_td(pos)
        pos, amount = self.read_amount(pos)
        if tdate is None or pdate is None \
        or desc is None or amount is None or amount == 0:
            return startPos, None
        else:
            tdate = closest_date(tdate, date_from, date_to)
            pdate = closest_date(pdate, date_from, date_to)
            desc = u' '.join(desc.split())

            trans = Transaction(ref or u'')
            trans.date = tdate
            trans.rdate = pdate
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = amount
            return pos, trans
Ejemplo n.º 9
0
    def read_card_transaction(self, pos, date_from, date_to):
        INDENT_CHARGES = 520

        startPos = pos

        pos, tdate = self.read_date(pos)
        pos, pdate_layout = self.read_layout_tm(pos)
        pos, pdate = self.read_date(pos)
        pos, ref_layout = self.read_layout_tm(pos)
        pos, ref = self.read_ref(pos)
        pos, desc = self.read_multiline_desc(pos)
        pos, amount = self.read_indent_amount(pos,
                                              range_minus=(INDENT_CHARGES,
                                                           9999),
                                              range_plus=(0, INDENT_CHARGES))

        if tdate is None or pdate_layout is None or pdate is None \
        or ref_layout is None or ref is None or desc is None or amount is None:
            return startPos, None
        else:
            tdate = closest_date(tdate, date_from, date_to)
            pdate = closest_date(pdate, date_from, date_to)

            trans = Transaction(ref)
            trans.date = tdate
            trans.rdate = pdate
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = amount
            return pos, trans
Ejemplo n.º 10
0
    def read_cash_transaction(self, pos, date_from, date_to):
        INDENT_BALANCE = 520
        INDENT_WITHDRAWAL = 470

        startPos = pos

        pos, date = self.read_date(pos)
        pos, _ = self.read_star(pos)
        pos, desc = self.read_multiline_desc(pos)
        pos, amount = self.read_indent_amount(
            pos,
            range_plus=(0, INDENT_WITHDRAWAL),
            range_minus=(INDENT_WITHDRAWAL, INDENT_BALANCE),
            range_skip=(INDENT_BALANCE, 9999))

        if desc is None or date is None or amount is None:
            return startPos, None
        else:
            date = closest_date(date, date_from, date_to)

            trans = Transaction(u'')
            trans.date = date
            trans.rdate = date
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = amount
            return pos, trans
Ejemplo n.º 11
0
    def unsorted_trans(self):
        for jnl in self.doc['accountDetailsAndActivity']['accountActivity'] \
                           ['postedTransactionJournals']:
            tdate = jnl['columns'][0]['activityColumn'][0]
            label = jnl['columns'][1]['activityColumn'][0]
            amount = jnl['columns'][3]['activityColumn'][0]
            xdescs = dict((x['label'], x['value'][0])
                          for x in jnl['extendedDescriptions'])
            pdate = xdescs[u'Posted Date :']
            ref = xdescs.get(u'Reference Number:') or u''

            if amount.startswith(u'(') and amount.endswith(u')'):
                amount = AmTr.decimal_amount(amount[1:-1])
            else:
                amount = -AmTr.decimal_amount(amount)
            label = clean_label(label)

            trans = Transaction(ref)
            trans.date = datetime.strptime(tdate, '%m-%d-%Y')
            trans.rdate = datetime.strptime(pdate, '%m-%d-%Y')
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = label
            trans.label = label
            trans.amount = amount
            yield trans
Ejemplo n.º 12
0
    def get_history(self):
        i = 0
        ignore = False
        for tr in self.doc.xpath(
                '//table[@cellpadding="1"]/tr') + self.doc.xpath(
                    '//tr[@class="rowClick" or @class="rowHover"]'):
            tds = tr.findall('td')

            if len(tds) < 4:
                continue

            # if there are more than 4 columns, ignore the first one.
            i = min(len(tds) - 4, 1)

            if tr.attrib.get('class', '') == 'DataGridHeader':
                if tds[2].text == u'Titulaire':
                    ignore = True
                else:
                    ignore = False
                continue

            if ignore:
                continue

            # Remove useless details
            detail = tr.cssselect('div.detail')
            if len(detail) > 0:
                detail[0].drop_tree()

            t = Transaction()

            date = u''.join([txt.strip() for txt in tds[i + 0].itertext()])
            raw = u' '.join([txt.strip() for txt in tds[i + 1].itertext()])
            debit = u''.join([txt.strip() for txt in tds[-2].itertext()])
            credit = u''.join([txt.strip() for txt in tds[-1].itertext()])

            t.parse(date, re.sub(r'[ ]+', ' ', raw))

            card_debit_date = self.doc.xpath(
                u'//span[@id="MM_HISTORIQUE_CB_m_TableTitle3_lblTitle"] | //label[contains(text(), "débiter le")]'
            )
            if card_debit_date:
                t.rdate = Date(dayfirst=True).filter(date)
                m = re.search('(\d{2}\/\d{2}\/\d{4})', card_debit_date[0].text)
                assert m
                t.date = Date(dayfirst=True).filter(m.group(1))
            if t.date is NotAvailable:
                continue
            if 'tot dif' in t.raw.lower():
                t.deleted = True
            t.set_amount(credit, debit)
            yield t

            i += 1
Ejemplo n.º 13
0
    def iter_history(self, account):
        for hist in self.doc['operationsIndividuelles']:
            if len(hist['instructions']) > 0:
                if self.belongs(hist['instructions'], account):
                    tr = Transaction()
                    tr.amount = self.get_amount(hist['instructions'], account)
                    tr.rdate = datetime.strptime(
                        hist['dateComptabilisation'].split('T')[0], '%Y-%m-%d')
                    tr.date = tr.rdate
                    tr.label = hist[
                        'libelleOperation'] if 'libelleOperation' in hist else hist[
                            'libelleCommunication']
                    tr.type = Transaction.TYPE_UNKNOWN

                    # Bypassed because we don't have the ISIN code
                    # tr.investments = []
                    # for ins in hist['instructions']:
                    #     inv = Investment()
                    #     inv.code = NotAvailable
                    #     inv.label = ins['nomFonds']
                    #     inv.description = ' '.join([ins['type'], ins['nomDispositif']])
                    #     inv.vdate = datetime.strptime(ins.get('dateVlReel', ins.get('dateVlExecution')).split('T')[
                    # 0], '%Y-%m-%d')
                    #     inv.valuation = Decimal(ins['montantNet'])
                    #     inv.quantity = Decimal(ins['nombreDeParts'])
                    #     inv.unitprice = inv.unitvalue = Decimal(ins['vlReel'])
                    #     tr.investments.append(inv)

                    yield tr
Ejemplo n.º 14
0
    def unsorted_trans(self):
        for jnl in self.doc['accountDetailsAndActivity']['accountActivity'] \
                           ['postedTransactionJournals']:
            tdate = jnl['columns'][0]['activityColumn'][0]
            label = jnl['columns'][1]['activityColumn'][0]
            amount = jnl['columns'][3]['activityColumn'][0]
            xdescs = dict((x['label'], x['value'][0])
                          for x in jnl['extendedDescriptions'])
            pdate = xdescs['Posted Date :']
            ref = xdescs.get('Reference Number:') or ''

            if amount.startswith('(') and amount.endswith(')'):
                amount = AmTr.decimal_amount(amount[1:-1])
            else:
                amount = -AmTr.decimal_amount(amount)
            label = clean_label(label)

            trans = Transaction(ref)
            trans.date = datetime.strptime(tdate, '%m-%d-%Y')
            trans.rdate = datetime.strptime(pdate, '%m-%d-%Y')
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = label
            trans.label = label
            trans.amount = amount
            yield trans
Ejemplo n.º 15
0
    def read_transaction(self, pos, date_from, date_to):
        startPos = pos

        pos, tdate = self.read_date(pos)
        pos, pdate = self.read_date(pos)

        # Early check to call read_multiline_desc() only when needed.
        if tdate is None:
            return startPos, None

        pos, desc = self.read_multiline_desc(pos)
        pos, amount = self.read_amount(pos)

        if desc is None or amount is None:
            return startPos, None
        else:
            # Sometimes one date is missing.
            pdate = pdate or tdate

            tdate = closest_date(tdate, date_from, date_to)
            pdate = closest_date(pdate, date_from, date_to)

            trans = Transaction()
            trans.date = tdate
            trans.rdate = pdate
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = -amount
            return pos, trans
Ejemplo n.º 16
0
    def read_cash_transaction(self, pos, date_from, date_to):
        INDENT_BALANCE = 520
        INDENT_WITHDRAWAL = 470

        startPos = pos

        pos, date = self.read_date(pos)
        pos, _ = self.read_star(pos)
        pos, desc = self.read_multiline_desc(pos)
        pos, amount = self.read_indent_amount(
            pos,
            range_plus = (0, INDENT_WITHDRAWAL),
            range_minus = (INDENT_WITHDRAWAL, INDENT_BALANCE),
            range_skip = (INDENT_BALANCE, 9999))

        if desc is None or date is None or amount is None:
            return startPos, None
        else:
            date = closest_date(date, date_from, date_to)

            trans = Transaction(u'')
            trans.date = date
            trans.rdate = date
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = amount
            return pos, trans
Ejemplo n.º 17
0
    def read_card_transaction(self, pos, date_from, date_to):
        INDENT_CHARGES = 520

        startPos = pos

        pos, tdate = self.read_date(pos)
        pos, pdate_layout = self.read_layout_tm(pos)
        pos, pdate = self.read_date(pos)
        pos, ref_layout = self.read_layout_tm(pos)
        pos, ref = self.read_ref(pos)
        pos, desc = self.read_multiline_desc(pos)
        pos, amount = self.read_indent_amount(
            pos,
            range_minus = (INDENT_CHARGES, 9999),
            range_plus = (0, INDENT_CHARGES))

        if tdate is None or pdate_layout is None or pdate is None \
        or ref_layout is None or ref is None or desc is None or amount is None:
            return startPos, None
        else:
            tdate = closest_date(tdate, date_from, date_to)
            pdate = closest_date(pdate, date_from, date_to)

            trans = Transaction(ref)
            trans.date = tdate
            trans.rdate = pdate
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = amount
            return pos, trans
Ejemplo n.º 18
0
    def read_transaction(self, pos, date_from, date_to):
        startPos = pos
        pos, tdate = self.read_date(pos)
        pos, pdate_layout = self.read_layout_td(pos)
        pos, pdate = self.read_date(pos)
        pos, ref_layout = self.read_layout_td(pos)
        pos, ref = self.read_ref(pos)
        pos, desc_layout = self.read_layout_td(pos)
        pos, desc = self.read_text(pos)
        pos, amount_layout = self.read_layout_td(pos)
        pos, amount = self.read_amount(pos)
        if tdate is None or pdate is None \
        or desc is None or amount is None or amount == 0:
            return startPos, None
        else:
            tdate = closest_date(tdate, date_from, date_to)
            pdate = closest_date(pdate, date_from, date_to)
            desc = u' '.join(desc.split())

            trans = Transaction(ref or u'')
            trans.date = tdate
            trans.rdate = pdate
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = amount
            return pos, trans
Ejemplo n.º 19
0
    def iter_transactions(self):
        for row in self.doc.xpath('//tr/th[@headers='
                                  '"postedHeader dateHeader"]/..'):
            date = row.xpath('th[@headers="postedHeader '
                             'dateHeader"]/text()')[0]
            desc = row.xpath('td[@headers="postedHeader '
                             'descriptionHeader"]/span/text()')[0]
            deposit = row.xpath('td[@headers="postedHeader '
                                'depositsConsumerHeader"]/span/text()')[0]
            withdraw = row.xpath('td[@headers="postedHeader '
                                 'withdrawalsConsumerHeader"]/span/text()')[0]

            date = datetime.datetime.strptime(date, '%m/%d/%y')

            desc = clean_label(desc)

            deposit = deposit.strip()
            deposit = AmTr.decimal_amount(deposit or '0')
            withdraw = withdraw.strip()
            withdraw = AmTr.decimal_amount(withdraw or '0')

            amount = deposit - withdraw

            trans = Transaction(u'')
            trans.date = date
            trans.rdate = date
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = amount
            yield trans
Ejemplo n.º 20
0
    def iter_transactions(self):
        for row in self.doc.xpath('//tr/th[@headers='
                                  '"postedHeader transactionDateHeader"]/..'):
            tdate = row.xpath('th[@headers="postedHeader '
                              'transactionDateHeader"]/text()')[0]
            pdate = row.xpath('td[@headers="postedHeader '
                              'postingDateHeader"]/text()')[0]
            desc = row.xpath('td[@headers="postedHeader '
                              'descriptionHeader"]/span/text()')[0]
            ref = row.xpath('td[@headers="postedHeader '
                             'descriptionHeader"]/text()')[0]
            amount = row.xpath('td[@headers="postedHeader '
                               'amountHeader"]/text()')[0]

            tdate = datetime.datetime.strptime(tdate, '%m/%d/%y')
            pdate = datetime.datetime.strptime(pdate, '%m/%d/%y')

            desc = clean_label(desc)

            ref = re.match('.*<REFERENCE ([^>]+)>.*', ref).group(1)

            if amount.startswith('+'):
                amount = AmTr.decimal_amount(amount[1:])
            else:
                amount = -AmTr.decimal_amount(amount)

            trans = Transaction(ref)
            trans.date = tdate
            trans.rdate = pdate
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = amount
            yield trans
Ejemplo n.º 21
0
 def iter_transactions(self):
     for li in self.doc.xpath('//section[@class="transactions"]//div/li'):
         date = li.xpath('p[@data-type="date"]//text()')[0].strip()
         label = li.xpath('p[@data-type="description"]//text()')[0].strip()
         amount = li.xpath('p[@data-type="amount"]//text()')[0].strip()
         t = Transaction()
         t.date = datetime.strptime(date, '%m/%d/%Y')
         t.rdate = datetime.strptime(date, '%m/%d/%Y')
         t.type = Transaction.TYPE_UNKNOWN
         t.raw = unicode(label)
         t.label = unicode(label)
         t.amount = -AmTr.decimal_amount(amount)
         yield t
Ejemplo n.º 22
0
    def iter_history(self, account):
        if account.id not in self.histories:
            histories = []
            self.open('/user/%s/project/%s/activity' % (self.users['userId'], account.number), method="OPTIONS")
            for activity in [acc for acc in self.request('/user/%s/project/%s/activity' % (self.users['userId'], account.number), headers=self.request_headers)['activities'] \
                             if acc['details'] is not None]:
                m = re.search(u'([\d\,]+)(?=[\s]+€|[\s]+euro)', activity['details'])
                if "Souscription" not in activity['title'] and not m:
                    continue

                t = Transaction()
                t.label = "%s - %s" % (" ".join(activity['type'].split("_")), activity['title'])
                t.date = Date().filter(activity['date'])
                t.type = Transaction.TYPE_BANK
                amount = account._startbalance if not m else "-%s" % m.group(1) if "FRAIS" in activity['type'] else m.group(1)
                t.amount = CleanDecimal(replace_dots=True).filter(amount)

                histories.append(t)

            self.histories[account.id] = histories
        return self.histories[account.id]
Ejemplo n.º 23
0
 def iter_transactions(self):
     for ntrans in reversed(self.doc.xpath('//TRANSACTION')):
         desc = u' '.join(
             ntrans.xpath('TRANSDESCRIPTION/text()')[0].split())
         tdate = u''.join(ntrans.xpath('TRANSACTIONDATE/text()'))
         pdate = u''.join(ntrans.xpath('POSTDATE/text()'))
         t = Transaction()
         t.date = datetime.strptime(tdate, '%m/%d/%Y')
         t.rdate = datetime.strptime(pdate or tdate, '%m/%d/%Y')
         t.type = Transaction.TYPE_UNKNOWN
         t.raw = desc
         t.label = desc
         t.amount = -AmTr.decimal_amount(ntrans.xpath('AMOUNT/text()')[0])
         yield t
Ejemplo n.º 24
0
    def iter_history(self, account):
        for hist in self.doc['operationsIndividuelles']:
            if len(hist['instructions']) > 0:
                if self.belongs(hist['instructions'], account):
                    tr = Transaction()
                    tr.amount = self.get_amount(hist['instructions'], account)
                    tr.rdate = datetime.strptime(hist['dateComptabilisation'].split('T')[0], '%Y-%m-%d')
                    tr.date = tr.rdate
                    tr.label = hist['libelleOperation'] if 'libelleOperation' in hist else hist['libelleCommunication']
                    tr.type = Transaction.TYPE_UNKNOWN

                    # Bypassed because we don't have the ISIN code
                    # tr.investments = []
                    # for ins in hist['instructions']:
                    #     inv = Investment()
                    #     inv.code = NotAvailable
                    #     inv.label = ins['nomFonds']
                    #     inv.description = ' '.join([ins['type'], ins['nomDispositif']])
                    #     inv.vdate = datetime.strptime(ins.get('dateVlReel', ins.get('dateVlExecution')).split('T')[
                    # 0], '%Y-%m-%d')
                    #     inv.valuation = Decimal(ins['montantNet'])
                    #     inv.quantity = Decimal(ins['nombreDeParts'])
                    #     inv.unitprice = inv.unitvalue = Decimal(ins['vlReel'])
                    #     tr.investments.append(inv)

                    yield tr
Ejemplo n.º 25
0
    def iter_history(self, account):
        if account.id not in self.histories:
            histories = []
            self.open('/user/%s/project/%s/activity' %
                      (self.users['userId'], account.number),
                      method="OPTIONS")
            for activity in [acc for acc in self.request('/user/%s/project/%s/activity' % (self.users['userId'], account.number), headers=self.request_headers)['activities'] \
                             if acc['details'] is not None]:
                m = re.search(u'([\d\,]+)(?=[\s]+€|[\s]+euro)',
                              activity['details'])
                if "Souscription" not in activity['title'] and not m:
                    continue

                t = Transaction()
                t.label = "%s - %s" % (" ".join(
                    activity['type'].split("_")), activity['title'])
                t.date = Date().filter(activity['date'])
                t.type = Transaction.TYPE_BANK
                amount = account._startbalance if not m else "-%s" % m.group(
                    1) if "FRAIS" in activity['type'] else m.group(1)
                t.amount = CleanDecimal(replace_dots=True).filter(amount)

                histories.append(t)

            self.histories[account.id] = histories
        return self.histories[account.id]
Ejemplo n.º 26
0
 def iter_recent(self):
     records = json.loads(
         self.doc.xpath(
             '//div[@id="completedActivityRecords"]//input[1]/@value')[0])
     recent = [x for x in records if x['PDF_LOC'] is None]
     for rec in sorted(recent, ActivityPage.cmp_records, reverse=True):
         desc = u' '.join(rec['TRANS_DESC'].split())
         trans = Transaction((rec['REF_NUM'] or u'').strip())
         trans.date = ActivityPage.parse_date(rec['TRANS_DATE'])
         trans.rdate = ActivityPage.parse_date(rec['POST_DATE'])
         trans.type = Transaction.TYPE_UNKNOWN
         trans.raw = desc
         trans.label = desc
         trans.amount = -AmTr.decimal_amount(rec['TRANS_AMOUNT'])
         yield trans
Ejemplo n.º 27
0
    def get_history(self, account):
        if not account._consultable:
            raise NotImplementedError()

        offset = 0
        next_page = True
        while next_page:
            r = self.open(
                '/transactionnel/services/applications/operations/get/%(number)s/%(nature)s/00/%(currency)s/%(startDate)s/%(endDate)s/%(offset)s/%(limit)s'
                % {
                    'number': account._number,
                    'nature': account._nature,
                    'currency': account.currency,
                    'startDate': '2000-01-01',
                    'endDate': date.today().strftime('%Y-%m-%d'),
                    'offset': offset,
                    'limit': 50
                })
            next_page = False
            offset += 50
            next_page = True
            for op in r.json()['content']['operations']:
                t = Transaction()
                t.id = op['id']
                t.amount = Decimal(str(op['montant']))
                t.date = date.fromtimestamp(
                    op.get('dateDebit', op.get('dateOperation')) / 1000)
                t.rdate = date.fromtimestamp(
                    op.get('dateOperation', op.get('dateDebit')) / 1000)
                t.vdate = date.fromtimestamp(
                    op.get('dateValeur',
                           op.get('dateDebit', op.get('dateOperation'))) /
                    1000)
                if 'categorie' in op:
                    t.category = op['categorie']
                t.label = op['libelle']
                t.raw = ' '.join([op['libelle']] + op['details'])
                yield t
Ejemplo n.º 28
0
    def get_history(self, account):
        if not account._consultable:
            raise NotImplementedError()

        offset = 0
        next_page = True
        seen = set()
        while next_page:
            r = self.api_open(
                "/transactionnel/services/applications/operations/get/%(number)s/%(nature)s/00/%(currency)s/%(startDate)s/%(endDate)s/%(offset)s/%(limit)s"
                % {
                    "number": account._number,
                    "nature": account._nature,
                    "currency": account.currency,
                    "startDate": "2000-01-01",
                    "endDate": date.today().strftime("%Y-%m-%d"),
                    "offset": offset,
                    "limit": 50,
                }
            )
            next_page = False
            offset += 50
            transactions = []
            for op in reversed(r.json()["content"]["operations"]):
                next_page = True
                t = Transaction()
                if op["id"] in seen:
                    raise ParseError("There are several transactions with the same ID, probably an infinite loop")
                t.id = op["id"]
                seen.add(t.id)
                t.amount = Decimal(str(op["montant"]))
                t.date = date.fromtimestamp(op.get("dateDebit", op.get("dateOperation")) / 1000)
                t.rdate = date.fromtimestamp(op.get("dateOperation", op.get("dateDebit")) / 1000)
                t.vdate = date.fromtimestamp(op.get("dateValeur", op.get("dateDebit", op.get("dateOperation"))) / 1000)
                if "categorie" in op:
                    t.category = op["categorie"]
                t.label = op["libelle"]
                t.raw = " ".join([op["libelle"]] + op["details"])
                transactions.append(t)

            # Transactions are unsorted
            for t in sorted(transactions, key=lambda t: t.rdate, reverse=True):
                yield t
Ejemplo n.º 29
0
    def iter_history(self, account):
        for hist in self.doc['operationsIndividuelles']:
            if len(hist['instructions']) > 0:
                if self.belongs(hist['instructions'], account):
                    tr = Transaction()
                    tr.amount = self.get_amount(hist['instructions'], account)
                    tr.rdate = datetime.strptime(hist['dateComptabilisation'].split('T')[0], '%Y-%m-%d')
                    tr.date = tr.rdate
                    tr.label = hist.get('libelleOperation') or hist['libelleCommunication']
                    tr.type = Transaction.TYPE_UNKNOWN

                    yield tr
Ejemplo n.º 30
0
    def get_history(self, account):
        if not account._consultable:
            raise NotImplementedError()

        if account._univers != self.current_univers:
            self.move_to_univers(account._univers)
        offset = 0
        next_page = True
        seen = set()
        while next_page:
            r = self.api_open('/transactionnel/services/applications/operations/get/%(number)s/%(nature)s/00/%(currency)s/%(startDate)s/%(endDate)s/%(offset)s/%(limit)s' %
                          {'number': account._number,
                           'nature': account._nature,
                           'currency': account.currency,
                           'startDate': '2000-01-01',
                           'endDate': date.today().strftime('%Y-%m-%d'),
                           'offset': offset,
                           'limit': 50
                          })
            next_page = False
            offset += 50
            transactions = []
            for op in reversed(r.json()['content']['operations']):
                next_page = True
                t = Transaction()
                if op['id'] in seen:
                    raise ParseError('There are several transactions with the same ID, probably an infinite loop')
                t.id = op['id']
                seen.add(t.id)
                t.amount = Decimal(str(op['montant']))
                t.date = date.fromtimestamp(op.get('dateDebit', op.get('dateOperation'))/1000)
                t.rdate = date.fromtimestamp(op.get('dateOperation', op.get('dateDebit'))/1000)
                t.vdate = date.fromtimestamp(op.get('dateValeur', op.get('dateDebit', op.get('dateOperation')))/1000)
                if 'categorie' in op:
                    t.category = op['categorie']
                t.label = op['libelle']
                t.raw = ' '.join([op['libelle']] + op['details'])
                transactions.append(t)

            # Transactions are unsorted
            for t in sorted(transactions, key=lambda t: t.rdate, reverse=True):
                yield t
Ejemplo n.º 31
0
 def iter_transactions(self):
     for li in self.doc.xpath('//section[@class="transactions"]//div/li'):
         date = li.xpath('p[@data-type="date"]//text()')[0].strip()
         label = li.xpath('p[@data-type="description"]//text()')[0].strip()
         amount = li.xpath('p[@data-type="amount"]//text()')[0].strip()
         t = Transaction()
         t.date = datetime.strptime(date, '%m/%d/%Y')
         t.rdate = datetime.strptime(date, '%m/%d/%Y')
         t.type = Transaction.TYPE_UNKNOWN
         t.raw = unicode(label)
         t.label = unicode(label)
         t.amount = -AmTr.decimal_amount(amount)
         yield t
Ejemplo n.º 32
0
 def iter_transactions(self):
     for ntrans in reversed(self.doc.xpath('//TRANSACTION')):
         desc = u' '.join(ntrans.xpath(
             'TRANSDESCRIPTION/text()')[0].split())
         tdate = u''.join(ntrans.xpath('TRANSACTIONDATE/text()'))
         pdate = u''.join(ntrans.xpath('POSTDATE/text()'))
         t = Transaction()
         t.date = datetime.strptime(tdate, '%m/%d/%Y')
         t.rdate = datetime.strptime(pdate or tdate, '%m/%d/%Y')
         t.type = Transaction.TYPE_UNKNOWN
         t.raw = desc
         t.label = desc
         t.amount = -AmTr.decimal_amount(ntrans.xpath('AMOUNT/text()')[0])
         yield t
Ejemplo n.º 33
0
 def iter_recent(self):
     records = json.loads(self.doc.xpath(
         '//div[@id="completedActivityRecords"]//input[1]/@value')[0])
     recent = [x for x in records if x['PDF_LOC'] is None]
     for rec in sorted(recent, ActivityPage.cmp_records, reverse=True):
         desc = u' '.join(rec['TRANS_DESC'].split())
         trans = Transaction((rec['REF_NUM'] or u'').strip())
         trans.date = ActivityPage.parse_date(rec['TRANS_DATE'])
         trans.rdate = ActivityPage.parse_date(rec['POST_DATE'])
         trans.type = Transaction.TYPE_UNKNOWN
         trans.raw = desc
         trans.label = desc
         trans.amount = -AmTr.decimal_amount(rec['TRANS_AMOUNT'])
         yield trans
Ejemplo n.º 34
0
 def iter_transactions(self):
     for ntrans in reversed(self.doc.xpath('//TRANSACTION')):
         desc = u' '.join(ntrans.xpath(
             'TRANSDESCRIPTION/text()')[0].split())
         tdate = u''.join(ntrans.xpath('TRANSACTIONDATE/text()'))
         pdate = u''.join(ntrans.xpath('POSTDATE/text()'))
         # Skip transactions which are not posted,
         # because they are not accounted for in balance calculation.
         if not pdate:
             continue
         t = Transaction()
         t.date = datetime.strptime(tdate, '%m/%d/%Y')
         t.rdate = datetime.strptime(pdate, '%m/%d/%Y')
         t.type = Transaction.TYPE_UNKNOWN
         t.raw = desc
         t.label = desc
         t.amount = -AmTr.decimal_amount(ntrans.xpath('AMOUNT/text()')[0])
         yield t
Ejemplo n.º 35
0
    def iter_history_recent(self, account):
        self.start()
        if account.id != self._account_id():
            raise AccountNotFound()
        self._account_link().click()
        self.wait_ajax()
        for span in self.find('span.cM-maximizeButton'):
            span.click()
        for tr in self.find('tr.payments,tr.purchase'):
            trdata = lambda n: tr.find_element_by_css_selector(
                        'td.cT-bodyTableColumn%i span.cT-line1' % n).text
            treid = tr.get_attribute('id').replace('rowID', 'rowIDExt')
            tredata = {}
            for tre in self.find('tr#%s' % treid):
                labels = [x.text for x in tre.find_elements_by_css_selector(
                                                    'div.cT-labelItem')]
                values = [x.text for x in tre.find_elements_by_css_selector(
                                                    'div.cT-valueItem')]
                tredata = dict(zip(labels, values))

            ref = tredata.get(u'Reference Number:', u'')
            tdate = trdata(1)
            pdate = tredata.get(u'Posted Date :', tdate)
            desc = clean_label(trdata(2))
            amount = trdata(4)

            tdate = datetime.datetime.strptime(tdate, '%m-%d-%Y')
            pdate = datetime.datetime.strptime(pdate, '%m-%d-%Y')

            if amount.startswith(u'(') and amount.endswith(u')'):
                amount = AmTr.decimal_amount(amount[1:-1])
            else:
                amount = -AmTr.decimal_amount(amount)

            trans = Transaction(ref)
            trans.date = tdate
            trans.rdate = pdate
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = amount
            yield trans

        self.finish()
Ejemplo n.º 36
0
 def get_transactions(self, index):
     i = 0
     for table in self.document.xpath('//table'):
         try:
             textdate = table.find('.//td[@class="date"]').text_content()
         except AttributeError:
             continue
         # Do not parse transactions already parsed
         if i < index:
             i += 1
             continue
         if textdate == 'hier':
             textdate = (date.today() - timedelta(days=1)).strftime('%d/%m/%Y')
         elif textdate == "aujourd'hui":
             textdate = date.today().strftime('%d/%m/%Y')
         else:
             frenchmonth = textdate.split(' ')[1]
             month = self.monthvalue[frenchmonth]
             textdate = textdate.replace(' ', '')
             textdate = textdate.replace(frenchmonth, '/%s/' %month)
         # We use lower for compatibility with old website
         textraw = table.find('.//td[@class="lbl"]').text_content().strip().lower()
         # The id will be rewrite
         op = Transaction(1)
         amount = op.clean_amount(table.xpath('.//td[starts-with(@class, "amount")]')[0].text_content())
         id = hashlib.md5(textdate.encode('utf-8') + textraw.encode('utf-8')
                 + amount.encode('utf-8')).hexdigest()
         op.id = id
         op.parse(date = date(*reversed([int(x) for x in textdate.split('/')])),
                 raw = textraw)
         category = table.find('.//td[@class="picto"]/span')
         category = unicode(category.attrib['class'].split('-')[0].lower())
         try:
             op.category = self.catvalue[category]
         except:
             op.category = category
         op.amount = Decimal(amount)
         yield op
Ejemplo n.º 37
0
    def iter_history(self, account):
        # Load i18n for type translation
        self.i18np.open(lang1=self.LANG, lang2=self.LANG).load_i18n()

        # For now detail for each account is not available. History is global for all accounts and very simplist
        data = {'clang': self.LANG,
                'ctcc': self.CTCC,
                'login': self.username,
                'session': self.sessionId}

        for trans in self.historyp.open(data=data).get_transactions():
            t = Transaction()
            t.id = trans["referenceOperationIndividuelle"]
            t.date = datetime.strptime(trans["dateHeureSaisie"], "%d/%m/%Y")
            t.rdate = datetime.strptime(trans["dateHeureSaisie"], "%d/%m/%Y")
            t.type = Transaction.TYPE_DEPOSIT if trans["montantNetEuro"] > 0 else Transaction.TYPE_PAYBACK
            t.raw = trans["typeOperation"]
            try:
                t.label = self.i18n["OPERATION_TYPE_" + trans["casDeGestion"]]
            except KeyError:
                t.label = self.i18n["OPERATION_TYPE_TOTAL_" + trans["casDeGestion"]]
            t.amount = Decimal(trans["montantNetEuro"]).quantize(Decimal('.01'))
            yield t
Ejemplo n.º 38
0
    def _parse_transaction(self, payment):
        transaction = Transaction()
        transaction_id = Dict('transaction_number', default=None)(payment)
        # Check if transaction_id is None which indicates failed transaction
        if transaction_id is None:
            return
        transaction.id = transaction_id
        transaction.date = DateTime(Dict('executed_at'))(payment)
        transaction.rdate = DateTime(Dict('created_at'))(payment)

        types = {
            'ORDER': Transaction.TYPE_CARD,  # order on lunchr website
            'LUNCHR_CARD_PAYMENT': Transaction.TYPE_CARD,  # pay in shop
            'MEAL_VOUCHER_CREDIT': Transaction.TYPE_DEPOSIT,
            # type can be null for refunds
        }
        transaction.type = types.get(Dict('type')(payment), Transaction.TYPE_UNKNOWN)
        transaction.label = Dict('name')(payment)
        transaction.amount = CleanDecimal(Dict('amount/value'))(payment)
        return transaction
Ejemplo n.º 39
0
    def get_transactions(self):
        table = self.document.findall('//tbody')[0]
        for tr in table.xpath('tr'):
            textdate = tr.find('td[@class="op_date"]').text_content()
            textraw = tr.find('td[@class="op_label"]').text_content().strip()
            # The id will be rewrite
            op = Transaction(1)
            amount = op.clean_amount(
                tr.find('td[@class="op_amount"]').text_content())
            id = hashlib.md5(textdate + textraw.encode('utf-8') +
                             amount.encode('utf-8')).hexdigest()
            op.id = id
            op.parse(date=date(*reversed([int(x)
                                          for x in textdate.split('/')])),
                     raw=textraw)
            # force the use of website category
            op.category = unicode(tr.find('td[@class="op_type"]').text)

            op.amount = Decimal(amount)

            yield op
Ejemplo n.º 40
0
    def get_transactions(self):
        table = self.document.findall('//tbody')[0]
        for tr in table.xpath('tr'):
            textdate = tr.find('td[@class="op_date"]').text_content()
            textraw = tr.find('td[@class="op_label"]').text_content().strip()
            # The id will be rewrite
            op = Transaction(1)
            amount = op.clean_amount(tr.find('td[@class="op_amount"]').text_content())
            id = hashlib.md5(textdate + textraw.encode('utf-8') + amount.encode('utf-8')).hexdigest()
            op.id = id
            op.parse(date = date(*reversed([int(x) for x in textdate.split('/')])),
                     raw = textraw)
            # force the use of website category
            op.category = unicode(tr.find('td[@class="op_type"]').text)

            op.amount = Decimal(amount)

            yield op
Ejemplo n.º 41
0
    def iter_history_recent(self, account):
        self.start()
        if account.id != self._account_id():
            raise AccountNotFound()
        self._account_link().click()
        self.wait_ajax()
        for span in self.find('span.cM-maximizeButton'):
            span.click()
        for tr in self.find('tr.payments,tr.purchase'):
            trdata = lambda n: tr.find_element_by_css_selector(
                        'td.cT-bodyTableColumn%i span.cT-line1' % n).text
            treid = tr.get_attribute('id').replace('rowID', 'rowIDExt')
            tredata = {}
            for tre in self.find('tr#%s' % treid):
                labels = [x.text for x in tre.find_elements_by_css_selector(
                                                    'div.cT-labelItem')]
                values = [x.text for x in tre.find_elements_by_css_selector(
                                                    'div.cT-valueItem')]
                tredata = dict(zip(labels, values))

            ref = tredata.get(u'Reference Number:', u'')
            tdate = trdata(1)
            pdate = tredata.get(u'Posted Date :', tdate)
            desc = clean_label(trdata(2))
            amount = trdata(4)

            tdate = datetime.datetime.strptime(tdate, '%m-%d-%Y')
            pdate = datetime.datetime.strptime(pdate, '%m-%d-%Y')

            if amount.startswith(u'(') and amount.endswith(u')'):
                amount = AmTr.decimal_amount(amount[1:-1])
            else:
                amount = -AmTr.decimal_amount(amount)

            trans = Transaction(ref)
            trans.date = tdate
            trans.rdate = pdate
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = desc
            trans.label = desc
            trans.amount = amount
            yield trans

        self.finish()
Ejemplo n.º 42
0
    def unsorted_trans(self):
        for jnl in self.doc["accountDetailsAndActivity"]["accountActivity"]["postedTransactionJournals"]:
            tdate = jnl["columns"][0]["activityColumn"][0]
            label = jnl["columns"][1]["activityColumn"][0]
            amount = jnl["columns"][3]["activityColumn"][0]
            xdescs = dict((x["label"], x["value"][0]) for x in jnl["extendedDescriptions"])
            pdate = xdescs[u"Posted Date :"]
            ref = xdescs.get(u"Reference Number:") or u""

            if amount.startswith(u"(") and amount.endswith(u")"):
                amount = AmTr.decimal_amount(amount[1:-1])
            else:
                amount = -AmTr.decimal_amount(amount)
            label = clean_label(label)

            trans = Transaction(ref)
            trans.date = datetime.strptime(tdate, "%m-%d-%Y")
            trans.rdate = datetime.strptime(pdate, "%m-%d-%Y")
            trans.type = Transaction.TYPE_UNKNOWN
            trans.raw = label
            trans.label = label
            trans.amount = amount
            yield trans
Ejemplo n.º 43
0
    def iter_history(self, data):
        for hist in self.doc['operationsIndividuelles']:
            if len(hist['instructions']) > 0:
                if 'nomDispositif' in hist['instructions'][0] and \
                   hist['instructions'][0]['nomDispositif'] + hist['instructions'][0]['codeDispositif'] == data['acc'].label + data['acc'].id:
                    tr = Transaction()
                    tr.amount = Decimal(hist['montantNet']) + Decimal(
                        hist['montantNetAbondement'])
                    tr.rdate = datetime.strptime(
                        hist['dateComptabilisation'].split('T')[0], '%Y-%m-%d')
                    tr.date = tr.rdate
                    tr.label = hist[
                        'libelleOperation'] if 'libelleOperation' in hist else hist[
                            'libelleCommunication']
                    tr.type = Transaction.TYPE_UNKNOWN
                    yield tr

        if data['total'] > data['params']['limit'] * (
                data['params']['offset'] + 1):
            offset = data['params']['offset']
            self.url = self.url.replace('&offset=' + str(offset),
                                        '&offset=' + str(offset + 1))
            data['params']['offset'] += 1
            raise NextPage(self.url)
Ejemplo n.º 44
0
    def iter_history(self, account):
        if account not in self.histories:
            histories = []
            for activity in self.request(
                    '/user/%s/project/%s/activity' %
                (self.users['userId'], account.number))['activities']:
                m = re.search(u'([\d\.]+)(?=[\s]+€|[\s]+euro)',
                              activity['details'])
                if "Souscription" not in activity['title'] and not m:
                    continue

                t = Transaction()
                t.label = "%s - %s" % (" ".join(
                    activity['type'].split("_")), activity['title'])
                t.date = Date().filter(activity['date'])
                t.type = Transaction.TYPE_BANK
                amount = account._startbalance if not m else "-%s" % m.group(
                    1) if "FRAIS" in activity['type'] else m.group(1)
                t.amount = CleanDecimal().filter(amount)

                histories.append(t)

            self.histories[account] = histories
        return self.histories[account]
Ejemplo n.º 45
0
    def generate_single_transaction(self):
        """
        Generate a fake transaction.
        """
        now = datetime.datetime.now()

        transaction = Transaction()
        transaction.type = self.generate_type()

        n = random.randrange(100)
        if n < 2:
            # with a 2% rate, generate a special operation to test duplicates
            # (happening on 4th of current month).
            transaction.amount = Decimal(-300.0)
            transaction.label = "Loyer"
            transaction.raw = "Loyer habitation"
            transaction.date = self.generate_date(4, 4, now.month, now.month)
            return transaction

        transaction.date = self.generate_date(1, min(now.day, 28), 1,
                                              max(1, now.month - 1))

        if n < 15:
            transaction.label, transaction.raw = self.generate_label(
                positive=True)
            transaction.amount = Decimal(
                random.randint(100, 800) + random.random())
            return transaction

        if n < 30:
            transaction.rdate = transaction.date
        elif n < 60:
            transaction.rdate = None

        transaction.amount = Decimal(random.randint(-60, 0) + random.random())
        transaction.label, transaction.raw = self.generate_label()
        transaction.type = self.generate_type()
        return transaction
Ejemplo n.º 46
0
    def iter_history(self, account):
        if not self.islogged:
            self.login()

        page = "https://www.cmb.fr/domiweb/prive/particulier/releve/"
        if account._cmbtype == 'D':
            page += "10-releve.act"
        else:
            page += "2-releve.act"
        page += "?noPageReleve=1&indiceCompte="
        page += account._cmbvaleur
        page += "&typeCompte="
        page += account._cmbvaleur2
        page += "&deviseOrigineEcran=EUR"

        data = self.browser.open(page).content
        parser = etree.HTMLParser()
        tree = etree.parse(StringIO(data), parser)

        tables = tree.xpath('/html/body/table')
        if len(tables) == 0:
            title = tree.xpath('/html/head/title')[0].text
            if title == u"Utilisateur non identifié":
                self.login()
                data = self.browser.open(page).content

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

        i = 0

        for table in tables:
            if table.get('id') != "tableMouvements":
                continue
            for tr in table.getiterator('tr'):
                if (tr.get('class') != 'LnTit' and tr.get('class') != 'LnTot'):
                    operation = Transaction(i)
                    td = tr.xpath('td')

                    div = td[1].xpath('div')
                    d = div[0].text.split('/')
                    operation.date = date(*reversed([int(x) for x in d]))

                    div = td[2].xpath('div')
                    label = div[0].xpath('a')[0].text.replace('\n', '')
                    operation.raw = unicode(' '.join(label.split()))
                    for pattern, _type, _label in self.LABEL_PATTERNS:
                        mm = pattern.match(operation.raw)
                        if mm:
                            operation.type = _type
                            operation.label = sub('[ ]+', ' ', _label %
                                                  mm.groupdict()).strip()
                            break

                    amount = td[3].text
                    if amount.count(',') != 1:
                        amount = td[4].text
                        amount = amount.replace(',', '.').replace(u'\xa0', '')
                        operation.amount = Decimal(amount)
                    else:
                        amount = amount.replace(',', '.').replace(u'\xa0', '')
                        operation.amount = -Decimal(amount)

                    i += 1
                    yield operation
Ejemplo n.º 47
0
    def parse(self):
        emonths = ['January', 'February', 'March', 'April',
                   'May', 'June', 'July', 'August',
                   'September', 'October', 'November', 'December']
        date_format, time_format, months = self.guess_format()
        for row in self.document.xpath('//table[@id="transactionTable"]/tbody/tr'):
            if len(row.xpath('.//td')) < 5:
                continue

            amount = row.xpath('.//td[@headers="gross"]')[-1].text_content().strip()
            if re.search('\d', amount):
                currency = Account.get_currency(amount)
                amount = AmTr.decimal_amount(amount)
            else:
                continue

            idtext = row.xpath('.//td[@class="detailsNoPrint"]//span[@class="accessAid"]')[0] \
                .text_content().replace(u'\xa0', u' ').strip().rpartition(' ')[-1]
            trans = Transaction(idtext)
            trans.amount = amount
            trans._currency = currency

            datetext = row.xpath('.//td[@class="dateInfo"]')[0].text_content().strip()
            for i in range(0, 12):
                datetext = datetext.replace(months[i], emonths[i])
            date = dateutil.parser.parse(datetext)
            trans.date = date
            trans.rdate = date

            trans.label = to_unicode(row.xpath('.//td[@class="emailInfo"]')[0].text_content().strip())
            info = to_unicode(row.xpath('.//td[@class="paymentTypeInfo"]')[0].text_content().strip())
            trans.raw = info + u' ' + trans.label

            if u'Authorization' in info or u'Autorisation' in info or \
               u'Order' in info:
                continue

            if u'Credit Card' in trans.label or u'Carte bancaire' in trans.label:
                trans.type = Transaction.TYPE_CARD
            elif info.startswith(u'Payment') or info.startswith(u'Paiement'):
                trans.type = Transaction.TYPE_ORDER
            elif u'Currency Conversion' in info or u'Conversion de devise' in info:
                trans.type = Transaction.TYPE_BANK
            else:
                trans.type = Transaction.TYPE_UNKNOWN

            yield trans
Ejemplo n.º 48
0
    def iter_transactions(self, account):
        csv = self.document

        if len(csv.header) == 42 or len(csv.header) == 43:
            # Merchant multi-currency account
            # 42 is for when the user can't access the balance on the website
            # 43 is for full acces to the account
            DATE = 0
            TIME = 1
            NAME = 3
            TYPE = 4
            if csv.header[7] == "Devise":
                CURRENCY = 7
                GROSS = 8
                FEE = 9
                NET = 10
                FROM = 11
                TO = 12
                TRANS_ID = 13
                ITEM = 16
                SITE = -1

            else:
                CURRENCY = 6
                GROSS = 7
                FEE = 8
                NET = 9
                FROM = 10
                TO = 11
                TRANS_ID = 12
                ITEM = 15
                SITE = 24
        elif len(csv.header) == 11:
            # Regular multi-currency account
            DATE = 0
            TIME = 1
            NAME = 3
            TYPE = 4
            CURRENCY = 6
            GROSS = -1
            FEE = -1
            NET = 7
            FROM = -1
            TO = -1
            TRANS_ID = -1
            ITEM = -1
            SITE = -1
        else:
            raise ValueError('CSV fields count of %i is not supported' % len(csv.header))

        for row in csv.rows:
            # we filter transaction currceny to match account currency, except if we don't now the account currency
            # we ignore canceled transactions
            if (account.balance != NotAvailable and account.get_currency(row[CURRENCY]) != account.currency) or row[NET] == '...':
                continue

            # analog to dict.get()
            get = lambda i, v=None: row[i] if 0 <= i < len(row) else v

            trans = Transaction(get(TRANS_ID, u''))

            # silly American locale
            if re.search(r'\d\.\d\d$', row[NET]):
                date = datetime.datetime.strptime(row[DATE] + ' ' + row[TIME], "%m/%d/%Y %H:%M:%S")
            else:
                date = datetime.datetime.strptime(row[DATE] + ' ' + row[TIME], "%d/%m/%Y %H:%M:%S")
            trans.date = date
            trans.rdate = date

            line = row[NAME]
            if get(ITEM):
                line += u' ' + row[ITEM]
            if get(SITE):
                line += u"(" + row[SITE] + u")"
            trans.raw = line
            trans.label = row[NAME]

            if row[TYPE].startswith(u'Update to eCheck') or \
               row[TYPE].startswith(u'Order'):
                continue

            if row[TYPE].endswith(u'Credit Card') or row[TYPE].endswith(u'carte bancaire'):
                trans.type = Transaction.TYPE_CARD
            elif row[TYPE].endswith(u'Payment Sent') or row[TYPE].startswith(u'Paiement'):
                trans.type = Transaction.TYPE_ORDER
            elif row[TYPE] in (u'Currency Conversion', u'Conversion de devise'):
                trans.type = Transaction.TYPE_BANK
            else:
                trans.type = Transaction.TYPE_UNKNOWN

            # Net is what happens after the fee (0 for most users), so what is the most "real"
            trans.amount = AmTr.decimal_amount(row[NET])
            trans._gross = AmTr.decimal_amount(get(GROSS, row[NET]))
            trans._fees = AmTr.decimal_amount(get(FEE, u'0.00'))

            trans._to = get(TO)
            trans._from = get(FROM)

            yield trans
Ejemplo n.º 49
0
    def iter_transactions(self, account):
        DATE = 0
        TIME = 1
        NAME = 3
        TYPE = 4
        CURRENCY = 6
        GROSS = 7
        FEE = 8
        NET = 9
        FROM = 10
        TO = 11
        TRANS_ID = 12
        ITEM = 15
        SITE = 24
        csv = self.document
        for row in csv.rows:
            # we filter accounts by currency
            if account.get_currency(row[CURRENCY]) != account.currency:
                continue

            trans = Transaction(row[TRANS_ID])

            # silly American locale
            if re.search(r'\d\.\d\d$', row[NET]):
                date = datetime.datetime.strptime(row[DATE] + ' ' + row[TIME], "%m/%d/%Y %I:%M:%S %p")
            else:
                date = datetime.datetime.strptime(row[DATE] + ' ' + row[TIME], "%d/%m/%Y %H:%M:%S")
            trans.date = date
            trans.rdate = date

            line = row[NAME]
            if row[ITEM]:
                line += u' ' + row[ITEM]
            if row[SITE]:
                line += u"(" + row[SITE] + u")"
            trans.raw = line
            trans.label = row[NAME]

            if row[TYPE].endswith(u'Credit Card') or row[TYPE].endswith(u'carte bancaire'):
                trans.type = Transaction.TYPE_CARD
            elif row[TYPE].endswith(u'Payment Sent') or row[TYPE].startswith(u'Paiement'):
                trans.type = Transaction.TYPE_ORDER
            elif row[TYPE] in (u'Currency Conversion', u'Conversion de devise'):
                trans.type = Transaction.TYPE_BANK
            else:
                trans.type = Transaction.TYPE_UNKNOWN

            # Net is what happens after the fee (0 for most users), so what is the most "real"
            trans.amount = clean_amount(row[NET])
            trans._gross = clean_amount(row[GROSS])
            trans._fees = clean_amount(row[FEE])

            trans._to = row[TO] or None
            trans._from = row[FROM] or None

            yield trans
Ejemplo n.º 50
0
    def _internal_get_transactions(self, categories, filter_func):
        transactions = self.request('/api/smrt/transactions?limit=1000')

        for t in transactions:

            if not filter_func(t):
                continue

            new = Transaction()

            new.date = datetime.fromtimestamp(t["createdTS"] / 1000)
            new.rdate = datetime.fromtimestamp(t["visibleTS"] / 1000)
            new.id = t['id']

            new.amount = Decimal(str(t["amount"]))

            if "merchantName" in t:
                new.raw = new.label = t["merchantName"]
            elif "partnerName" in t:
                new.raw = CleanText().filter(t["referenceText"]) if "referenceText" in t else CleanText().filter(t["partnerName"])
                new.label = t["partnerName"]
            else:
                new.raw = new.label = ''

            if "originalCurrency" in t:
                new.original_currency = t["originalCurrency"]
            if "originalAmount" in t:
                new.original_amount = Decimal(str(t["originalAmount"]))

            if t["type"] == 'PT':
                new.type = Transaction.TYPE_CARD
            elif t["type"] == 'CT':
                new.type = Transaction.TYPE_TRANSFER
            elif t["type"] == 'WEE':
                new.type = Transaction.TYPE_BANK

            if t["category"] in categories:
                new.category = categories[t["category"]]

            yield new
Ejemplo n.º 51
0
    def generate_single_transaction(self):
        """
        Generate a fake transaction.
        """
        now = datetime.datetime.now()

        transaction = Transaction()
        transaction.type = self.generate_type()

        n = random.randrange(100)
        if n < 2:
            # with a 2% rate, generate a special operation to test duplicates
            # (happening on 4th of current month).
            duplicate_date = datetime.datetime(now.year, now.month, 4)
            transaction.amount = Decimal(-300.0)
            transaction.label = "Loyer"
            transaction.raw = "Loyer habitation"
            transaction.date = self.generate_date(duplicate_date,
                                                  duplicate_date)
            return transaction

        # Get transactions for the previous month.
        min_date = now - datetime.timedelta(days=30)

        transaction.date = self.generate_date(min_date, now)

        if n < 15:
            transaction.label, transaction.raw = self.generate_label(
                positive=True)
            transaction.amount = Decimal(
                random.randint(100, 800) + random.random())
            return transaction

        if n < 30:
            transaction.rdate = transaction.date
        elif n < 60:
            transaction.rdate = None

        transaction.amount = Decimal(random.randint(-60, 0) + random.random())
        transaction.label, transaction.raw = self.generate_label()
        transaction.type = self.generate_type()

        # Randomly set the date properties to date class instead of datetime.
        maybe_date_object = random.randrange(3)
        if maybe_date_object == 0:
            transaction.date = transaction.date.date()

        if maybe_date_object == 1 and transaction.rdate:
            transaction.rdate = transaction.rdate.date()

        return transaction
Ejemplo n.º 52
0
 def __init__(self, id='', *args, **kwargs):
     Transaction.__init__(self, id, *args, **kwargs)
     self._logger = getLogger('FrenchTransaction')
Ejemplo n.º 53
0
 def __init__(self, id='', *args, **kwargs):
     Transaction.__init__(self, id, *args, **kwargs)
     self._logger = getLogger('FrenchTransaction')
Ejemplo n.º 54
0
 def __init__(self, id="", *args, **kwargs):
     Transaction.__init__(self, id, *args, **kwargs)
     self._logger = getLogger("FrenchTransaction")
Ejemplo n.º 55
0
    def _internal_get_transactions(self, categories, filter_func):
        TYPES = {
            'PT': Transaction.TYPE_CARD,
            'AA': Transaction.TYPE_CARD,
            'CT': Transaction.TYPE_TRANSFER,
            'WEE': Transaction.TYPE_BANK,
        }

        transactions = self.request('/api/smrt/transactions?limit=1000')

        for t in transactions:

            if not filter_func(t) or t["amount"] == 0:
                continue

            new = Transaction()

            new.date = datetime.fromtimestamp(t["createdTS"] / 1000)
            new.rdate = datetime.fromtimestamp(t["visibleTS"] / 1000)
            new.id = t['id']

            new.amount = Decimal(str(t["amount"]))

            if "merchantName" in t:
                new.raw = new.label = t["merchantName"]
            elif "partnerName" in t:
                new.raw = CleanText().filter(
                    t["referenceText"]) if "referenceText" in t else CleanText(
                    ).filter(t["partnerName"])
                new.label = t["partnerName"]
            else:
                new.raw = new.label = ''

            if "originalCurrency" in t:
                new.original_currency = t["originalCurrency"]
            if "originalAmount" in t:
                new.original_amount = Decimal(str(t["originalAmount"]))

            new.type = TYPES.get(t["type"], Transaction.TYPE_UNKNOWN)

            if t["category"] in categories:
                new.category = categories[t["category"]]

            yield new
Ejemplo n.º 56
0
    def iter_history(self, account):
        if not self.cookie:
            self.login()

        page = "/domiweb/prive/particulier/releve/"
        if account._cmbtype == 'D':
            page += "10-releve.act"
        else:
            page += "2-releve.act"
        page +="?noPageReleve=1&indiceCompte="
        page += account._cmbvaleur
        page += "&typeCompte="
        page += account._cmbvaleur2
        page += "&deviseOrigineEcran=EUR"

        def do_http():
            if 'no_check' in self.config and self.config['no_check'].get() == "y":
                conn = HellHTTPS("www.cmb.fr")
            else:
                conn = HellHTTPS("www.cmb.fr", ca_file=self.AUTH_CERT, callBack=self.sslCallBack)
            conn.connect()
            headers = self.headers
            headers['Cookie'] = self.cookie
            conn.request("GET", page, {}, headers)
            response = conn.getresponse()
            data = response.read()
            conn.close
            return data

        data = do_http()
        parser = etree.HTMLParser()
        tree = etree.parse(StringIO(data), parser)

        tables = tree.xpath('/html/body/table')
        if len(tables) == 0:
            title = tree.xpath('/html/head/title')[0].text
            if title == u"Utilisateur non identifié":
                self.login()
                data = do_http()

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

        i = 0

        for table in tables:
            if table.get('id') != "tableMouvements":
                continue
            for tr in table.getiterator('tr'):
                if (tr.get('class') != 'LnTit' and
                        tr.get('class') != 'LnTot'):
                    operation = Transaction(i)
                    td = tr.xpath('td')

                    div = td[1].xpath('div')
                    d = div[0].text.split('/')
                    operation.date = date(*reversed([int(x) for x in d]))

                    div = td[2].xpath('div')
                    label = div[0].xpath('a')[0].text.replace('\n', '')
                    operation.raw = unicode(' '.join(label.split()))
                    for pattern, _type, _label in self.LABEL_PATTERNS:
                        mm = pattern.match(operation.raw)
                        if mm:
                            operation.type = _type
                            operation.label = sub('[ ]+', ' ',
                                    _label % mm.groupdict()).strip()
                            break

                    amount = td[3].text
                    if amount.count(',') != 1:
                        amount = td[4].text
                        amount = amount.replace(',', '.').replace(u'\xa0', '')
                        operation.amount = Decimal(amount)
                    else:
                        amount = amount.replace(',', '.').replace(u'\xa0', '')
                        operation.amount = - Decimal(amount)

                    i += 1
                    yield operation
Ejemplo n.º 57
0
    def iter_history(self, account):
        if not self.islogged:
            self.login()

        page = "https://www.cmb.fr/domiweb/prive/particulier/releve/"
        if account._cmbtype == 'D':
            page += "10-releve.act"
        else:
            page += "2-releve.act"
        page +="?noPageReleve=1&indiceCompte="
        page += account._cmbvaleur
        page += "&typeCompte="
        page += account._cmbvaleur2
        page += "&deviseOrigineEcran=EUR"

        data = self.browser.open(page).content
        parser = etree.HTMLParser()
        tree = etree.parse(StringIO(data), parser)

        tables = tree.xpath('/html/body/table')
        if len(tables) == 0:
            title = tree.xpath('/html/head/title')[0].text
            if title == u"Utilisateur non identifié":
                self.login()
                data = self.browser.open(page).content

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

        i = 0

        for table in tables:
            if table.get('id') != "tableMouvements":
                continue
            for tr in table.getiterator('tr'):
                if (tr.get('class') != 'LnTit' and
                        tr.get('class') != 'LnTot'):
                    operation = Transaction()
                    td = tr.xpath('td')

                    div = td[1].xpath('div')
                    d = div[0].text.split('/')
                    operation.date = date(*reversed([int(x) for x in d]))

                    div = td[2].xpath('div')
                    label = div[0].xpath('a')[0].text.replace('\n', '')
                    operation.raw = unicode(' '.join(label.split()))
                    for pattern, _type, _label in self.LABEL_PATTERNS:
                        mm = pattern.match(operation.raw)
                        if mm:
                            operation.type = _type
                            operation.label = sub('[ ]+', ' ',
                                    _label % mm.groupdict()).strip()
                            break

                    amount = td[3].text
                    if amount.count(',') != 1:
                        amount = td[4].text
                        amount = amount.replace(',', '.').replace(u'\xa0', '')
                        operation.amount = Decimal(amount)
                    else:
                        amount = amount.replace(',', '.').replace(u'\xa0', '')
                        operation.amount = - Decimal(amount)

                    i += 1
                    yield operation