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
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
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
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
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
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
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
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
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"] t.label = self.i18n["OPERATION_TYPE_" + trans["casDeGestion"]] t.amount = Decimal(trans["montantNetEuro"]).quantize(Decimal('.01')) yield t
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
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
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
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