From 633e1b6a375787f345c28bf5474d6fb6ec91e7cb Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Tue, 4 Jun 2019 10:37:27 -0400 Subject: [PATCH 01/11] Update TO Form to include CLINs and LOAs --- atst/forms/data.py | 7 ++++ atst/forms/task_order.py | 59 ++++++++++++--------------- atst/routes/task_orders/new.py | 2 +- tests/routes/task_orders/test_new.py | 61 +++++++++++++++++++++++++--- 4 files changed, 90 insertions(+), 39 deletions(-) diff --git a/atst/forms/data.py b/atst/forms/data.py index e0d4cf7f..4df9e0fc 100644 --- a/atst/forms/data.py +++ b/atst/forms/data.py @@ -221,3 +221,10 @@ ENV_ROLE_NO_ACCESS = "No Access" ENV_ROLES = [(role.value, role.value) for role in CSPRole] + [ (ENV_ROLE_NO_ACCESS, "No access") ] + +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")), +] diff --git a/atst/forms/task_order.py b/atst/forms/task_order.py index d5938bd1..88427041 100644 --- a/atst/forms/task_order.py +++ b/atst/forms/task_order.py @@ -1,13 +1,37 @@ -from wtforms.fields import BooleanField, DecimalField, FileField, StringField +from wtforms.fields import BooleanField, DecimalField, FieldList, FileField, FormField, StringField from wtforms.fields.html5 import DateField from wtforms.validators import Required, Optional from flask_wtf.file import FileAllowed +from .data import JEDI_CLIN_TYPES +from .fields import SelectField from .forms import BaseForm from atst.forms.validators import FileLength 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()]) + start_date = DateField( + translate("forms.task_order.start_date_label"), + format="%m/%d/%Y", + validators=[Required()], + ) + end_date = DateField( + translate("forms.task_order.end_date_label"), + format="%m/%d/%Y", + validators=[Required()], + ) + obligated_funds = DecimalField() + loas = FieldList(StringField()) + + +class UnclassifiedCLINForm(CLINForm): + # TODO: overwrite jedi_clin_type to only include the unclassified options + pass + + class TaskOrderForm(BaseForm): number = StringField( translate("forms.task_order.number_label"), @@ -22,38 +46,7 @@ class TaskOrderForm(BaseForm): ], render_kw={"accept": ".pdf,application/pdf"}, ) - - -class FundingForm(BaseForm): - start_date = DateField( - translate("forms.task_order.start_date_label"), format="%m/%d/%Y" - ) - end_date = DateField( - translate("forms.task_order.end_date_label"), format="%m/%d/%Y" - ) - clin_01 = DecimalField( - translate("forms.task_order.clin_01_label"), validators=[Optional()] - ) - clin_02 = DecimalField( - translate("forms.task_order.clin_02_label"), validators=[Optional()] - ) - clin_03 = DecimalField( - translate("forms.task_order.clin_03_label"), validators=[Optional()] - ) - clin_04 = DecimalField( - translate("forms.task_order.clin_04_label"), validators=[Optional()] - ) - - -class UnclassifiedFundingForm(FundingForm): - clin_02 = StringField( - translate("forms.task_order.unclassified_clin_02_label"), - filters=[BaseForm.remove_empty_string], - ) - clin_04 = StringField( - translate("forms.task_order.unclassified_clin_04_label"), - filters=[BaseForm.remove_empty_string], - ) + clins = FieldList(FormField(CLINForm)) class SignatureForm(BaseForm): diff --git a/atst/routes/task_orders/new.py b/atst/routes/task_orders/new.py index 9778320f..03f1f328 100644 --- a/atst/routes/task_orders/new.py +++ b/atst/routes/task_orders/new.py @@ -14,7 +14,7 @@ def render_task_orders_edit(portfolio_id, task_order_id=None, form=None): if task_order_id: task_order = TaskOrders.get(task_order_id) render_args["form"] = form or TaskOrderForm( - number=task_order.number, pdf=task_order.pdf + **task_order.to_dictionary() ) render_args["task_order_id"] = task_order_id else: diff --git a/tests/routes/task_orders/test_new.py b/tests/routes/task_orders/test_new.py index f4ee00d4..577c8899 100644 --- a/tests/routes/task_orders/test_new.py +++ b/tests/routes/task_orders/test_new.py @@ -33,24 +33,75 @@ def user(): return UserFactory.create() -def test_task_orders_new(client, user_session, portfolio): +def test_task_orders_edit(client, user_session, portfolio): user_session(portfolio.owner) response = client.get(url_for("task_orders.edit", portfolio_id=portfolio.id)) assert response.status_code == 200 -def test_task_orders_create(client, user_session, portfolio, pdf_upload, session): +def test_task_orders_update(client, user_session, portfolio): user_session(portfolio.owner) - data = {"number": "0123456789", "pdf": pdf_upload} + form_data = { + "number": "0123456789", + "pdf": pdf_upload, + "clins-0-jedi_clin_type": "jedi_clin_0001", + "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-1-start_date": "01/01/2020", + "clins-1-end_date": "01/01/2021", + "clins-1-obligated_funds": "5000", + "clins-1-loas-0-loa": "78979087", + } response = client.post( - url_for("task_orders.update", portfolio_id=portfolio.id), data=data + url_for("task_orders.update", portfolio_id=portfolio.id), data=form_data ) assert response.status_code == 302 task_order = session.query(TaskOrder).filter_by(number=data["number"]).one() assert task_order.pdf.filename == pdf_upload.filename -def test_task_orders_create_invalid_data(client, user_session, portfolio): +def test_task_orders_edit_existing_to(client, user_session, task_order): + user_session(task_order.creator) + response = client.get( + url_for( + "task_orders.edit", + portfolio_id=task_order.portfolio_id, + task_order_id=task_order.id, + ) + ) + assert response.status_code == 200 + + +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-start_date": "01/01/2020", + "clins-0-end_date": "01/01/2021", + "clins-0-obligated_funds": "5000", + "clins-0-loas-0-loa": "123123123123", + } + response = client.post( + url_for( + "task_orders.update", + portfolio_id=task_order.portfolio_id, + task_order_id=task_order.id, + ), + data=form_data, + ) + assert response.status_code == 302 + assert task_order.number == "0123456789" + + +def test_task_orders_update_invalid_data(client, user_session, portfolio): user_session(portfolio.owner) num_task_orders = len(portfolio.task_orders) response = client.post( From 36200e01ad3f242a9d86b110f8b3a2476bf6fd73 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Tue, 4 Jun 2019 11:42:14 -0400 Subject: [PATCH 02/11] Create CLINs when creating a TO --- atst/domain/task_orders.py | 43 +++++++++---- atst/forms/data.py | 8 +-- atst/forms/task_order.py | 4 +- atst/models/clin.py | 8 +-- atst/models/task_order.py | 2 +- tests/domain/test_task_orders.py | 90 ++++++++++++++++++++++++++++ tests/factories.py | 15 +++++ tests/routes/task_orders/test_new.py | 24 ++++---- 8 files changed, 161 insertions(+), 33 deletions(-) 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( From cca101b50c71f0b61c5436809b3925033001096c Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 5 Jun 2019 19:11:33 -0400 Subject: [PATCH 03/11] Add CLINs to Task Order --- js/components/clin_fields.js | 92 +++++++++++++++++++++++++++++++++ js/components/forms/to_form.js | 40 ++++++++++++++ js/index.js | 4 ++ templates/task_orders/edit.html | 34 ++++++++++-- 4 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 js/components/clin_fields.js create mode 100644 js/components/forms/to_form.js diff --git a/js/components/clin_fields.js b/js/components/clin_fields.js new file mode 100644 index 00000000..df3d3b83 --- /dev/null +++ b/js/components/clin_fields.js @@ -0,0 +1,92 @@ +import DateSelector from './date_selector' +import optionsinput from './options_input' +import textinput from './text_input' + +export default { + name: 'clin-fields', + + components: { + DateSelector, + optionsinput, + textinput, + }, + + props: { + clinIndex: String, + }, + // get clin index from props and pass into template + template: ` +
+ + +
+ + + +
+
+ +
Start Date +
+
+
+ +
+ + +
+
+ + +
+
+ + +
+ +
+

+

+
+
+ +
End Date +
+
+
+ +
+ + +
+
+ + +
+
+ + +
+ +
+

+

+
+
+ + + +
+
`, +} diff --git a/js/components/forms/to_form.js b/js/components/forms/to_form.js new file mode 100644 index 00000000..5d19d982 --- /dev/null +++ b/js/components/forms/to_form.js @@ -0,0 +1,40 @@ +import ClinFields from '../clin_fields' +import DateSelector from '../date_selector' +import FormMixin from '../../mixins/form' +import optionsinput from '../options_input' +import textinput from '../text_input' + +export default { + name: 'to-form', + + mixins: [FormMixin], + + components: { + ClinFields, + DateSelector, + optionsinput, + textinput, + }, + + props: { + initialClinCount: String, + }, + + data: function() { + const clins = this.initialClinCount == 0 ? [''] : [] + + return { + clins, + clinCount: this.initalClinCount - 1, + } + // pass initialCLINIndex in props and add one each time a clin is added... + // this way we can keep track of the clin id for the html name/id/etc + }, + + methods: { + addClin: function(event) { + this.clins.push('') + this.clinCount = this.clinCount + 1 + }, + }, +} diff --git a/js/index.js b/js/index.js index 9446814f..2f167883 100644 --- a/js/index.js +++ b/js/index.js @@ -41,6 +41,8 @@ import DeleteConfirmation from './components/delete_confirmation' import NewEnvironment from './components/forms/new_environment' import EnvironmentRole from './components/environment_role' import SemiCollapsibleText from './components/semi_collapsible_text' +import ToForm from './components/forms/to_form' +import ClinFields from './components/clin_fields' Vue.config.productionTip = false @@ -83,6 +85,8 @@ const app = new Vue({ NewEnvironment, EnvironmentRole, SemiCollapsibleText, + ToForm, + ClinFields, }, mounted: function() { diff --git a/templates/task_orders/edit.html b/templates/task_orders/edit.html index e8a5b6a6..169a4263 100644 --- a/templates/task_orders/edit.html +++ b/templates/task_orders/edit.html @@ -1,19 +1,31 @@ {% extends "portfolios/base.html" %} +{% from 'components/date_picker.html' import DatePicker %} {% from 'components/save_button.html' import SaveButton %} +{% from 'components/options_input.html' import OptionsInput %} {% from 'components/text_input.html' import TextInput %} {% from 'components/upload_input.html' import UploadInput %} +{% macro CLINFields(fields) %} +
+ {{ OptionsInput(fields.jedi_clin_type) }} + {{ TextInput(fields.number) }} + {{ DatePicker(fields.start_date) }} + {{ DatePicker(fields.end_date) }} + {{ TextInput(fields.obligated_amount) }} +
+{% endmacro %} + {% block portfolio_content %}
{% include "fragments/flash.html" %} - + {% if task_order_id %} {% set action = url_for("task_orders.update", portfolio_id=portfolio.id, task_order_id=task_order_id) %} {% else %} {% set action = url_for("task_orders.update", portfolio_id=portfolio.id) %} {% endif %} -
+ {{ form.csrf_token }} Add Funding @@ -29,8 +41,24 @@


{{ TextInput(form.number, validation='taskOrderNumber') }} + {% for clin in form.clins %} + {{ CLINFields(clin) }} + {% endfor %} +
+ + + + + + + +
+ + {{ UploadInput(form.pdf) }}
-
+
{% endblock %} From e017cd12af2a01d6377564ee0f965eac9d578ddc Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Fri, 7 Jun 2019 09:25:25 -0400 Subject: [PATCH 04/11] Vue for adding multiple CLINs --- atst/models/clin.py | 7 ++ atst/models/task_order.py | 3 + js/components/clin_fields.js | 83 ++---------------- js/components/forms/to_form.js | 7 +- templates/task_orders/edit.html | 149 ++++++++++++++++++++++++-------- 5 files changed, 133 insertions(+), 116 deletions(-) diff --git a/atst/models/clin.py b/atst/models/clin.py index 081ab764..dd4bdd76 100644 --- a/atst/models/clin.py +++ b/atst/models/clin.py @@ -27,3 +27,10 @@ class CLIN(Base, mixins.TimestampsMixin): end_date = Column(Date, nullable=False) obligated_amount = Column(Numeric(scale=2), nullable=False) jedi_clin_type = Column(SQLAEnum(JEDICLINType, native_enum=False), nullable=False) + + def to_dictionary(self): + return { + c.name: getattr(self, c.name) + for c in self.__table__.columns + if c.name not in ["id"] + } diff --git a/atst/models/task_order.py b/atst/models/task_order.py index 93131078..9f37854a 100644 --- a/atst/models/task_order.py +++ b/atst/models/task_order.py @@ -129,6 +129,9 @@ class TaskOrder(Base, mixins.TimestampsMixin): def to_dictionary(self): return { "portfolio_name": self.portfolio_name, + "clins": [ + clin.to_dictionary() for clin in self.clins + ], **{ c.name: getattr(self, c.name) for c in self.__table__.columns diff --git a/js/components/clin_fields.js b/js/components/clin_fields.js index df3d3b83..808c764b 100644 --- a/js/components/clin_fields.js +++ b/js/components/clin_fields.js @@ -6,87 +6,14 @@ export default { name: 'clin-fields', components: { - DateSelector, - optionsinput, textinput, }, props: { - clinIndex: String, + initialClinIndex: Number, + }, + + data: function() { + return {clinIndex: this.initialClinIndex} }, - // get clin index from props and pass into template - template: ` -
- - -
- - - -
-
- -
Start Date -
-
-
- -
- - -
-
- - -
-
- - -
- -
-

-

-
-
- -
End Date -
-
-
- -
- - -
-
- - -
-
- - -
- -
-

-

-
-
- - - -
-
`, } diff --git a/js/components/forms/to_form.js b/js/components/forms/to_form.js index 5d19d982..49913beb 100644 --- a/js/components/forms/to_form.js +++ b/js/components/forms/to_form.js @@ -17,15 +17,16 @@ export default { }, props: { - initialClinCount: String, + initialClinCount: Number, }, data: function() { const clins = this.initialClinCount == 0 ? [''] : [] + const clinIndex = this.initialClinCount == 0 ? 0 : this.initialClinCount - 1 return { clins, - clinCount: this.initalClinCount - 1, + clinIndex, } // pass initialCLINIndex in props and add one each time a clin is added... // this way we can keep track of the clin id for the html name/id/etc @@ -34,7 +35,7 @@ export default { methods: { addClin: function(event) { this.clins.push('') - this.clinCount = this.clinCount + 1 + this.clinIndex = this.clinIndex + 1 }, }, } diff --git a/templates/task_orders/edit.html b/templates/task_orders/edit.html index 169a4263..eee3d470 100644 --- a/templates/task_orders/edit.html +++ b/templates/task_orders/edit.html @@ -12,47 +12,126 @@ {{ TextInput(fields.number) }} {{ DatePicker(fields.start_date) }} {{ DatePicker(fields.end_date) }} - {{ TextInput(fields.obligated_amount) }} + {{ TextInput(fields.obligated_amount, validation='dollars') }} {% endmacro %} {% block portfolio_content %}
{% include "fragments/flash.html" %} - - {% if task_order_id %} - {% set action = url_for("task_orders.update", portfolio_id=portfolio.id, task_order_id=task_order_id) %} - {% else %} - {% set action = url_for("task_orders.update", portfolio_id=portfolio.id) %} - {% endif %} -
- {{ form.csrf_token }} - - Add Funding - - - {{ "common.cancel" | translate }} - - {{ SaveButton(text=('common.save' | translate), element='input', form='new-task-order') }} -

- {{ "task_orders.new.form_help_text" | translate }} -

-
- {{ TextInput(form.number, validation='taskOrderNumber') }} - {% for clin in form.clins %} - {{ CLINFields(clin) }} - {% endfor %} -
- - - - - - - -
+ + {% if task_order_id %} + {% set action = url_for("task_orders.update", portfolio_id=portfolio.id, task_order_id=task_order_id) %} + {% else %} + {% set action = url_for("task_orders.update", portfolio_id=portfolio.id) %} + {% endif %} + + {{ form.csrf_token }} + + Add Funding + + + {{ "common.cancel" | translate }} + + + {{ "task_orders.new.form_help_text" | translate }} +
+ {{ TextInput(form.number, validation='taskOrderNumber') }} + {% for clin in form.clins %} + {{ CLINFields(clin) }} + {% endfor %} +
+
+ +
+
+
+ +
+
+
+ +
+
+
+ + + +
+
+ +
Start Date +
+
+
+ +
+ + +
+
+ + +
+
+ + +
+ +
+

+

+
+
+ +
End Date +
+
+
+ +
+ + +
+
+ + +
+
+ + +
+ +
+

+

+
+
+ + + +
+
+
+
From f85af06297df7f90c46c284833f6a9f009989005 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Mon, 10 Jun 2019 14:34:10 -0400 Subject: [PATCH 11/11] Use number instead of array to add new CLIN fields --- js/components/forms/to_form.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/components/forms/to_form.js b/js/components/forms/to_form.js index 0f4f6f45..5255fbb9 100644 --- a/js/components/forms/to_form.js +++ b/js/components/forms/to_form.js @@ -23,7 +23,7 @@ export default { }, data: function() { - const clins = this.initialClinCount == 0 ? [''] : [] + const clins = this.initialClinCount == 0 ? 1 : 0 const clinIndex = this.initialClinCount == 0 ? 0 : this.initialClinCount - 1 return { @@ -34,7 +34,7 @@ export default { methods: { addClin: function(event) { - this.clins.push('') + this.clins = this.clins + 1 this.clinIndex = this.clinIndex + 1 }, },