diff --git a/atst/domain/task_orders.py b/atst/domain/task_orders.py index 0a2caeda..af5d014b 100644 --- a/atst/domain/task_orders.py +++ b/atst/domain/task_orders.py @@ -1,6 +1,7 @@ from flask import current_app as app from atst.database import db +from atst.models.clin import CLIN from atst.models.task_order import TaskOrder from . import BaseDomainClass @@ -18,27 +19,49 @@ class TaskOrders(BaseDomainClass): UNCLASSIFIED_FUNDING = [] @classmethod - def create(cls, creator, portfolio_id, **kwargs): - task_order = TaskOrder(portfolio_id=portfolio_id, creator=creator) - for key, value in kwargs.items(): - setattr(task_order, key, value) - + def create(cls, creator, portfolio_id, number, clins): + task_order = TaskOrder( + portfolio_id=portfolio_id, creator=creator, number=number + ) db.session.add(task_order) db.session.commit() + TaskOrders.create_clins(task_order.id, clins) + return task_order @classmethod - def update(cls, task_order_id, **kwargs): + def update(cls, task_order_id, number, clins): task_order = TaskOrders.get(task_order_id) - for key, value in kwargs.items(): - setattr(task_order, key, value) - db.session.add(task_order) - db.session.commit() + for clin in task_order.clins: + db.session.delete(clin) + db.session.commit() + + if number != task_order.number: + task_order.number = number + db.session.add(task_order) + db.session.commit() + + TaskOrders.create_clins(task_order_id, clins) return task_order + @classmethod + def create_clins(cls, task_order_id, clin_list): + for clin_data in clin_list: + clin = CLIN( + task_order_id=task_order_id, + number=clin_data["number"], + loas=clin_data["loas"], + start_date=clin_data["start_date"], + end_date=clin_data["end_date"], + obligated_amount=clin_data["obligated_amount"], + jedi_clin_type=clin_data["jedi_clin_type"], + ) + db.session.add(clin) + db.session.commit() + @classmethod def section_completion_status(cls, task_order, section): if section in TaskOrders.mission_owner_sections(): diff --git a/atst/forms/data.py b/atst/forms/data.py index 4df9e0fc..b2b33e9a 100644 --- a/atst/forms/data.py +++ b/atst/forms/data.py @@ -223,8 +223,8 @@ ENV_ROLES = [(role.value, role.value) for role in CSPRole] + [ ] JEDI_CLIN_TYPES = [ - ("jedi_clin_0001", translate("forms.task_order.clin_01_label")), - ("jedi_clin_0002", translate("forms.task_order.clin_02_label")), - ("jedi_clin_0003", translate("forms.task_order.clin_03_label")), - ("jedi_clin_0004", translate("forms.task_order.clin_04_label")), + ("JEDI_CLIN_1", translate("forms.task_order.clin_01_label")), + ("JEDI_CLIN_2", translate("forms.task_order.clin_02_label")), + ("JEDI_CLIN_3", translate("forms.task_order.clin_03_label")), + ("JEDI_CLIN_4", translate("forms.task_order.clin_04_label")), ] diff --git a/atst/forms/task_order.py b/atst/forms/task_order.py index 88427041..4e3aaaf0 100644 --- a/atst/forms/task_order.py +++ b/atst/forms/task_order.py @@ -12,7 +12,7 @@ from atst.utils.localization import translate class CLINForm(FlaskForm): jedi_clin_type = SelectField("Jedi CLIN type", choices=JEDI_CLIN_TYPES) - clin_number = StringField(validators=[Required()]) + number = StringField(validators=[Required()]) start_date = DateField( translate("forms.task_order.start_date_label"), format="%m/%d/%Y", @@ -23,7 +23,7 @@ class CLINForm(FlaskForm): format="%m/%d/%Y", validators=[Required()], ) - obligated_funds = DecimalField() + obligated_amount = DecimalField() loas = FieldList(StringField()) diff --git a/atst/models/clin.py b/atst/models/clin.py index 0570ca02..081ab764 100644 --- a/atst/models/clin.py +++ b/atst/models/clin.py @@ -7,10 +7,10 @@ from atst.models import Base, mixins, types class JEDICLINType(Enum): - JEDI_CLIN_1 = "jedi clin 0001" - JEDI_CLIN_2 = "jedi clin 0002" - JEDI_CLIN_3 = "jedi clin 0003" - JEDI_CLIN_4 = "jedi clin 0004" + JEDI_CLIN_1 = "JEDI_CLIN_1" + JEDI_CLIN_2 = "JEDI_CLIN_2" + JEDI_CLIN_3 = "JEDI_CLIN_3" + JEDI_CLIN_4 = "JEDI_CLIN_4" class CLIN(Base, mixins.TimestampsMixin): diff --git a/atst/models/task_order.py b/atst/models/task_order.py index 049b7d85..93131078 100644 --- a/atst/models/task_order.py +++ b/atst/models/task_order.py @@ -34,7 +34,7 @@ class TaskOrder(Base, mixins.TimestampsMixin): signer_dod_id = Column(String) signed_at = Column(DateTime) - clins = relationship("CLIN") + clins = relationship("CLIN", back_populates="task_order") @hybrid_property def pdf(self): diff --git a/tests/domain/test_task_orders.py b/tests/domain/test_task_orders.py index a3ed8abb..b34bbd24 100644 --- a/tests/domain/test_task_orders.py +++ b/tests/domain/test_task_orders.py @@ -1,4 +1,6 @@ import pytest +from datetime import date +from decimal import Decimal from atst.domain.task_orders import TaskOrders, TaskOrderError from atst.domain.exceptions import UnauthorizedError @@ -51,3 +53,91 @@ def test_all_sections_complete(): assert not TaskOrders.all_sections_complete(task_order) task_order.scope = "str12345" assert TaskOrders.all_sections_complete(task_order) + + +def test_create_adds_clins(): + portfolio = PortfolioFactory.create() + clins = [ + { + "jedi_clin_type": "JEDI_CLIN_1", + "number": "12312", + "start_date": date(2020, 1, 1), + "end_date": date(2021, 1, 1), + "obligated_amount": Decimal("5000"), + "loas": ["123123123123", "345345234"], + }, + { + "jedi_clin_type": "JEDI_CLIN_1", + "number": "12312", + "start_date": date(2020, 1, 1), + "end_date": date(2021, 1, 1), + "obligated_amount": Decimal("5000"), + "loas": ["78979087"], + }, + ] + task_order = TaskOrders.create( + creator=portfolio.owner, + portfolio_id=portfolio.id, + number="0123456789", + clins=clins, + ) + assert len(task_order.clins) == 2 + + +def test_update_adds_clins(): + task_order = TaskOrderFactory.create(number="1231231234") + to_number = task_order.number + clins = [ + { + "jedi_clin_type": "JEDI_CLIN_1", + "number": "12312", + "start_date": date(2020, 1, 1), + "end_date": date(2021, 1, 1), + "obligated_amount": Decimal("5000"), + "loas": ["123123123123", "345345234"], + }, + { + "jedi_clin_type": "JEDI_CLIN_1", + "number": "12312", + "start_date": date(2020, 1, 1), + "end_date": date(2021, 1, 1), + "obligated_amount": Decimal("5000"), + "loas": ["78979087"], + }, + ] + task_order = TaskOrders.create( + creator=task_order.creator, + portfolio_id=task_order.portfolio_id, + number="0000000000", + clins=clins, + ) + assert task_order.number != to_number + assert len(task_order.clins) == 2 + + +def test_update_does_not_duplicate_clins(): + task_order = TaskOrderFactory.create(number="3453453456", clins=["123", "456"]) + clins = [ + { + "jedi_clin_type": "JEDI_CLIN_1", + "number": "123", + "start_date": date(2020, 1, 1), + "end_date": date(2021, 1, 1), + "obligated_amount": Decimal("5000"), + "loas": ["123123123123", "345345234"], + }, + { + "jedi_clin_type": "JEDI_CLIN_1", + "number": "111", + "start_date": date(2020, 1, 1), + "end_date": date(2021, 1, 1), + "obligated_amount": Decimal("5000"), + "loas": ["78979087"], + }, + ] + task_order = TaskOrders.update( + task_order_id=task_order.id, number="0000000000", clins=clins + ) + assert len(task_order.clins) == 2 + for clin in task_order.clins: + assert clin.number != "456" diff --git a/tests/factories.py b/tests/factories.py index e91ec26b..05b8606f 100644 --- a/tests/factories.py +++ b/tests/factories.py @@ -41,6 +41,10 @@ def random_future_date(year_min=1, year_max=5): return _random_date(year_min, year_max, operator.add) +def random_loa_numbers(): + return ["".join(random.choices(string.digits, k=43))] + + def _random_date(year_min, year_max, operation): if year_min == year_max: inc = year_min @@ -267,6 +271,17 @@ class TaskOrderFactory(Base): portfolio = factory.SubFactory(PortfolioFactory) number = factory.LazyFunction(random_task_order_number) + creator = factory.SubFactory(UserFactory) + + @classmethod + def _create(cls, model_class, *args, **kwargs): + with_clins = kwargs.pop("clins", []) + task_order = super()._create(model_class, *args, **kwargs) + + for clin in with_clins: + CLINFactory.create(task_order=task_order, number=clin) + + return task_order class CLINFactory(Base): diff --git a/tests/routes/task_orders/test_new.py b/tests/routes/task_orders/test_new.py index 577c8899..110c8851 100644 --- a/tests/routes/task_orders/test_new.py +++ b/tests/routes/task_orders/test_new.py @@ -44,19 +44,19 @@ def test_task_orders_update(client, user_session, portfolio): form_data = { "number": "0123456789", "pdf": pdf_upload, - "clins-0-jedi_clin_type": "jedi_clin_0001", + "clins-0-jedi_clin_type": "JEDI_CLIN_1", "clins-0-clin_number": "12312", "clins-0-start_date": "01/01/2020", "clins-0-end_date": "01/01/2021", - "clins-0-obligated_funds": "5000", - "clins-0-loas-0-loa": "123123123123", - "clins-0-loas-1-loa": "345345234", - "clins-1-jedi_clin_type": "jedi_clin_0001", - "clins-1-clin_number": "12312", + "clins-0-obligated_amount": "5000", + "clins-0-loas-0": "123123123123", + "clins-0-loas-1": "345345234", + "clins-1-jedi_clin_type": "JEDI_CLIN_1", + "clins-1-number": "12312", "clins-1-start_date": "01/01/2020", "clins-1-end_date": "01/01/2021", - "clins-1-obligated_funds": "5000", - "clins-1-loas-0-loa": "78979087", + "clins-1-obligated_amount": "5000", + "clins-1-loas-0": "78979087", } response = client.post( url_for("task_orders.update", portfolio_id=portfolio.id), data=form_data @@ -82,12 +82,12 @@ def test_task_orders_update_existing_to(client, user_session, task_order): user_session(task_order.creator) form_data = { "number": "0123456789", - "clins-0-jedi_clin_type": "jedi_clin_0001", - "clins-0-clin_number": "12312", + "clins-0-jedi_clin_type": "JEDI_CLIN_1", + "clins-0-number": "12312", "clins-0-start_date": "01/01/2020", "clins-0-end_date": "01/01/2021", - "clins-0-obligated_funds": "5000", - "clins-0-loas-0-loa": "123123123123", + "clins-0-obligated_amount": "5000", + "clins-0-loas-0": "123123123123", } response = client.post( url_for(