data: Add Account.is_open_on_date() method.

This commit is contained in:
Brett Smith 2020-07-17 09:58:18 -04:00
parent a0372d4b73
commit 4483d76999
2 changed files with 62 additions and 2 deletions

View file

@ -250,6 +250,22 @@ class Account(str):
def is_credit_card(self) -> bool:
return self.is_under('Liabilities:CreditCard') is not None
def is_open_on_date(self, date: datetime.date) -> Optional[bool]:
"""Return true if this account is open on the given date.
This method considers the dates on the account's open and close
directives. If there is no close directive, it just checks the date is
on or after the opening date. If neither exists, returns None.
"""
try:
meta = self.meta
except KeyError:
return None
close_date = meta.close_date
if close_date is None:
close_date = date + datetime.timedelta(days=1)
return meta.open_date <= date < close_date
def is_opening_equity(self) -> bool:
return self.is_under('Equity:Funds', 'Equity:OpeningBalance') is not None

View file

@ -14,17 +14,17 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import datetime
import pytest
from . import testutil
from datetime import date as Date
from beancount.core.data import Open, Close, Booking
from beancount.parser import options as bc_options
from conservancy_beancount import data
Date = datetime.date
clean_account_meta = pytest.fixture()(testutil.clean_account_meta)
@pytest.fixture
@ -160,6 +160,50 @@ def test_is_credit_card(acct_name, expected):
def test_is_opening_equity(acct_name, expected):
assert data.Account(acct_name).is_opening_equity() == expected
@pytest.mark.parametrize('date', [
testutil.PAST_DATE,
testutil.FY_START_DATE,
testutil.FY_MID_DATE,
testutil.FUTURE_DATE,
])
def test_is_open_on_date_without_opening(date):
account = data.Account('Assets:Cash')
assert account.is_open_on_date(date) is None
@pytest.mark.parametrize('days_diff', range(-2, 3))
def test_is_open_on_date_without_closing(clean_account_meta, days_diff):
open_date = testutil.FY_START_DATE
acct_name = 'Assets:Checking'
data.Account.load_opening(Open({}, open_date, acct_name, None, None))
account = data.Account(acct_name)
check_date = open_date + datetime.timedelta(days=days_diff)
assert account.is_open_on_date(check_date) == (days_diff >= 0)
@pytest.mark.parametrize('close_diff,check_diff', [
(30, -30),
(30, -1),
(30, 0),
(30, 1),
(30, 29),
(30, 30),
(30, 60),
(60, 30),
(60, 59),
(60, 60),
(60, 90),
(60, -60),
])
def test_is_open_on_date_with_closing(clean_account_meta, close_diff, check_diff):
open_date = testutil.FY_START_DATE
acct_name = 'Assets:Savings'
data.Account.load_opening(Open({}, open_date, acct_name, None, None))
close_date = open_date + datetime.timedelta(days=close_diff)
data.Account.load_closing(Close({}, close_date, acct_name))
account = data.Account(acct_name)
check_date = open_date + datetime.timedelta(days=check_diff)
expected = (0 <= check_diff < close_diff)
assert account.is_open_on_date(check_date) == expected
@pytest.mark.parametrize('acct_name', [
'Assets:Cash',
'Assets:Prepaid:Expenses',