Ejemplo n.º 1
0
def test_deduplicate_both_unknown():
    bank_to_accounts_map = {
        'bankA': ['accountA'],
        'bankB': ['accountB'],
    }

    transactions = [
        schema.Transaction('bankA', 'accountA', 'unknownB',
                           schema.Date(2017, 1, 1), 'a transaction',
                           Decimal('10.00')),
        schema.Transaction('bankB', 'unknownA', 'accountB',
                           schema.Date(2017, 1, 1), 'same transaction!',
                           Decimal('10.00')),
    ]

    deduped = deduplicate.deduplicate(transactions, bank_to_accounts_map)
    assert_equals(len(deduped), 2)

    assert_in(
        schema.Transaction('bankA', 'accountA', 'unknownB',
                           schema.Date(2017, 1, 1), 'a transaction',
                           Decimal('10.00')), deduped)

    assert_in(
        schema.Transaction('bankB', 'unknownA', 'accountB',
                           schema.Date(2017, 1, 1), 'same transaction!',
                           Decimal('10.00')), deduped)
Ejemplo n.º 2
0
def test_deduplicate_ok():
    bank_to_accounts_map = {
        'bankA': ['accountA'],
        'bankB': ['accountB'],
    }

    transactions = [
        schema.Transaction('bankA', 'accountA', 'accountB',
                           schema.Date(2017, 1, 1), 'a transaction',
                           Decimal('10.00')),
        schema.Transaction('bankB', 'accountA', 'accountB',
                           schema.Date(2017, 1, 1), 'same transaction!',
                           Decimal('10.00')),
    ]
    deduped = deduplicate.deduplicate(transactions, bank_to_accounts_map)

    assert_equals(len(deduped), 1)

    expected = [
        schema.Transaction('bankA + bankB', 'accountA', 'accountB',
                           schema.Date(2017, 1,
                                       1), 'a transaction + same transaction!',
                           Decimal('10.00')),
    ]
    assert_equals(deduped, expected)
Ejemplo n.º 3
0
def transactions_by_account(fileobj):
    result = []
    account = fileobj.readline().rstrip('\n')
    data = json.load(fileobj, parse_float=Decimal)['data']

    # not sure if this is a valid assumption, but i'd rather wait for
    # it to break than introduce maybe dead code for injecting a
    # a starting balance.
    assert data['start_balance'] == 0

    for transaction in data['transactions']:
        date_string, _ = transaction['datetime_created'].split('T')
        date = schema.Date(*map(int, date_string.split('-')))
        if transaction['payment'] is not None:
            a = transaction['payment']['actor']['username']
            b = transaction['payment']['target']['user']['username']
            action = transaction['payment']['action']
            if a == account:
                other = b
                b = ''
            elif b == account:
                other = a
                a = ''
            else:
                assert False
            if action == 'pay':
                from_to = [a, b]
            else:
                assert action == 'charge'
                from_to = [b, a]
        elif transaction['capture'] is not None:
            assert transaction['capture']['authorization']['user'][
                'username'] == account
            transaction['note'] = transaction['capture']['authorization'][
                'descriptor']
            other = transaction['note']
            from_to = [account, '']
        else:
            assert False

        funding = transaction.get('funding_source')
        if funding is not None and funding['name'] != 'Venmo balance':
            assert from_to[0] == account
            result.append(
                schema.Transaction(
                    '', account, date,
                    json.dumps({
                        'other': funding['name'],
                        'note': 'fund ' + transaction['note']
                    }), Decimal(transaction['amount'])))
        result.append(
            schema.Transaction(
                from_to[0], from_to[1], date,
                json.dumps({
                    'other': other,
                    'note': transaction['note']
                }), Decimal(transaction['amount'])))
    assert compute_balance(account, result) == data['end_balance']
    return {account: result}
Ejemplo n.º 4
0
def test_deduplicate_unmatched_missing():
    bank_to_accounts_map = {
        'bankA': ['accountA'],
        'bankB': ['accountB'],
    }
    transactions = [
        schema.Transaction('bankA', 'accountA', 'accountB',
                           schema.Date(2017, 1, 1), 'a transaction',
                           Decimal('10.00')),
    ]

    deduped = deduplicate.deduplicate(transactions, bank_to_accounts_map)

    expected = [
        schema.Transaction('bankA', 'accountA', 'unmatched: accountB',
                           schema.Date(2017, 1, 1), 'a transaction',
                           Decimal('10.00')),
    ]
    assert_equals(deduped, expected)
Ejemplo n.º 5
0
def correct_balance(account, real_balance, transactions):
    correction = Decimal(real_balance) - compute_balance(account, transactions)
    frm, to = '', account
    if correction != 0:
        if correction < 0:
            frm, to = to, frm
            correction *= -1
        transactions.append(
            schema.Transaction(
                frm,
                to,
                _oldest_transaction_date(transactions),
                'Balance correction',
                correction,
            ))
    assert real_balance == compute_balance(account, transactions)
Ejemplo n.º 6
0
def transactions_by_account(fileobj):
    account_name = fileobj.readline().rstrip('\n')
    balance = Decimal(fileobj.readline().rstrip('\n'))
    result = []
    lines = list(csv.reader(fileobj))[1:]
    for date, transaction_type, description, _, signed_amount_str in lines:
        signed_amount = Decimal(signed_amount_str.replace(',', ''))
        frm, to = '', account_name
        if signed_amount > 0:
            assert transaction_type == 'CREDIT'
        else:
            assert signed_amount < 0
            assert transaction_type == 'DEBIT'
            frm, to = to, frm
        month, day, year = map(int, date.split('/'))
        result.append(
            schema.Transaction(frm, to, schema.Date(year, month, day),
                               description, signed_amount.copy_abs()))
    correct_balance(account_name, balance, result)
    return {account_name: result}
Ejemplo n.º 7
0
def test_generate_data_json():
    transactions = [
        schema.Transaction(
            'bankA',
            'src',
            'dest',
            schema.Date(1940, '3', 26),
            'something',
            Decimal('29.99'),
            'foo',
        ),
    ]
    actual_parsed = json.loads(
        report._generate_data_json(transactions, ['some_account'])
    )
    expected_parsed = {
        'columns': ['bank', 'source', 'to', 'date', 'description',
            'amount', 'category'],
        'transactions': [['bankA', 'src', 'dest', '1940/03/26', 'something', '29.99', 'foo']],
        'accounts': ['some_account'],
    }
    assert_equal(actual_parsed, expected_parsed)
Ejemplo n.º 8
0
def _statement_transactions(st):
    result = []
    acctname = str(st.invacctfrom.acctid)
    for t in st.transactions:
        if hasattr(t, 'total'):
            # ignore investment buy/sell
            continue
        amount = t.trnamt
        frm, to = '', acctname
        if amount < 0:
            frm, to = to, frm
            amount *= -1
        result.append(
            schema.Transaction(
                frm,
                to,
                schema.Date(t.dtposted.year, t.dtposted.month, t.dtposted.day),
                str(t.memo),
                Decimal(amount),
            ))
    net = _networth(st)
    correct_balance(acctname, net, result)
    return result