Files @ 5784068904e8
Branch filter:

Location: NPO-Accounting/conservancy_beancount/tests/test_data_posting.py

bkuhn
payroll-type — US:403b:Employee:Roth — needed separate since taxable

Since Roth contributions are taxable, there are some reports that
need to include these amounts in total salary (i.e., when running a
report that seeks to show total taxable income for an employee). As
such, we need a `payroll-type` specifically for Roth 403(b)
contributions.
"""Test Posting methods"""
# Copyright © 2020  Brett Smith
# License: AGPLv3-or-later WITH Beancount-Plugin-Additional-Permission-1.0
#
# Full copyright and licensing details can be found at toplevel file
# LICENSE.txt in the repository.

import pytest

from . import testutil

from beancount.core import data as bc_data

from conservancy_beancount import data

@pytest.fixture
def simple_txn(index=None, key=None):
    return testutil.Transaction(note='txn note', postings=[
        ('Assets:Cash', 5),
        ('Income:Donations', -5, {'note': 'donation love', 'extra': 'Extra'}),
    ])

def test_from_beancount():
    txn = testutil.Transaction(payee='Smith-Dakota', postings=[
        ('Income:Donations', -50),
        ('Assets:Cash', 50, {'receipt': 'cash-donation.pdf'}),
    ])
    post = data.Posting.from_beancount(txn, 1)
    # We don't just want to assert isinstance(post.attr, data.SomeClass);
    # we also want to double-check that attributes were instantiated correctly.
    assert post.account.is_under('Assets:Cash')
    assert post.meta['receipt'] == 'cash-donation.pdf'
    assert post.meta['entity'] == 'Smith-Dakota'
    assert post.meta.date == testutil.FY_MID_DATE

def test_setting_metadata_propagates_to_source(simple_txn):
    src_post = simple_txn.postings[1]
    post = data.Posting.from_beancount(simple_txn, 1)
    post.meta['edited'] = 'yes'
    assert src_post.meta['edited'] == 'yes'
    assert not isinstance(src_post.meta, data.PostingMeta)

def test_deleting_metadata_propagates_to_source(simple_txn):
    post = data.Posting.from_beancount(simple_txn, 1)
    del post.meta['extra']
    assert 'extra' not in simple_txn.postings[1].meta

def test_from_txn(simple_txn):
    for source, post in zip(simple_txn.postings, data.Posting.from_txn(simple_txn)):
        assert all(source[x] == post[x] for x in range(len(source) - 1))
        assert isinstance(post.account, data.Account)
        assert post.meta['note']  # Only works with PostingMeta

def test_from_entries_two_txns(simple_txn):
    entries = [simple_txn, simple_txn]
    sources = [post for txn in entries for post in txn.postings]
    for source, post in zip(sources, data.Posting.from_entries(entries)):
        assert all(source[x] == post[x] for x in range(len(source) - 1))
        assert isinstance(post.account, data.Account)
        assert post.meta['note']  # Only works with PostingMeta

def test_from_entries_mix_txns_and_other_directives(simple_txn):
    meta = {
        'filename': __file__,
        'lineno': 75,
    }
    entries = [
        bc_data.Commodity(meta, testutil.FY_START_DATE, 'EUR'),
        bc_data.Commodity(meta, testutil.FY_START_DATE, 'USD'),
        simple_txn,
    ]
    for source, post in zip(simple_txn.postings, data.Posting.from_entries(entries)):
        assert all(source[x] == post[x] for x in range(len(source) - 1))
        assert isinstance(post.account, data.Account)
        assert post.meta['note']  # Only works with PostingMeta

@pytest.mark.parametrize('cost_num', [105, 110, 115])
def test_at_cost(cost_num):
    post = data.Posting(
        'Income:Donations',
        testutil.Amount(25, 'EUR'),
        testutil.Cost(cost_num, 'JPY'),
        None,
        '*',
        None,
    )
    assert post.at_cost() == testutil.Amount(25 * cost_num, 'JPY')

def test_at_cost_no_cost():
    amount = testutil.Amount(25, 'EUR')
    post = data.Posting(
        'Income:Donations',
        amount,
        None,
        None,
        '*',
        None,
    )
    assert post.at_cost() == amount