From 16c47c64b23d187ef9b8248ea429652b50324eb6 Mon Sep 17 00:00:00 2001 From: Brett Smith Date: Thu, 5 Mar 2020 14:37:47 -0500 Subject: [PATCH] expenseAllocation: Date-limit the transactions we work on. This prevents the plugin from giving meaning to postings that might not really be there. --- conservancy_beancount/plugin/core.py | 23 ++++++++++++++++++++++- tests/test_meta_expenseAllocation.py | 18 ++++++++++++++++++ tests/testutil.py | 3 +++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/conservancy_beancount/plugin/core.py b/conservancy_beancount/plugin/core.py index d3f42b5..befa40c 100644 --- a/conservancy_beancount/plugin/core.py +++ b/conservancy_beancount/plugin/core.py @@ -14,10 +14,31 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import datetime + from . import errors as errormod +DEFAULT_START_DATE = datetime.date(2020, 3, 1) +DEFAULT_STOP_DATE = datetime.date(datetime.MAXYEAR, 1, 1) + +class _GenericRange: + def __init__(self, start, stop): + self.start = start + self.stop = stop + + def __repr__(self): + return "{clsname}({self.start!r}, {self.stop!r})".format( + clsname=type(self).__name__, + self=self, + ) + + def __contains__(self, item): + return self.start <= item < self.stop + + class PostingChecker: ACCOUNTS = ('',) + TXN_DATE_RANGE = _GenericRange(DEFAULT_START_DATE, DEFAULT_STOP_DATE) VALUES_ENUM = {} def _meta_get(self, txn, post, key, default=None): @@ -35,7 +56,7 @@ class PostingChecker: raise errormod.InvalidMetadataError(txn, post, self.METADATA_KEY) def _should_check(self, txn, post): - ok = True + ok = txn.date in self.TXN_DATE_RANGE if isinstance(self.ACCOUNTS, tuple): ok = ok and post.account.startswith(self.ACCOUNTS) else: diff --git a/tests/test_meta_expenseAllocation.py b/tests/test_meta_expenseAllocation.py index 34d9dd8..b5578f1 100644 --- a/tests/test_meta_expenseAllocation.py +++ b/tests/test_meta_expenseAllocation.py @@ -109,3 +109,21 @@ def test_default_values(account, set_value): errors = checker.check(txn, txn.postings[-1]) assert not errors assert txn.postings[-1].meta['expenseAllocation'] == set_value + +@pytest.mark.parametrize('date,set_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, set_value): + txn = testutil.Transaction(date=date, postings=[ + ('Liabilites:CreditCard', -25), + ('Expenses:General', 25), + ]) + checker = meta_expense_allocation.MetaExpenseAllocation() + errors = checker.check(txn, txn.postings[-1]) + assert not errors + got_value = (txn.postings[-1].meta or {}).get('expenseAllocation') + assert bool(got_value) == bool(set_value) diff --git a/tests/testutil.py b/tests/testutil.py index 47368a3..c113e1b 100644 --- a/tests/testutil.py +++ b/tests/testutil.py @@ -21,8 +21,11 @@ import beancount.core.data as bc_data from decimal import Decimal +EXTREME_FUTURE_DATE = datetime.date(datetime.MAXYEAR, 12, 30) +FUTURE_DATE = datetime.date.today() + datetime.timedelta(days=365 * 99) FY_START_DATE = datetime.date(2020, 3, 1) FY_MID_DATE = datetime.date(2020, 9, 1) +PAST_DATE = datetime.date(2000, 1, 1) def parse_date(s, fmt='%Y-%m-%d'): return datetime.datetime.strptime(s, fmt).date()