185 lines
5.2 KiB
Python
185 lines
5.2 KiB
Python
|
"""test_meta_tax_reporting.py - Unit tests for tax-reporting metadata validation"""
|
||
|
# Copyright © 2021 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_tax_reporting
|
||
|
|
||
|
TEST_KEY = 'tax-reporting'
|
||
|
IMPLICATION_KEY = 'tax-implication'
|
||
|
|
||
|
REQUIRED_ACCOUNTS = {
|
||
|
'Assets:Checking',
|
||
|
'Assets:Bank:Savings',
|
||
|
}
|
||
|
|
||
|
NON_REQUIRED_ACCOUNTS = {
|
||
|
'Assets:Prepaid:Expenses',
|
||
|
'Assets:Receivable:Accounts',
|
||
|
'Liabilities:CreditCard',
|
||
|
}
|
||
|
|
||
|
REQUIRED_AMOUNTS = {-50, -500}
|
||
|
NON_REQUIRED_AMOUNTS = {-5, 500}
|
||
|
|
||
|
REQUIRED_IMPLICATIONS = {
|
||
|
'1099',
|
||
|
'1099-Misc-Other',
|
||
|
'foreign-grantee',
|
||
|
'Foreign-Individual-Contractor',
|
||
|
'USA-501c3',
|
||
|
'US-Grantee',
|
||
|
}
|
||
|
|
||
|
NON_REQUIRED_IMPLICATIONS = {
|
||
|
'Bank-Transfer',
|
||
|
'chargeback',
|
||
|
'Foreign-Corp',
|
||
|
'Loan',
|
||
|
'refund',
|
||
|
'Reimbursement',
|
||
|
'retirement-pretax',
|
||
|
'Tax-Payment',
|
||
|
'us-corp',
|
||
|
'w2',
|
||
|
}
|
||
|
|
||
|
@pytest.fixture(scope='module')
|
||
|
def hook():
|
||
|
config = testutil.TestConfig(payment_threshold=10)
|
||
|
return meta_tax_reporting.MetaTaxReporting(config)
|
||
|
|
||
|
@pytest.mark.parametrize('account,amount,implication,value', testutil.combine_values(
|
||
|
REQUIRED_ACCOUNTS,
|
||
|
REQUIRED_AMOUNTS,
|
||
|
REQUIRED_IMPLICATIONS,
|
||
|
testutil.LINK_METADATA_STRINGS,
|
||
|
))
|
||
|
def test_pass_on_txn(hook, account, amount, implication, value):
|
||
|
txn_meta = {
|
||
|
IMPLICATION_KEY: implication,
|
||
|
TEST_KEY: value,
|
||
|
}
|
||
|
txn = testutil.Transaction(**txn_meta, postings=[
|
||
|
(account, amount),
|
||
|
('Expenses:Other', -amount),
|
||
|
])
|
||
|
assert not list(hook.run(txn))
|
||
|
|
||
|
@pytest.mark.parametrize('account,amount,implication,value', testutil.combine_values(
|
||
|
REQUIRED_ACCOUNTS,
|
||
|
REQUIRED_AMOUNTS,
|
||
|
REQUIRED_IMPLICATIONS,
|
||
|
testutil.LINK_METADATA_STRINGS,
|
||
|
))
|
||
|
def test_pass_on_post(hook, account, amount, implication, value):
|
||
|
post_meta = {
|
||
|
IMPLICATION_KEY: implication,
|
||
|
TEST_KEY: value,
|
||
|
}
|
||
|
txn = testutil.Transaction(postings=[
|
||
|
(account, amount, post_meta),
|
||
|
('Expenses:Other', -amount),
|
||
|
])
|
||
|
assert not list(hook.run(txn))
|
||
|
|
||
|
@pytest.mark.parametrize('account,amount,implication', testutil.combine_values(
|
||
|
REQUIRED_ACCOUNTS,
|
||
|
REQUIRED_AMOUNTS,
|
||
|
REQUIRED_IMPLICATIONS,
|
||
|
))
|
||
|
def test_error_when_missing(hook, account, amount, implication):
|
||
|
txn = testutil.Transaction(postings=[
|
||
|
(account, amount, {IMPLICATION_KEY: implication}),
|
||
|
('Expenses:Other', -amount),
|
||
|
])
|
||
|
assert list(hook.run(txn))
|
||
|
|
||
|
@pytest.mark.parametrize('account,amount,implication,value', testutil.combine_values(
|
||
|
REQUIRED_ACCOUNTS,
|
||
|
REQUIRED_AMOUNTS,
|
||
|
REQUIRED_IMPLICATIONS,
|
||
|
testutil.NON_LINK_METADATA_STRINGS,
|
||
|
))
|
||
|
def test_error_when_empty(hook, account, amount, implication, value):
|
||
|
txn_meta = {
|
||
|
IMPLICATION_KEY: implication,
|
||
|
TEST_KEY: value,
|
||
|
}
|
||
|
txn = testutil.Transaction(**txn_meta, postings=[
|
||
|
(account, amount),
|
||
|
('Expenses:Other', -amount),
|
||
|
])
|
||
|
assert list(hook.run(txn))
|
||
|
|
||
|
@pytest.mark.parametrize('account,amount,implication,value', testutil.combine_values(
|
||
|
REQUIRED_ACCOUNTS,
|
||
|
REQUIRED_AMOUNTS,
|
||
|
REQUIRED_IMPLICATIONS,
|
||
|
testutil.NON_STRING_METADATA_VALUES,
|
||
|
))
|
||
|
def test_error_when_wrong_type(hook, account, amount, implication, value):
|
||
|
txn_meta = {
|
||
|
IMPLICATION_KEY: implication,
|
||
|
TEST_KEY: value,
|
||
|
}
|
||
|
txn = testutil.Transaction(**txn_meta, postings=[
|
||
|
(account, amount),
|
||
|
('Expenses:Other', -amount),
|
||
|
])
|
||
|
assert list(hook.run(txn))
|
||
|
|
||
|
@pytest.mark.parametrize('account,amount,implication', testutil.combine_values(
|
||
|
NON_REQUIRED_ACCOUNTS,
|
||
|
REQUIRED_AMOUNTS,
|
||
|
REQUIRED_IMPLICATIONS,
|
||
|
))
|
||
|
def test_skip_by_account(hook, account, amount, implication):
|
||
|
txn = testutil.Transaction(postings=[
|
||
|
(account, amount, {IMPLICATION_KEY: implication}),
|
||
|
('Expenses:Other', -amount),
|
||
|
])
|
||
|
assert not list(hook.run(txn))
|
||
|
|
||
|
@pytest.mark.parametrize('account,amount,implication', testutil.combine_values(
|
||
|
REQUIRED_ACCOUNTS,
|
||
|
NON_REQUIRED_AMOUNTS,
|
||
|
REQUIRED_IMPLICATIONS,
|
||
|
))
|
||
|
def test_skip_by_amount(hook, account, amount, implication):
|
||
|
txn = testutil.Transaction(postings=[
|
||
|
(account, amount, {IMPLICATION_KEY: implication}),
|
||
|
('Expenses:Other', -amount),
|
||
|
])
|
||
|
assert not list(hook.run(txn))
|
||
|
|
||
|
@pytest.mark.parametrize('account,amount,implication', testutil.combine_values(
|
||
|
REQUIRED_ACCOUNTS,
|
||
|
REQUIRED_AMOUNTS,
|
||
|
NON_REQUIRED_IMPLICATIONS,
|
||
|
))
|
||
|
def test_skip_by_implication(hook, account, amount, implication):
|
||
|
txn = testutil.Transaction(postings=[
|
||
|
(account, amount, {IMPLICATION_KEY: implication}),
|
||
|
('Expenses:Other', -amount),
|
||
|
])
|
||
|
assert not list(hook.run(txn))
|
||
|
|
||
|
@pytest.mark.parametrize('account,amount,implication', testutil.combine_values(
|
||
|
REQUIRED_ACCOUNTS,
|
||
|
REQUIRED_AMOUNTS,
|
||
|
REQUIRED_IMPLICATIONS,
|
||
|
))
|
||
|
def test_skip_by_flag(hook, account, amount, implication):
|
||
|
txn = testutil.Transaction(flag='!', postings=[
|
||
|
(account, amount, {IMPLICATION_KEY: implication}),
|
||
|
('Expenses:Other', -amount),
|
||
|
])
|
||
|
assert not list(hook.run(txn))
|