Пример #1
0
def enter_transaction(t):
    utils.log_debug('enter_transaction', t)
    accounts_sidebar = gui.get_by_text('user-entered-text', t.account_name)
    gui.click(accounts_sidebar)  # handles that it contains two elements
    locate_transaction(t)
    assert t.account_name not in ('Annotated', 'Test Data'
                                  )  # don't overwrite test data
    adjust_subtransaction_rows(t)
    date, payees, categories, memos = map(
        lambda p: gui.get_by_placeholder('accounts-text-field', p),
        ('date', 'payee', 'category', 'memo'))
    date.send_keys(gui_format_date(t.date))
    outflows, inflows = map(
        lambda p: gui.get_by_placeholder('ember-text-field', p),
        ('outflow', 'inflow'))
    if len(t.subtransactions) == 0:
        enter(t, payees, categories, memos, outflows, inflows)
        ' TODO: do not approve, only save? '
        ' Maybe it is only approving things that are already approved? '
        approve = gui.get_by_text('button-primary', ['Approve', 'Save'])
        utils.log_debug('approve/save?', approve.text)
        gui.click(approve)
    else:
        for i, s in enumerate(t.subtransactions):
            enter(s, payees[i + 1], categories[i + 1], memos[i + 1],
                  outflows[i + 1], inflows[i + 1])
        outflows[-1].send_keys(gui.Keys.ENTER)
Пример #2
0
def delete_accounts(accounts):
    utils.log_info('Deleting %s accounts via Web App' % len(accounts))
    load_gui()
    navlink_accounts = gui.get('navlink-accounts')
    gui.scroll_to(navlink_accounts)
    gui.click(navlink_accounts)
    for a in accounts:
        edit_account = gui.get_by_text('nav-account-name', a.name)
        utils.log_debug(edit_account)
        gui.scroll_to(edit_account)
        gui.right_click(edit_account)
        gui.get_by_text('button-red', ['Close Account', 'Delete', 'Delete Account'], partial=True).click()
Пример #3
0
def adjust_subtransaction_rows(t):
    utils.log_debug('add_subtransactions_rows', len(t.subtransactions))
    # Remove existing subtransactions
    memo = gui.get_by_text('user-entered-text', t.id, count=1)  # TODO: why was this partial?
    gui.click(memo, 2)
    removes = gui.get('ynab-grid-sub-remove', require=False, wait=1)
    while removes:
        gui.click(removes)
        removes = gui.get('ynab-grid-sub-remove', require=False, wait=.5)

    # Add rows for the new ones
    n = len(t.subtransactions)
    if n == 0:
        return
    gui.get_by_placeholder('accounts-text-field', 'category').clear()  # needed?
    category_dropdown = gui.get_by_placeholder('dropdown-text-field', 'category')
    category_dropdown.send_keys(' ')
    split = gui.get('modal-account-categories-split-transaction')
    gui.click(split)
    for i in range(n - 2):
        # gui.clicking split means we already have two
        gui.click(gui.get('ynab-grid-split-add-sub-transaction'))
    if n == 1:
        # which is weird but in principle OK
        gui.click(gui.get('ynab-grid-sub-remove'))
    assert len(gui.get('ynab-grid-sub-remove')) == n
Пример #4
0
def add_unlinked_account(account_name, balance=0, account_type='credit'):
    utils.log_debug('add_unlinked_account')
    assert account_type in {'credit'}
    load_gui()
    # TODO: other account types? linked?
    time.sleep(1)
    add_account = gui.get('nav-add-account')
    add_account.click()
    unlinked = gui.get_by_text('select-linked-unlinked-box-title', 'UNLINKED')
    unlinked.click()
    gui.send_keys(account_type)
    gui.send_keys(gui.Keys.TAB)
    gui.send_keys(account_name)
    gui.send_keys(gui.Keys.TAB)
    gui.send_keys(str(balance))
    gui.send_keys(gui.Keys.TAB)
    gui.send_keys(gui.Keys.ENTER)
    time.sleep(2)
    gui.get_by_text('pull-right', 'Done').click()
Пример #5
0
def delete_transactions():
    load_gui()
    search('Memo: ' + afy.ynab.ynab.delete_key)
    if not isinstance(gui.get('ynab-checkbox-button-square'), list):
        return  # Means no transactions in results to delete, because only one element
    select_all()
    gui.send_keys(gui.Keys.TAB)
    gui.send_keys(gui.Keys.TAB)
    gui.send_keys(gui.Keys.DELETE)
    # Only gives confirm modal over some number of transactions. TODO: cut down this wait.
    confirm_delete = gui.get_by_text('button-primary', 'Delete', require=False, wait=7)
    if confirm_delete:
        gui.click(confirm_delete)
Пример #6
0
def setup_ynab_auth():
    utils.log_info('Checking for YNAB authentication')
    # TODO: make this use oauth instead of api tokens
    if settings.get('api_token'):
        return
    utils.log_info('Installing YNAB authentication')
    api_token_url = 'https://app.youneedabudget.com/settings/developer'
    d = gui.driver()
    d.get(api_token_url)
    utils.log_info('Log in if needed')
    new_token_button = gui.get_by_text('button', 'New Token')
    gui.click(new_token_button)
    utils.log_info(
        'Enter your password in the YNAB Web App, then click "Generate"')
    while 'New Personal Access Token' not in d.page_source:
        time.sleep(.5)
    api_token = re.search(
        'New Personal Access Token: <strong>([^<]*)</strong>',
        d.page_source).groups()[0]
    settings.set('api_token', api_token)
    utils.log_debug('settings.api_token', settings.api_token)
    assert settings.api_token
    gui.quit()