コード例 #1
0
ファイル: dkb.py プロジェクト: zurajm/pybank
    def _get_transactions_from_credit_card_statement(self):
        transactions = []
        rows = self._browser.find_elements_by_css_selector('table tr')
        # Skip header row.
        rows = rows[1:]
        for row in rows:
            try:
                cells = row.find_elements_by_tag_name('td')

                # Date. First row is value date, second is voucher date.
                date_text = cells[1].text.split('\n')[0]
                date = self._parse_date(date_text)

                # Memo.
                memo = fetch.normalize_text(cells[2].text)

                # Amount.
                amounts = cells[3].text.split('\n')
                amount = fetch.parse_decimal_number(amounts[0], 'de_DE')

                # Currency.
                currencies = cells[4].text.split('\n')
                if len(currencies) > 1 and len(amounts) > 1:
                    original_amount = fetch.parse_decimal_number(
                        amounts[1], 'de_DE')
                    original_currency = currencies[1]
                    memo += '\nOriginal amount: %s %.2f' % (original_currency,
                                                            original_amount)

                transactions.append(model.Payment(date, amount, memo=memo))
            except ValueError, e:
                logger.warning('Skipping invalid row: %s. Error: %s' %
                               (row.text, e))
                raise
コード例 #2
0
ファイル: dkb.py プロジェクト: zurajm/pybank
    def _get_transactions_from_checking_account_statement(self):
        transactions = []
        rows = self._browser.find_elements_by_css_selector(
            'table tbody tr.mainRow')
        for row in rows:
            try:
                cells = row.find_elements_by_tag_name('td')

                # Date. First row is entry date, second is value date.
                date_text = cells[0].text.split('\n')[1]
                date = self._parse_date(date_text)

                # Payee and memo.
                details_lines = fetch.normalize_text(cells[1].text).split('\n')
                unused_transaction_type = details_lines[0]
                payee = '\n'.join(
                    details_lines[1:2])  # This line might not exist.
                memo = '\n'.join(details_lines[2:])  # Might be empty.
                payee_lines = cells[2].text.split('\n') + ['']
                payee_account, payee_clearing = payee_lines[:2]
                if payee_account:
                    memo += '\nAccount: %s' % payee_account
                if payee_clearing:
                    memo += '\nClearing: %s' % payee_clearing

                # Amount
                amount = fetch.parse_decimal_number(cells[3].text, 'de_DE')

                transactions.append(model.Payment(date, amount, payee, memo))
            except ValueError, e:
                logger.warning('Skipping invalid row: %s. Error: %s' %
                               (row.text, e))
                raise
コード例 #3
0
ファイル: app.py プロジェクト: knazarov/birthdaybot
def pay():
    if not flask_security.current_user.is_authenticated:
        return redirect('/login')

    if not flask_security.current_user.id == int(app.config['ADMIN_ID']):
        flask.abort(404)

    users = model.get_users()

    users_choices = []
    for u in users:
        users_choices.append((str(u.id),
                              ("%s %s" % (str(u.first_name), str(u.last_name)))))

    print(users_choices)

    form = forms.PaymentForm()
    form.user.choices = users_choices

    if form.validate_on_submit():
        user_id = int(form.user.data)

        users = (model.User.query
                 .filter(model.User.approved == True)
                 .filter(model.User.participates == True)
                 .filter(model.User.id != user_id)).all()

        amount = form.amount.data

        birthday = model.Birthday()
        birthday.amount = int(amount)
        birthday.user_id = user_id
        birthday.gift = form.gift.data
        db.session.add(birthday)

        num_users = int(len(users))
        individual_payment = int(birthday.amount / num_users)

        for user in users:
            payment = model.Payment()
            payment.amount = individual_payment
            payment.birthday = birthday
            payment.user = user
            payment.timestamp = datetime.datetime.utcnow()
            db.session.add(payment)

        db.session.commit()

        for user in users:
            tasks.pay.delay(user.id, int(individual_payment), user_id, birthday.gift)

        return flask.redirect(flask.url_for(
            'pay'))

    return render_template('pay.html', form=form)
