def check_transaction(self, account, tr, coming): today = date.today() self.assertFalse(empty(tr.date), 'transaction %r has no debit date' % tr) self.assertTrue(tr.amount, 'transaction %r has no amount' % tr) self.assertFalse( empty(tr.raw) and empty(tr.label), 'transaction %r has no raw or label' % tr) if coming: self.assertGreaterEqual( new_date(tr.date), today, 'coming transaction %r should be in the future' % tr) else: self.assertLessEqual( new_date(tr.date), today, 'history transaction %r should be in the past' % tr) if tr.rdate: self.assertGreaterEqual( new_date(tr.date), new_date(tr.rdate), 'transaction %r rdate should be before date' % tr) if tr.original_amount or tr.original_currency: self.assertTrue(tr.original_amount and tr.original_currency, 'transaction %r has missing foreign info' % tr) for inv in (tr.investments or []): self.assertTrue( inv.label, 'transaction %r investment %r has no label' % (tr, inv)) self.assertTrue( inv.valuation, 'transaction %r investment %r has no valuation' % (tr, inv))
def iter_events(self, start_date, users): start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0) for d in self.doc['data']: if not d['ls']: # seems to be validation state continue assert d['ls'] == 2 user = users[d['u']] ev = BaseCalendarEvent() ev.timezone = 'Europe/Paris' ev.summary = user.name ev.status = STATUS.CONFIRMED ev.start_date = self._offset(start_date, d['o']) if d['a'] == 2: ev.end_date = ev.start_date + timedelta(days=1) ev.start_date = ev.start_date.date() ev.end_date = ev.end_date.date() elif d['a'] == 1: ev.start_date = ev.start_date + timedelta(hours=12) ev.end_date = ev.start_date + timedelta(hours=12) else: assert d['a'] == 0 ev.end_date = ev.start_date + timedelta(hours=12) if user.end and new_date(user.end) < new_date(ev.start_date): continue yield ev
def _guess_card_debitting(self, accounts): # the site doesn't indicate if cards are immediate or deferred # try to guess it by looking at history of checking account cards = {} checkings = [ account for account in accounts if account.type == Account.TYPE_CHECKING ] card_account_ids = [ account._redacted_card for account in accounts if account.type == Account.TYPE_CARD ] limit = new_date(datetime.now() - timedelta(days=90)) for account in checkings: card_dates = {} for tr in self._iter_history_base(account): if new_date(tr.date) < limit: break if tr.type == Transaction.TYPE_CARD and tr._redacted_card: card_dates.setdefault(tr._redacted_card, []).append( (tr.date, tr.rdate)) for card, dates in card_dates.items(): debit_dates = set(d[0] for d in dates) if len(debit_dates) != len( set((d.year, d.month) for d in debit_dates)): self.logger.debug( 'card %r has multiple debit dates per month -> immediate debit', card) cards[card] = 'immediate' continue cards[card] = 'deferred' # checking diff between date and rdate may not be a good clue # there has been a transaction with: # dateOpt: 2017-10-25 # dateValeur: 2017-10-18 # dateIntro: 2017-10-30 # carteDateFacturette: 2017-10-13 for card in cards: if cards[card] != 'immediate' and card not in card_account_ids: self.logger.warning( "card %s seems deferred but account not found, its transactions will be skipped...", card) return cards
def iter_history(self, account): self.go_site(account._site) if account._site == 'oney': if account._num: self.card_page.go(acc_num=account._num) post = {'task': 'Synthese', 'process': 'SyntheseCompte', 'taskid': 'Releve'} self.operations.go(data=post) for tr in self.page.iter_transactions(seen=set()): yield tr elif account._site == 'other': if self.last_hist.go().has_transactions(): # transactions are missing from the xls from 2016 to today # so two requests are needed d = date.today() page_before = self.credit_hist.open( params=self._build_hist_form(last_months=True) ) page_today = self.credit_hist.go( params=self._build_hist_form() ) for tr in chain(page_before.iter_history(), page_today.iter_history()): if new_date(tr.date) < d: yield tr
def iter_history(self, account): self.go_site(account._site) if account._site == 'oney': if account._num: self.card_page.go(acc_num=account._num) post = {'task': 'Synthese', 'process': 'SyntheseCompte', 'taskid': 'Releve'} self.operations.go(data=post) for tr in self.page.iter_transactions(seen=set()): yield tr elif account._site == 'other' and account.type != Account.TYPE_LOAN: self.credit_home.go(data={'numeroCompte': account.id}) self.last_hist.go() if self.page.has_transactions(): # transactions are missing from the xls from 2016 to today # so two requests are needed d = date.today() page_before = self.credit_hist.open( params=self._build_hist_form(last_months=True) ) page_today = self.credit_hist.go( params=self._build_hist_form() ) for tr in chain(page_before.iter_history(), page_today.iter_history()): if new_date(tr.date) < d: yield tr
def __setattr__(self, name, value): if name == 'value': # Force use of our date and datetime types, to fix bugs in python2 # with strftime on year<1900. if type(value) is datetime.datetime: value = new_datetime(value) if type(value) is datetime.date: value = new_date(value) return object.__setattr__(self, name, value)
def iter_events(self, start_date, users): start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0) # key: (userId, date) events = {} for d in self.doc['data']['items']: if not d['leavePeriod']['isConfirmed']: # not validated by manager continue user_id = d['leavePeriod']['ownerId'] user = users[user_id] ev = BaseCalendarEvent() ev.timezone = 'Europe/Paris' ev.summary = user.name ev.status = STATUS.CONFIRMED ev.start_date = DateTime().filter(d['date']) if not d['isAM']: ev.start_date = ev.start_date + timedelta(hours=12) ev.end_date = ev.start_date + timedelta(hours=12) else: ev.end_date = ev.start_date + timedelta(hours=12) if user.end and new_date(user.end) < new_date(ev.start_date): continue event_key = user_id, ev.start_date.date() if event_key in events: ev.start_date = ev.start_date.date() ev.end_date = ev.start_date + timedelta(days=1) events[event_key] = ev return events.values()
def _guess_card_debitting(self, accounts): # the site doesn't indicate if cards are immediate or deferred # try to guess it by looking at history of checking account cards = {} checkings = [account for account in accounts if account.type == Account.TYPE_CHECKING] card_account_ids = [account._redacted_card for account in accounts if account.type == Account.TYPE_CARD] limit = new_date(datetime.now() - timedelta(days=90)) for account in checkings: card_dates = {} for tr in self._iter_history_base(account): if new_date(tr.date) < limit: break if tr.type == Transaction.TYPE_CARD and tr._redacted_card: card_dates.setdefault(tr._redacted_card, []).append((tr.date, tr.rdate)) for card, dates in card_dates.items(): debit_dates = set(d[0] for d in dates) if len(debit_dates) != len(set((d.year, d.month) for d in debit_dates)): self.logger.debug('card %r has multiple debit dates per month -> immediate debit', card) cards[card] = 'immediate' continue cards[card] = 'deferred' # checking diff between date and rdate may not be a good clue # there has been a transaction with: # dateOpt: 2017-10-25 # dateValeur: 2017-10-18 # dateIntro: 2017-10-30 # carteDateFacturette: 2017-10-13 for card in cards: if cards[card] != 'immediate' and card not in card_account_ids: self.logger.warning("card %s seems deferred but account not found, its transactions will be skipped...", card) return cards
def check_transaction(self, account, tr, coming): today = date.today() self.assertFalse(empty(tr.date), 'transaction %r has no debit date' % tr) if tr.amount != 0: self.assertTrue(tr.amount, 'transaction %r has no amount' % tr) self.assertFalse(empty(tr.raw) and empty(tr.label), 'transaction %r has no raw or label' % tr) if coming: self.assertGreaterEqual(new_date(tr.date), today, 'coming transaction %r should be in the future' % tr) else: self.assertLessEqual(new_date(tr.date), today, 'history transaction %r should be in the past' % tr) if tr.rdate: self.assertGreaterEqual(new_date(tr.date), new_date(tr.rdate), 'transaction %r rdate should be before date' % tr) self.assertLess(abs(tr.date.year - tr.rdate.year), 2, 'transaction %r date (%r) and rdate (%r) are too far away' % (tr, tr.date, tr.rdate)) if tr.original_amount or tr.original_currency: self.assertTrue(tr.original_amount and tr.original_currency, 'transaction %r has missing foreign info' % tr) for inv in (tr.investments or []): self.assertTrue(inv.label, 'transaction %r investment %r has no label' % (tr, inv)) self.assertTrue(inv.valuation, 'transaction %r investment %r has no valuation' % (tr, inv))
def iter_coming(self, account): self.go_site(account._site) if account._site == 'oney': if account._num: self.card_page.go(acc_num=account._num) post = {'task': 'OperationRecente', 'process': 'OperationRecente', 'taskid': 'OperationRecente'} self.operations.go(data=post) for tr in self.page.iter_transactions(seen=set()): yield tr elif account._site == 'other': self.credit_hist.go(params=self._build_hist_form()) d = date.today().replace(day=1) # TODO is it the right date? for tr in self.page.iter_history(): if new_date(tr.date) >= d: yield tr
def init_transfer(self, transfer): date = new_date(transfer.exec_date or datetime.now()) self.transfer_start.go() transfer_page = self.page self.emitters.go(data={ 'typevirradio': 'ponct', }) self.recipients.go(data={ 'typevirradio': 'ponct', 'nCompteDeb': transfer.account_id, }) all_recipients = list(self.page.iter_recipients()) self.transfer_date.go(data={ 'nCompteCred': transfer.recipient_id, }) for page_date in self.page.iter_dates(): if page_date >= date: date = page_date break else: raise TransferInvalidDate('The bank proposes no date greater or equal to the desired date') form = transfer_page.prepare_form(transfer=transfer, date=page_date) form.url = self.transfer_validate.build() form.submit() assert self.transfer_validate.is_here() form = transfer_page.prepare_form(transfer=transfer, date=page_date) form.url = self.transfer_post.build() form.submit() assert self.transfer_post.is_here() ret = self.page.get_transfer() if ret.recipient_iban: assert not ret.recipient_id # it's nowhere on the page recipient = find_object(all_recipients, iban=ret.recipient_iban) assert recipient ret.recipient_id = recipient.id return ret
def iter_coming(self, account): self.go_site(account._site) if account._site == 'oney': if account._num: self.card_page.go(acc_num=account._num) post = {'task': 'OperationRecente', 'process': 'OperationRecente', 'taskid': 'OperationRecente'} self.operations.go(data=post) for tr in self.page.iter_transactions(seen=set()): yield tr elif account._site == 'other' and account.type != Account.TYPE_LOAN: self.credit_home.go(data={'numeroCompte': account.id}) self.last_hist.go() if self.page.has_transactions(): self.credit_hist.go(params=self._build_hist_form()) d = date.today().replace(day=1) # TODO is it the right date? for tr in self.page.iter_history(): if new_date(tr.date) >= d: yield tr
def iter_history(self, account): self.go_site(account._site) if account._site == 'oney': if account._num: self.card_page.go(acc_num=account._num) post = { 'task': 'Synthese', 'process': 'SyntheseCompte', 'taskid': 'Releve' } self.operations.go(data=post) for tr in self.page.iter_transactions(seen=set()): yield tr elif account._site == 'other': self.credit_hist.go(params=self._build_hist_form()) d = date.today().replace(day=1) # TODO is it the right date? for tr in self.page.iter_history(): if new_date(tr.date) < d: yield tr
def transfer_check_exec_date(self, old, new): delta = new_date(new) - new_date(old) return delta.days <= 2