data: Add Account.is_open_on_date() method.
This commit is contained in:
parent
a0372d4b73
commit
4483d76999
2 changed files with 62 additions and 2 deletions
|
@ -250,6 +250,22 @@ class Account(str):
|
||||||
def is_credit_card(self) -> bool:
|
def is_credit_card(self) -> bool:
|
||||||
return self.is_under('Liabilities:CreditCard') is not None
|
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:
|
def is_opening_equity(self) -> bool:
|
||||||
return self.is_under('Equity:Funds', 'Equity:OpeningBalance') is not None
|
return self.is_under('Equity:Funds', 'Equity:OpeningBalance') is not None
|
||||||
|
|
||||||
|
|
|
@ -14,17 +14,17 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import datetime
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from . import testutil
|
from . import testutil
|
||||||
|
|
||||||
from datetime import date as Date
|
|
||||||
|
|
||||||
from beancount.core.data import Open, Close, Booking
|
from beancount.core.data import Open, Close, Booking
|
||||||
from beancount.parser import options as bc_options
|
from beancount.parser import options as bc_options
|
||||||
|
|
||||||
from conservancy_beancount import data
|
from conservancy_beancount import data
|
||||||
|
|
||||||
|
Date = datetime.date
|
||||||
clean_account_meta = pytest.fixture()(testutil.clean_account_meta)
|
clean_account_meta = pytest.fixture()(testutil.clean_account_meta)
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -160,6 +160,50 @@ def test_is_credit_card(acct_name, expected):
|
||||||
def test_is_opening_equity(acct_name, expected):
|
def test_is_opening_equity(acct_name, expected):
|
||||||
assert data.Account(acct_name).is_opening_equity() == 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', [
|
@pytest.mark.parametrize('acct_name', [
|
||||||
'Assets:Cash',
|
'Assets:Cash',
|
||||||
'Assets:Prepaid:Expenses',
|
'Assets:Prepaid:Expenses',
|
||||||
|
|
Loading…
Reference in a new issue