コード例 #4
0
ファイル: ib.py プロジェクト: zurajm/pybank
    def _get_transfers(self, csv_dict, account_name):
        logger.debug('Extracting transfers...')

        transactions_by_currency = collections.defaultdict(list)
        for row in csv_dict['Deposits & Withdrawals']['Data']['__rows']:
            currency = row[0]
            if currency.startswith('Total'):
                continue
            date = datetime.datetime.strptime(row[1], self._DATE_FORMAT)
            kind = row[2]
            amount = self._parse_float(row[3])
            transaction = model.Payment(date, amount, payee=account_name)
            transactions_by_currency[currency].append(transaction)

        return transactions_by_currency
コード例 #5
0
ファイル: postfinance.py プロジェクト: zurajm/pybank
    def _parse_transaction_from_text(self, date, memo, amount):
        try:
            date = datetime.datetime.strptime(date, self._DATE_FORMAT)
        except ValueError:
            logger.warning('Skipping transaction with invalid date %s.', date)
            return

        memo = fetch.normalize_text(memo)
        try:
            amount = fetch.parse_decimal_number(amount, 'de_CH')
        except ValueError:
            logger.warning('Skipping transaction with invalid amount %s.',
                           amount)
            return

        return model.Payment(date, amount, memo=memo)
コード例 #6
0
ファイル: postfinance.py プロジェクト: zurajm/pybank
    def _get_credit_card_transactions(self, account, start, end):
        browser = self._browser

        logger.info('Opening credit cards overview...')
        self._go_to_assets()
        cc_tile = self._get_tile_by_title('Credit card')
        fetch.find_element_by_title(cc_tile, 'Detailed overview').click()
        self._wait_to_finish_loading()
        content = browser.find_element_by_class_name('detail_page')

        logger.debug('Finding credit card account...')
        # Switch to tab for that account.
        for tab in content.find_elements_by_css_selector('tab-wrapper'):
            if tab.text.endswith(account.name[-4:]):
                tab.find_element_by_tag_name('a').click()
        # Verify that the correct card is displayed.
        active_pane = content.find_element_by_css_selector(
            'section.js-tabs--pane.is-active')
        formatted_account_name = fetch.format_cc_account_name(account.name)
        if formatted_account_name not in active_pane.text:
            raise fetch.FetchError('Couldn\'t find account %s.' % account)

        # You can see the transactions for one month/period at a time.
        transactions = []
        while True:
            self._wait_to_finish_loading()

            # Get the period of the current page.
            date_select_el = content.find_element_by_css_selector(
                '.buttons select')
            date_select = ui.Select(date_select_el)
            period = date_select.first_selected_option.text
            if period == 'Current accounting period':
                # Just use "now", which is an inaccurate hack, but works for our
                # purposes.
                start_date = end_date = datetime.datetime.now()
            else:
                match = self._CREDIT_CARD_DATE_RANGE_PATTERN.search(period)
                if match:
                    start_date_str = match.group(1)
                    end_date_str = match.group(2)
                    start_date = datetime.datetime.strptime(
                        start_date_str, self._DATE_FORMAT)
                    end_date = datetime.datetime.strptime(
                        end_date_str, self._DATE_FORMAT)
                else:
                    raise fetch.FetchError(
                        'Not a credit card transactions page %s.' %
                        account.name)
            logger.debug('Current period: ' + period)

            transactions_on_page = self._extract_cc_transactions()
            transactions += transactions_on_page
            logger.debug('Found %i transactions on the current page.' %
                         len(transactions_on_page))

            # Are we done yet?
            if start_date <= start:
                logger.info('Should have loaded enough transaction pages.')
                break
            else:
                logger.debug('Adding marker transaction for page break.')
                if transactions:
                    transactions.append(
                        model.Payment(transactions[-1].date,
                                      amount=0,
                                      memo='[Next billing cycle]'))

            # Load earlier transactions.
            next_option = date_select_el.find_element_by_xpath(
                "option[text() = '%s']/following-sibling::option" % period)
            if not next_option:
                logger.info('No more earlier transactions.')
                break
            logger.info('Loading earlier transactions page...')
            date_select.select_by_value(next_option.get_attribute('value'))
            self._wait_to_finish_loading()

        # Filter the transactions for the requested date range.
        logger.debug('Found %i transactions before filtering for date range.' %
                     len(transactions))
        transactions = filter(lambda t: start <= t.date < end, transactions)

        # They should be sorted in reverse chronological order already, but
        # let's make this explicit.
        transactions.sort(key=lambda t: t.date, reverse=True)

        logger.info('Found %i transactions.' % len(transactions))

        self._close_tile()
        return transactions