Add properties to portfolio model

1. Funding duration

Returns a tuple of the earliest period of performance start date and
latest period of performance end date for all active task order in a  portfolio.

2. Days to funding expiration
Returns the numbei of days between today and the lastest
period performance end date of all active task orders

3. Active task orders
Returns a list of a portfolio's active task orders a
This commit is contained in:
graham-dds 2019-11-20 11:52:28 -05:00
parent 4f2a75b64f
commit 7a0dc4d264
2 changed files with 122 additions and 1 deletions

View File

@ -74,6 +74,49 @@ class Portfolio(
if clin.is_active
]
@property
def active_task_orders(self):
return [task_order for task_order in self.task_orders if task_order.is_active]
@property
def funding_duration(self):
"""
Return the earliest period of performance start date and latest period
of performance end date for all active task orders in a portfolio.
@return: (datetime.date or None, datetime.date or None)
"""
start_dates = (
task_order.start_date
for task_order in self.task_orders
if task_order.is_active
)
end_dates = (
task_order.end_date
for task_order in self.task_orders
if task_order.is_active
)
earliest_pop_start_date = min(start_dates, default=None)
latest_pop_end_date = max(end_dates, default=None)
return (earliest_pop_start_date, latest_pop_end_date)
@property
def days_to_funding_expiration(self):
"""
Returns the number of days between today and the lastest period performance
end date of all active Task Orders
"""
return max(
(
task_order.days_to_expiration
for task_order in self.task_orders
if task_order.is_active
),
default=None,
)
@property
def members(self):
return (

View File

@ -1,4 +1,12 @@
from tests.factories import ApplicationFactory, PortfolioFactory
from tests.factories import (
ApplicationFactory,
PortfolioFactory,
TaskOrderFactory,
CLINFactory,
random_future_date,
random_past_date,
)
import datetime
def test_portfolio_applications_excludes_deleted():
@ -7,3 +15,73 @@ def test_portfolio_applications_excludes_deleted():
ApplicationFactory.create(portfolio=portfolio, deleted=True)
assert len(portfolio.applications) == 1
assert portfolio.applications[0].id == app.id
def test_funding_duration(session):
# portfolio with active task orders
portfolio = PortfolioFactory()
funding_start_date = random_past_date()
funding_end_date = random_future_date(year_min=2)
TaskOrderFactory.create(
signed_at=random_past_date(),
portfolio=portfolio,
create_clins=[
{
"start_date": funding_start_date,
"end_date": random_future_date(year_max=1),
}
],
)
TaskOrderFactory.create(
portfolio=portfolio,
signed_at=random_past_date(),
create_clins=[
{"start_date": datetime.datetime.now(), "end_date": funding_end_date,}
],
)
assert portfolio.funding_duration == (funding_start_date, funding_end_date)
# empty portfolio
empty_portfolio = PortfolioFactory()
assert empty_portfolio.funding_duration == (None, None)
def test_days_remaining(session):
# portfolio with task orders
funding_end_date = random_future_date(year_min=2)
portfolio = PortfolioFactory()
TaskOrderFactory.create(
portfolio=portfolio,
signed_at=random_past_date(),
create_clins=[{"end_date": funding_end_date}],
)
assert (
portfolio.days_to_funding_expiration
== (funding_end_date - datetime.date.today()).days
)
# empty portfolio
empty_portfolio = PortfolioFactory()
assert empty_portfolio.days_to_funding_expiration == 0
def test_active_task_orders(session):
portfolio = PortfolioFactory()
TaskOrderFactory.create(
portfolio=portfolio,
signed_at=random_past_date(),
create_clins=[
{
"start_date": datetime.date(2019, 1, 1),
"end_date": datetime.date(2019, 10, 31),
}
],
)
TaskOrderFactory.create(
portfolio=portfolio, signed_at=random_past_date(), clins=[CLINFactory.create()]
)
assert len(portfolio.active_task_orders) == 1