Files @ 5784068904e8
Branch filter:

Location: NPO-Accounting/conservancy_beancount/tests/test_meta_income_type.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 handling of income-type metadata"""
# 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 conservancy_beancount.plugin import meta_income_type

VALID_VALUES = {
    'Donations': 'Donations',
    'Payable-Derecognition': 'Payable-Derecognition',
    'RBI': 'RBI',
    'UBTI': 'UBTI',
}

INVALID_VALUES = {
    'Dontion',
    'Payble-Derecognitoin',
    'RIB',
    'UTBI',
    '',
}

TEST_KEY = 'income-type'

@pytest.fixture(scope='module')
def hook():
    config = testutil.TestConfig()
    return meta_income_type.MetaIncomeType(config)

@pytest.mark.parametrize('src_value,set_value', VALID_VALUES.items())
def test_valid_values_on_postings(hook, src_value, set_value):
    txn = testutil.Transaction(postings=[
        ('Assets:Cash', 25),
        ('Income:Other', -25, {TEST_KEY: src_value}),
    ])
    errors = list(hook.run(txn))
    assert not errors
    testutil.check_post_meta(txn, None, {TEST_KEY: set_value})

@pytest.mark.parametrize('src_value', INVALID_VALUES)
def test_invalid_values_on_postings(hook, src_value):
    txn = testutil.Transaction(postings=[
        ('Assets:Cash', 25),
        ('Income:Other', -25, {TEST_KEY: src_value}),
    ])
    errors = list(hook.run(txn))
    assert errors
    testutil.check_post_meta(txn, None, {TEST_KEY: src_value})

@pytest.mark.parametrize('src_value,set_value', VALID_VALUES.items())
def test_valid_values_on_transactions(hook, src_value, set_value):
    txn = testutil.Transaction(**{TEST_KEY: src_value}, postings=[
        ('Assets:Cash', 25),
        ('Income:Other', -25),
    ])
    errors = list(hook.run(txn))
    assert not errors
    testutil.check_post_meta(txn, None, {TEST_KEY: set_value})

@pytest.mark.parametrize('src_value', INVALID_VALUES)
def test_invalid_values_on_transactions(hook, src_value):
    txn = testutil.Transaction(**{TEST_KEY: src_value}, postings=[
        ('Assets:Cash', 25),
        ('Income:Other', -25),
    ])
    errors = list(hook.run(txn))
    assert errors
    testutil.check_post_meta(txn, None, None)

@pytest.mark.parametrize('account', [
    'Assets:Cash',
    'Assets:Receivable:Accounts',
    'Equity:OpeningBalance',
    'Expenses:Other',
    'Liabilities:CreditCard',
    'Liabilities:Payable:Vacation',
])
def test_non_income_accounts_skipped(hook, account):
    meta = {TEST_KEY: 'RBI'}
    txn = testutil.Transaction(postings=[
        (account, 25),
        ('Income:Other', -25, meta.copy()),
    ])
    errors = list(hook.run(txn))
    assert not errors
    testutil.check_post_meta(txn, None, meta)

@pytest.mark.parametrize('account,set_value', [
    ('Income:Conferences:Registrations', 'RBI'),
    ('Income:Conferences:Sponsorship', 'RBI'),
    ('Income:Donations', 'Donations'),
    ('Income:Honoraria', 'RBI'),
    ('Income:Interest', 'RBI'),
    ('Income:Interest:Dividend', 'RBI'),
    ('Income:Royalties', 'RBI'),
    ('Income:Sales', 'RBI'),
    ('Income:SoftwareDevelopment', 'RBI'),
    ('Income:TrademarkLicensing', 'RBI'),
    ('Income:TrademarkSales', 'RBI'),
])
def test_default_values(hook, account, set_value):
    txn = testutil.Transaction(postings=[
        ('Assets:Cash', 25),
        (account, -25),
    ])
    errors = list(hook.run(txn))
    assert not errors
    testutil.check_post_meta(txn, None, {TEST_KEY: set_value})

@pytest.mark.parametrize('account', [
    'Income:Other',
])
def test_no_default_value(hook, account):
    txn = testutil.Transaction(postings=[
        ('Assets:Cash', 25),
        (account, -25),
    ])
    errors = list(hook.run(txn))
    assert errors
    testutil.check_post_meta(txn, None, None)

@pytest.mark.parametrize('date,set_value', [
    (testutil.EXTREME_FUTURE_DATE, None),
    (testutil.FUTURE_DATE, 'Donations'),
    (testutil.FY_START_DATE, 'Donations'),
    (testutil.FY_MID_DATE, 'Donations'),
    (testutil.PAST_DATE, None),
])
def test_default_value_set_in_date_range(hook, date, set_value):
    txn = testutil.Transaction(date=date, postings=[
        ('Assets:Cash', 25),
        ('Income:Donations', -25),
    ])
    errors = list(hook.run(txn))
    assert not errors
    expect_meta = None if set_value is None else {TEST_KEY: set_value}
    testutil.check_post_meta(txn, None, expect_meta)

@pytest.mark.parametrize('src_value', INVALID_VALUES)
def test_flagged_txn_checked(hook, src_value):
    txn = testutil.Transaction(flag='!', postings=[
        ('Assets:Cash', 25),
        ('Income:Other', -25, {TEST_KEY: src_value}),
    ])
    errors = list(hook.run(txn))
    assert errors
    testutil.check_post_meta(txn, None, {TEST_KEY: src_value})

@pytest.mark.parametrize('src_value', testutil.FIXME_VALUES)
def test_flagged_fixme_ok(hook, src_value):
    txn = testutil.Transaction(flag='!', postings=[
        ('Assets:Cash', 25),
        ('Income:Other', -25, {TEST_KEY: src_value}),
    ])
    errors = list(hook.run(txn))
    assert not errors
    testutil.check_post_meta(txn, None, {TEST_KEY: src_value})