diff --git a/conservancy_beancount/data.py b/conservancy_beancount/data.py index 3af7eff9bab6d6a3fa85c86a33cc08f0088b09f0..1af27ac65b64cf649492e8d1a9ed246b2de6327a 100644 --- a/conservancy_beancount/data.py +++ b/conservancy_beancount/data.py @@ -58,7 +58,7 @@ LINK_METADATA = frozenset([ class Account(str): """Account name string - This is a string that names an account, like Accrued:AccountsPayable + This is a string that names an account, like Assets:Bank:Checking or Income:Donations. This class provides additional methods for common account name parsing and queries. """ @@ -66,17 +66,17 @@ class Account(str): SEP = bc_account.sep - def is_checking(self) -> bool: - return self.is_real_asset() and ':Check' in self + def is_cash_equivalent(self) -> bool: + return ( + self.is_under('Assets:') is not None + and self.is_under('Assets:Prepaid', 'Assets:Receivable') is None + ) - def is_income(self) -> bool: - return self.is_under('Income:', 'UnearnedIncome:') is not None + def is_checking(self) -> bool: + return self.is_cash_equivalent() and ':Check' in self - def is_real_asset(self) -> bool: - return bool( - self.is_under('Assets:') - and not self.is_under('Assets:PrepaidExpenses', 'Assets:PrepaidVacation') - ) + def is_credit_card(self) -> bool: + return self.is_under('Liabilities:CreditCard') is not None def is_under(self, *acct_seq: str) -> Optional[str]: """Return a match if this account is "under" a part of the hierarchy @@ -248,7 +248,7 @@ class Posting(BasePosting): threshold: DecimalCompat=0, default: Optional[bool]=None, ) -> Optional[bool]: - return self.account.is_real_asset() and self.is_debit(threshold, default) + return self.account.is_cash_equivalent() and self.is_debit(threshold, default) def iter_postings(txn: Transaction) -> Iterator[Posting]: diff --git a/conservancy_beancount/plugin/meta_entity.py b/conservancy_beancount/plugin/meta_entity.py index ee655f41111fc60745f0a2241291bc752f47a26f..78d562f356e7d2f6fd4889e0ef0c1a408035faa3 100644 --- a/conservancy_beancount/plugin/meta_entity.py +++ b/conservancy_beancount/plugin/meta_entity.py @@ -59,7 +59,12 @@ class MetaEntity(core.TransactionHook): if txn_entity_ok is False: yield errormod.InvalidMetadataError(txn, self.METADATA_KEY, txn_entity) for post in data.iter_postings(txn): - if post.account.is_under('Assets', 'Equity', 'Liabilities'): + if not post.account.is_under( + 'Assets:Receivable', + 'Expenses', + 'Income', + 'Liabilities:Payable', + ): continue entity = post.meta.get(self.METADATA_KEY) if entity is None: diff --git a/conservancy_beancount/plugin/meta_income_type.py b/conservancy_beancount/plugin/meta_income_type.py index 73038b63d754b7643785b71ea307349c972a563e..3834347b5d56434cc252ae7db9dc9eb99c3fa7de 100644 --- a/conservancy_beancount/plugin/meta_income_type.py +++ b/conservancy_beancount/plugin/meta_income_type.py @@ -30,6 +30,8 @@ class MetaIncomeType(core._NormalizePostingMetadataHook): 'UBTI', }) DEFAULT_VALUES = { + 'Income:Conferences:Registrations': 'RBI', + 'Income:Conferences:Sponsorship': 'RBI', 'Income:Donations': 'Donations', 'Income:Honoraria': 'RBI', 'Income:Interest': 'RBI', @@ -38,12 +40,10 @@ class MetaIncomeType(core._NormalizePostingMetadataHook): 'Income:Sales': 'RBI', 'Income:SoftwareDevelopment': 'RBI', 'Income:TrademarkLicensing': 'RBI', - 'UnearnedIncome:Conferences:Registrations': 'RBI', - 'UnearnedIncome:MatchPledges': 'Donations', } def _run_on_post(self, txn: Transaction, post: data.Posting) -> bool: - return post.account.is_income() + return post.account.is_under('Income') is not None def _default_value(self, txn: Transaction, post: data.Posting) -> MetaValueEnum: try: diff --git a/conservancy_beancount/plugin/meta_invoice.py b/conservancy_beancount/plugin/meta_invoice.py index 5ab7f4342ef788948ab546304602b1d8d02efe83..a9e25194f23725fdd49e741c486bfae92400018d 100644 --- a/conservancy_beancount/plugin/meta_invoice.py +++ b/conservancy_beancount/plugin/meta_invoice.py @@ -26,4 +26,7 @@ class MetaInvoice(core._RequireLinksPostingMetadataHook): METADATA_KEY = 'invoice' def _run_on_post(self, txn: Transaction, post: data.Posting) -> bool: - return post.account.is_under('Accrued') is not None + return post.account.is_under( + 'Assets:Receivable', + 'Liabilities:Payable', + ) is not None diff --git a/conservancy_beancount/plugin/meta_project.py b/conservancy_beancount/plugin/meta_project.py index ccde207243496385c7cf6021cbab0c324c483d83..b47d9fe6ab20aaf16afb90bedc7ccdab513cf90f 100644 --- a/conservancy_beancount/plugin/meta_project.py +++ b/conservancy_beancount/plugin/meta_project.py @@ -79,12 +79,19 @@ class MetaProject(core._NormalizePostingMetadataHook): ) def _run_on_post(self, txn: Transaction, post: data.Posting) -> bool: - return post.account.is_under('Assets', 'Equity', 'Liabilities') is None + if post.account.is_under('Liabilities'): + return not post.account.is_credit_card() + else: + return post.account.is_under( + 'Assets:Receivable', + 'Expenses', + 'Income', + ) is not None def _default_value(self, txn: Transaction, post: data.Posting) -> MetaValueEnum: if post.account.is_under( - 'Accrued:VacationPayable', 'Expenses:Payroll', + 'Liabilities:Payable:Vacation', ): return self.DEFAULT_PROJECT else: diff --git a/conservancy_beancount/plugin/meta_receipt.py b/conservancy_beancount/plugin/meta_receipt.py index 9166409860ff40c62ded18240b8d1d7f1a224664..a524656e8c85b7cc10a30b6d8f493b9a308dcaab 100644 --- a/conservancy_beancount/plugin/meta_receipt.py +++ b/conservancy_beancount/plugin/meta_receipt.py @@ -29,8 +29,8 @@ class MetaReceipt(core._RequireLinksPostingMetadataHook): self.payment_threshold = abs(config.payment_threshold()) def _run_on_post(self, txn: Transaction, post: data.Posting) -> bool: - return bool( - (post.account.is_real_asset() or post.account.is_under('Liabilities')) + return ( + (post.account.is_cash_equivalent() or post.account.is_credit_card()) and post.units.number is not None and abs(post.units.number) >= self.payment_threshold ) @@ -52,7 +52,7 @@ class MetaReceipt(core._RequireLinksPostingMetadataHook): if post.account.is_checking(): fallback_key = 'check' - elif post.account.is_under('Liabilities:CreditCard') and post_amount == -1: + elif post.account.is_credit_card() and post_amount == -1: fallback_key = 'invoice' elif post.account.is_under('Assets:PayPal') and post_amount == 1: fallback_key = 'paypal-id' diff --git a/conservancy_beancount/plugin/meta_receivable_documentation.py b/conservancy_beancount/plugin/meta_receivable_documentation.py index 9c79eb54e7e1ac45a42240aabf30d5ab3db54cd2..beb322b1599eb6c82d4c65f5720f51dcaf93a1ca 100644 --- a/conservancy_beancount/plugin/meta_receivable_documentation.py +++ b/conservancy_beancount/plugin/meta_receivable_documentation.py @@ -57,7 +57,7 @@ class MetaReceivableDocumentation(core._RequireLinksPostingMetadataHook): self.rt = rt_wrapper def _run_on_post(self, txn: Transaction, post: data.Posting) -> bool: - if not post.account.is_under('Accrued:AccountsReceivable'): + if not post.account.is_under('Assets:Receivable'): return False # Get the first invoice, or return False if it doesn't exist. diff --git a/tests/test_data_account.py b/tests/test_data_account.py index b2901d4b76cce2eacda52bac4a04ae6f2d83f530..978030489c8b33aed95e3fe0bca50a57fa15a1d5 100644 --- a/tests/test_data_account.py +++ b/tests/test_data_account.py @@ -26,55 +26,46 @@ from conservancy_beancount import data ('Expenses:Tax:Sales', 'Expenses:', True), ('Expenses:Tax:Sales', 'Expenses', True), ('Expenses:Tax:Sales', 'Expense', False), - ('Expenses:Tax:Sales', 'Accrued:', False), - ('Expenses:Tax:Sales', 'Accrued', False), + ('Expenses:Tax:Sales', 'Equity:', False), + ('Expenses:Tax:Sales', 'Equity', False), ]) def test_is_under_one_arg(acct_name, under_arg, expected): expected = under_arg if expected else None assert data.Account(acct_name).is_under(under_arg) == expected @pytest.mark.parametrize('acct_name,expected', [ - ('Income:Other', 'Income'), - ('UnearnedIncome:Other', 'UnearnedIncome'), - ('Accrued:AccountsPayable', None), - ('Expenses:General', None), + ('Assets:Cash', None), + ('Assets:Checking', None), + ('Assets:Prepaid:Expenses', 'Assets:Prepaid'), + ('Assets:Receivable:Accounts', 'Assets:Receivable'), ]) def test_is_under_multi_arg(acct_name, expected): - assert data.Account(acct_name).is_under('Income', 'UnearnedIncome') == expected + assert expected == data.Account(acct_name).is_under( + 'Assets:Prepaid', 'Assets:Receivable', + ) if expected: expected += ':' - assert data.Account(acct_name).is_under('Income:', 'UnearnedIncome:') == expected + assert expected == data.Account(acct_name).is_under( + 'Assets:Prepaid:', 'Assets:Receivable:', + ) @pytest.mark.parametrize('acct_name,expected', [ - ('Accrued:AccountsReceivable', False), - ('Assets:Cash', False), - ('Expenses:General', False), - ('Income:Donations', True), - ('Income:Sales', True), - ('Income:Other', True), - ('Liabilities:CreditCard', False), - ('UnearnedIncome:MatchPledges', True), -]) -def test_is_income(acct_name, expected): - assert data.Account(acct_name).is_income() == expected - -@pytest.mark.parametrize('acct_name,expected', [ - ('Accrued:AccountsPayable', False), - ('Accrued:AccountsReceivable', False), + ('Assets:Bank:Checking', True), ('Assets:Cash', True), ('Assets:Cash:EUR', True), - ('Assets:PrepaidExpenses', False), - ('Assets:PrepaidVacation', False), - ('Assets:Bank:Checking', True), - ('Expenses:General', False), - ('Income:Donations', False), + ('Assets:Prepaid:Expenses', False), + ('Assets:Prepaid:Vacation', False), + ('Assets:Receivable:Accounts', False), + ('Assets:Receivable:Fraud', False), + ('Expenses:Other', False), + ('Equity:OpeningBalance', False), + ('Income:Other', False), + ('Liabilities:CreditCard', False), ]) -def test_is_real_asset(acct_name, expected): - assert data.Account(acct_name).is_real_asset() == expected +def test_is_cash_equivalent(acct_name, expected): + assert data.Account(acct_name).is_cash_equivalent() == expected @pytest.mark.parametrize('acct_name,expected', [ - ('Accrued:AccountsPayable', False), - ('Accrued:AccountsReceivable', False), ('Assets:Bank:Check9999', True), ('Assets:Bank:CheckCard', True), ('Assets:Bank:Checking', True), @@ -83,10 +74,27 @@ def test_is_real_asset(acct_name, expected): ('Assets:Check9999', True), ('Assets:CheckCard', True), ('Assets:Checking', True), - ('Assets:PrepaidExpenses', False), - ('Assets:Savings', False), - ('Expenses:CheckingFees', False), - ('Income:Interest:Checking', False), + ('Assets:Prepaid:Expenses', False), + ('Assets:Receivable:Accounts', False), + ('Expenses:Other', False), + ('Equity:OpeningBalance', False), + ('Income:Other', False), + ('Liabilities:CreditCard', False), ]) def test_is_checking(acct_name, expected): assert data.Account(acct_name).is_checking() == expected + +@pytest.mark.parametrize('acct_name,expected', [ + ('Assets:Cash', False), + ('Assets:Prepaid:Expenses', False), + ('Assets:Receivable:Accounts', False), + ('Expenses:Other', False), + ('Equity:OpeningBalance', False), + ('Income:Other', False), + ('Liabilities:CreditCard', True), + ('Liabilities:CreditCard:Visa', True), + ('Liabilities:Payable:Accounts', False), + ('Liabilities:UnearnedIncome:Donations', False), +]) +def test_is_credit_card(acct_name, expected): + assert data.Account(acct_name).is_credit_card() == expected diff --git a/tests/test_data_posting.py b/tests/test_data_posting.py index 5f6dc05b18547dc793e86020bf4c889aca37a74f..708c940fc8b4e88fb8271d1bf32746fbe17c385d 100644 --- a/tests/test_data_posting.py +++ b/tests/test_data_posting.py @@ -26,17 +26,17 @@ from conservancy_beancount import data PAYMENT_ACCOUNTS = { 'Assets:Cash', - 'Assets:Checking', + 'Assets:Bank:Checking', } NON_PAYMENT_ACCOUNTS = { - 'Accrued:AccountsReceivable', - 'Assets:PrepaidExpenses', - 'Assets:PrepaidVacation', + 'Assets:Prepaid:Expenses', + 'Assets:Prepaid:Vacation', + 'Assets:Receivable:Accounts', + 'Equity:OpeningBalance', 'Expenses:Other', 'Income:Other', 'Liabilities:CreditCard', - 'UnearnedIncome:MatchPledges', } AMOUNTS = [ diff --git a/tests/test_meta_approval.py b/tests/test_meta_approval.py index 1d49825f3a64e164b19d6bf3faddbec7605c182c..90f01ec84f109d2446202918e2980ca9fd81e2f9 100644 --- a/tests/test_meta_approval.py +++ b/tests/test_meta_approval.py @@ -21,18 +21,18 @@ from . import testutil from conservancy_beancount.plugin import meta_approval REQUIRED_ACCOUNTS = { + 'Assets:Bank:Checking', 'Assets:Cash', - 'Assets:Checking', 'Assets:Savings', } NON_REQUIRED_ACCOUNTS = { - 'Accrued:AccountsPayable', - 'Assets:PrepaidExpenses', - 'Assets:PrepaidVacation', + 'Assets:Prepaid:Expenses', + 'Assets:Receivable:Accounts', + 'Equity:QpeningBalance', 'Expenses:Other', 'Income:Other', - 'UnearnedIncome:Donations', + 'Liabilities:Payable:Accounts', } CREDITCARD_ACCOUNT = 'Liabilities:CreditCard' diff --git a/tests/test_meta_entity.py b/tests/test_meta_entity.py index 35f6ffa3f2cdfa5f3baa76a585ad25ccb420b99f..4542fa4769b22f9acb0296e98a58b92ef02a684d 100644 --- a/tests/test_meta_entity.py +++ b/tests/test_meta_entity.py @@ -111,17 +111,21 @@ def test_invalid_values_on_transactions(hook, src_value): for error in hook.run(txn)) @pytest.mark.parametrize('account,required', [ - ('Accrued:AccountsReceivable', True), + ('Assets:Bank:Checking', False), ('Assets:Cash', False), + ('Assets:Receivable:Accounts', True), + ('Assets:Receivable:Loans', True), ('Equity:OpeningBalances', False), ('Expenses:General', True), ('Income:Donations', True), ('Liabilities:CreditCard', False), - ('UnearnedIncome:Donations', True), + ('Liabilities:Payable:Accounts', True), + ('Liabilities:Payable:Vacation', True), + ('Liabilities:UnearnedIncome:Donations', False), ]) def test_which_accounts_required_on(hook, account, required): txn = testutil.Transaction(postings=[ - ('Assets:Checking', 25), + ('Assets:Checking', -25), (account, 25), ]) errors = list(hook.run(txn)) diff --git a/tests/test_meta_expense_allocation.py b/tests/test_meta_expense_allocation.py index c96f88e4dc6c390358b4237a9bb106d95938c884..af081d9e389cbe5a8e06110adfef7046edcbad16 100644 --- a/tests/test_meta_expense_allocation.py +++ b/tests/test_meta_expense_allocation.py @@ -83,11 +83,12 @@ def test_invalid_values_on_transactions(hook, src_value): testutil.check_post_meta(txn, None, None) @pytest.mark.parametrize('account', [ - 'Accrued:AccountsReceivable', 'Assets:Cash', - 'Income:Donations', + 'Assets:Receivable:Accounts', + 'Equity:OpeningBalance', + 'Income:Other', 'Liabilities:CreditCard', - 'UnearnedIncome:Donations', + 'Liabilities:Payable:Vacation', ]) def test_non_expense_accounts_skipped(hook, account): meta = {TEST_KEY: 'program'} diff --git a/tests/test_meta_income_type.py b/tests/test_meta_income_type.py index 9adf4255305be9ec95e9d2584d4d13fd531f0489..0260bf071c852a7af5d1ab069ecb998b231b2550 100644 --- a/tests/test_meta_income_type.py +++ b/tests/test_meta_income_type.py @@ -83,10 +83,12 @@ def test_invalid_values_on_transactions(hook, src_value): testutil.check_post_meta(txn, None, None) @pytest.mark.parametrize('account', [ - 'Accrued:AccountsReceivable', 'Assets:Cash', - 'Expenses:General', + 'Assets:Receivable:Accounts', + 'Equity:OpeningBalance', + 'Expenses:Other', 'Liabilities:CreditCard', + 'Liabilities:Payable:Vacation', ]) def test_non_income_accounts_skipped(hook, account): meta = {TEST_KEY: 'RBI'} @@ -99,6 +101,8 @@ def test_non_income_accounts_skipped(hook, account): 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'), @@ -107,8 +111,6 @@ def test_non_income_accounts_skipped(hook, account): ('Income:Sales', 'RBI'), ('Income:SoftwareDevelopment', 'RBI'), ('Income:TrademarkLicensing', 'RBI'), - ('UnearnedIncome:Conferences:Registrations', 'RBI'), - ('UnearnedIncome:MatchPledges', 'Donations'), ]) def test_default_values(hook, account, set_value): txn = testutil.Transaction(postings=[ diff --git a/tests/test_meta_invoice.py b/tests/test_meta_invoice.py index fcaa6ce8845844e2c4051f5dff0fb8f0ca5f0e0b..b4c86d49e9a4ed711247daf112a175715fe90488 100644 --- a/tests/test_meta_invoice.py +++ b/tests/test_meta_invoice.py @@ -21,16 +21,18 @@ from . import testutil from conservancy_beancount.plugin import meta_invoice REQUIRED_ACCOUNTS = { - 'Accrued:AccountsPayable', - 'Accrued:AccountsReceivable', + 'Assets:Receivable:Accounts', + 'Assets:Receivable:Loans', + 'Liabilities:Payable:Accounts', + 'Liabilities:Payable:Vacation', } NON_REQUIRED_ACCOUNTS = { 'Assets:Cash', + 'Equity:OpeningBalance', 'Expenses:Other', 'Income:Other', 'Liabilities:CreditCard', - 'UnearnedIncome:Donations', } TEST_KEY = 'invoice' diff --git a/tests/test_meta_project.py b/tests/test_meta_project.py index ae5d3f0286cfbd6166dcbfb4fde33781bb81d059..5c372dcccf5756ebac80640d709f158bccbdfc54 100644 --- a/tests/test_meta_project.py +++ b/tests/test_meta_project.py @@ -86,13 +86,17 @@ def test_invalid_values_on_transactions(hook, src_value): testutil.check_post_meta(txn, None, None) @pytest.mark.parametrize('account,required', [ - ('Accrued:AccountsReceivable', True), ('Assets:Cash', False), - ('Equity:Opening-Balances', False), + ('Assets:Receivable:Accounts', True), + ('Assets:Receivable:Loans', True), + ('Equity:OpeningBalance', False), ('Expenses:General', True), ('Income:Donations', True), ('Liabilities:CreditCard', False), - ('UnearnedIncome:Donations', True), + ('Liabilities:Payable:Accounts', True), + # We do want a "project" for Lia:Pay:Vacation but it has a default value + ('Liabilities:Payable:Vacation', False), + ('Liabilities:UnearnedIncome:Donations', True), ]) def test_which_accounts_required_on(hook, account, required): txn = testutil.Transaction(postings=[ @@ -103,9 +107,9 @@ def test_which_accounts_required_on(hook, account, required): assert required == any(errors) @pytest.mark.parametrize('account', [ - 'Accrued:VacationPayable', 'Expenses:Payroll:Salary', 'Expenses:Payroll:Tax', + 'Liabilities:Payable:Vacation', ]) def test_default_values(hook, account): txn = testutil.Transaction(postings=[ @@ -126,7 +130,7 @@ def test_default_values(hook, account): def test_default_value_set_in_date_range(hook, date, required): txn = testutil.Transaction(date=date, postings=[ ('Expenses:Payroll:Benefits', 25), - ('Accrued:VacationPayable', -25), + ('Liabilities:Payable:Vacation', -25), ]) errors = list(hook.run(txn)) assert not errors diff --git a/tests/test_meta_receipt.py b/tests/test_meta_receipt.py index 6f24302cab3f1ed3532a424f2d03c59708d1483e..82a1b021fc9caaf64de76d8135532d02610fca63 100644 --- a/tests/test_meta_receipt.py +++ b/tests/test_meta_receipt.py @@ -77,13 +77,13 @@ KNOWN_FALLBACKS = {acct.fallback_meta for acct in ACCOUNTS_WITH_FALLBACKS} # doesn't require the decorated test to go over every value, which in turn # trims unnecessary test time. NOT_REQUIRED_ACCOUNTS = itertools.cycle([ - 'Accrued:AccountsPayable', - 'Accrued:AccountsReceivable', - 'Assets:PrepaidExpenses', - 'Assets:PrepaidVacation', + 'Assets:Prepaid:Expenses', + 'Assets:Receivable:Accounts', + 'Equity:OpeningBalance', 'Expenses:Other', 'Income:Other', - 'UnearnedIncome:Donations', + 'Liabilities:Payable:Accounts', + 'Liabilities:UnearnedIncome:Donations', ]) def check(hook, test_acct, other_acct, expected, *, diff --git a/tests/test_meta_receivable_documentation.py b/tests/test_meta_receivable_documentation.py index 9dbf6de1cd8a069c1048ae8b0bc0b3ce08ff498d..853a9cabda4f683a7d32d330d675d2e90a1ccb41 100644 --- a/tests/test_meta_receivable_documentation.py +++ b/tests/test_meta_receivable_documentation.py @@ -23,7 +23,7 @@ from . import testutil from conservancy_beancount import errors as errormod from conservancy_beancount.plugin import meta_receivable_documentation -TEST_ACCT = 'Accrued:AccountsReceivable' +TEST_ACCT = 'Assets:Receivable:Accounts' OTHER_ACCT = 'Income:Donations' SUPPORTING_METADATA = [ @@ -178,9 +178,17 @@ def test_type_errors_reported_with_valid_txn_docs(hook, invoice, support_key, su def test_received_invoices_not_checked(hook, invoice, meta_type): check(hook, None, **{meta_type: {'invoice': invoice}}) -def test_does_not_apply_to_payables(hook): +@pytest.mark.parametrize('account', [ + 'Assets:Bank:Checking', + 'Assets:Cash', + 'Equity:OpeningBalance', + 'Expenses:BankingFees', + 'Liabilities:CreditCard', + 'Liabilities:Payable:Accounts', +]) +def test_does_not_apply_to_other_accounts(hook, account): meta = seed_meta() - check(hook, None, 'Accrued:AccountsPayable', 'Expenses:Other', post_meta=meta) + check(hook, None, account, 'Expenses:Other', post_meta=meta) def test_configuration_error_without_rt(): config = testutil.TestConfig() diff --git a/tests/test_meta_tax_implication.py b/tests/test_meta_tax_implication.py index 2e98dcb623074b19c381b12c5e79140e2b87f242..62d80f79662d206a4cca46d0f99ab242bf613361 100644 --- a/tests/test_meta_tax_implication.py +++ b/tests/test_meta_tax_implication.py @@ -57,7 +57,7 @@ def hook(): @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=[ - ('Accrued:AccountsPayable', 25), + ('Liabilities:Payable:Accounts', 25), ('Assets:Cash', -25, {TEST_KEY: src_value}), ]) errors = list(hook.run(txn)) @@ -67,7 +67,7 @@ def test_valid_values_on_postings(hook, src_value, set_value): @pytest.mark.parametrize('src_value', INVALID_VALUES) def test_invalid_values_on_postings(hook, src_value): txn = testutil.Transaction(postings=[ - ('Accrued:AccountsPayable', 25), + ('Liabilities:Payable:Accounts', 25), ('Assets:Cash', -25, {TEST_KEY: src_value}), ]) errors = list(hook.run(txn)) @@ -77,7 +77,7 @@ def test_invalid_values_on_postings(hook, 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=[ - ('Accrued:AccountsPayable', 25), + ('Liabilities:Payable:Accounts', 25), ('Assets:Cash', -25), ]) errors = list(hook.run(txn)) @@ -87,37 +87,34 @@ def test_valid_values_on_transactions(hook, src_value, 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=[ - ('Accrued:AccountsPayable', 25), + ('Liabilities:Payable:Accounts', 25), ('Assets:Cash', -25), ]) errors = list(hook.run(txn)) assert errors testutil.check_post_meta(txn, None, None) -@pytest.mark.parametrize('account', [ - 'Accrued:AccountsPayable', - 'Expenses:General', +@pytest.mark.parametrize('count,account', enumerate([ + 'Assets:Payable:Accounts', + 'Assets:Prepaid:Expenses', + 'Equity:OpeningBalance', + 'Expenses:Other', + 'Income:Other', 'Liabilities:CreditCard', -]) -def test_non_asset_accounts_skipped(hook, account): + 'Liabilities:Payable:Accounts', + 'Liabilities:UnearnedIncome:Donations', +], 1)) +def test_non_payment_accounts_skipped(hook, account, count): + amount = count * 100 meta = {TEST_KEY: 'USA-Corporation'} txn = testutil.Transaction(postings=[ - (account, 25), - ('Assets:Cash', -25, meta.copy()), + (account, amount), + ('Assets:Checking', -amount, meta.copy()), ]) errors = list(hook.run(txn)) assert not errors testutil.check_post_meta(txn, None, meta) -def test_prepaid_expenses_skipped(hook, ): - txn = testutil.Transaction(postings=[ - ('Expenses:General', 25), - ('Assets:PrepaidExpenses', -25), - ]) - errors = list(hook.run(txn)) - assert not errors - testutil.check_post_meta(txn, None, None) - def test_asset_credits_skipped(hook, ): txn = testutil.Transaction(postings=[ ('Income:Donations', -25),