diff --git a/tests/test_meta_tax_implication.py b/tests/test_meta_tax_implication.py new file mode 100644 index 0000000000000000000000000000000000000000..94aa70a91a8dfbb8bc4f24d198c7a2189e02d716 --- /dev/null +++ b/tests/test_meta_tax_implication.py @@ -0,0 +1,132 @@ +"""Test handling of tax-implication metadata""" +# Copyright © 2020 Brett Smith +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import pytest + +from . import testutil + +from conservancy_beancount.plugin import meta_tax_implication + +VALID_VALUES = { + '1099': '1099', + 'Accountant-Advises-No-1099': 'Accountant-Advises-No-1099', + 'Bank-Transfer': 'Bank-Transfer', + 'Foreign-Corporation': 'Foreign-Corporation', + 'Foreign-Individual-Contractor': 'Foreign-Individual-Contractor', + 'Fraud': 'Fraud', + 'HSA-Contribution': 'HSA-Contribution', + 'Loan': 'Loan', + 'Payroll': 'Payroll', + 'Refund': 'Refund', + 'Reimbursement': 'Reimbursement', + 'Retirement-Pretax': 'Retirement-Pretax', + 'Tax-Payment': 'Tax-Payment', + 'USA-501c3': 'USA-501c3', + 'USA-Corporation': 'USA-Corporation', + 'USA-LLC-No-1099': 'USA-LLC-No-1099', + 'W2': 'W2', +} + +INVALID_VALUES = { + '199', + 'W3', + 'Payrol', + '', +} + +TEST_KEY = 'tax-implication' + +@pytest.mark.parametrize('src_value,set_value', VALID_VALUES.items()) +def test_valid_values_on_postings(src_value, set_value): + txn = testutil.Transaction(postings=[ + ('Accrued:AccountsPayable', 25), + ('Assets:Cash', -25, {TEST_KEY: src_value}), + ]) + checker = meta_tax_implication.MetaTaxImplication() + errors = checker.run(txn, txn.postings[-1], -1) + assert not errors + assert txn.postings[-1].meta.get(TEST_KEY) == set_value + +@pytest.mark.parametrize('src_value', INVALID_VALUES) +def test_invalid_values_on_postings(src_value): + txn = testutil.Transaction(postings=[ + ('Accrued:AccountsPayable', 25), + ('Assets:Cash', -25, {TEST_KEY: src_value}), + ]) + checker = meta_tax_implication.MetaTaxImplication() + errors = checker.run(txn, txn.postings[-1], -1) + assert errors + +@pytest.mark.parametrize('src_value,set_value', VALID_VALUES.items()) +def test_valid_values_on_transactions(src_value, set_value): + txn = testutil.Transaction(**{TEST_KEY: src_value}, postings=[ + ('Accrued:AccountsPayable', 25), + ('Assets:Cash', -25), + ]) + checker = meta_tax_implication.MetaTaxImplication() + errors = checker.run(txn, txn.postings[-1], -1) + assert not errors + assert txn.postings[-1].meta.get(TEST_KEY) == set_value + +@pytest.mark.parametrize('src_value', INVALID_VALUES) +def test_invalid_values_on_transactions(src_value): + txn = testutil.Transaction(**{TEST_KEY: src_value}, postings=[ + ('Accrued:AccountsPayable', 25), + ('Assets:Cash', -25), + ]) + checker = meta_tax_implication.MetaTaxImplication() + errors = checker.run(txn, txn.postings[-1], -1) + assert errors + +@pytest.mark.parametrize('account', [ + 'Accrued:AccountsPayable', + 'Expenses:General', + 'Liabilities:CreditCard', +]) +def test_non_asset_accounts_skipped(account): + txn = testutil.Transaction(postings=[ + (account, 25), + ('Assets:Cash', -25, {TEST_KEY: 'USA-Corporation'}), + ]) + checker = meta_tax_implication.MetaTaxImplication() + errors = checker.run(txn, txn.postings[0], 0) + assert not errors + +def test_asset_credits_skipped(): + txn = testutil.Transaction(postings=[ + ('Income:Donations', -25), + ('Assets:Cash', 25), + ]) + checker = meta_tax_implication.MetaTaxImplication() + errors = checker.run(txn, txn.postings[-1], -1) + assert not errors + assert not txn.postings[-1].meta + +@pytest.mark.parametrize('date,need_value', [ + (testutil.EXTREME_FUTURE_DATE, False), + (testutil.FUTURE_DATE, True), + (testutil.FY_START_DATE, True), + (testutil.FY_MID_DATE, True), + (testutil.PAST_DATE, False), +]) +def test_default_value_set_in_date_range(date, need_value): + txn = testutil.Transaction(date=date, postings=[ + ('Liabilites:CreditCard', 25), + ('Assets:Cash', -25), + ]) + checker = meta_tax_implication.MetaTaxImplication() + errors = checker.run(txn, txn.postings[-1], -1) + assert bool(errors) == bool(need_value)