diff --git a/atst/forms/task_order.py b/atst/forms/task_order.py index 99c1e35d..fca7bcfd 100644 --- a/atst/forms/task_order.py +++ b/atst/forms/task_order.py @@ -51,6 +51,16 @@ class CLINForm(FlaskForm): ) loas = FieldList(StringField()) + def validate(self, *args, **kwargs): + valid = super().validate(*args, **kwargs) + if self.start_date.data > self.end_date.data: + self.start_date.errors.append( + translate("forms.task_order.start_date_error") + ) + return False + else: + return valid + class TaskOrderForm(BaseForm): number = StringField(label=translate("forms.task_order.number_description")) diff --git a/templates/components/date_picker.html b/templates/components/date_picker.html index 6924eddc..c41db3d0 100644 --- a/templates/components/date_picker.html +++ b/templates/components/date_picker.html @@ -80,10 +80,10 @@ -

- {% if maxdate and mindate %}Date must be between {{mindate.strftime("%m/%d/%Y")}} and {{maxdate.strftime("%m/%d/%Y")}}{% endif %} - {% if maxdate and not mindate %}Date must be before or on {{maxdate.strftime("%m/%d/%Y")}}{% endif %} - {% if mindate and not maxdate %}Date must be after or on {{mindate.strftime("%m/%d/%Y")}}{% endif %} +

+ {% if field.errors %} + {{ field.errors[0] }} + {% endif %}

diff --git a/templates/task_orders/step_3.html b/templates/task_orders/step_3.html index f1c3d115..ddead4f6 100644 --- a/templates/task_orders/step_3.html +++ b/templates/task_orders/step_3.html @@ -138,14 +138,15 @@
{% if fields %} -
+
{{ DatePicker(fields.start_date, watch=True, optional=False) }}
-
+
{{ DatePicker(fields.end_date, watch=True, optional=False) }}
+ {% else %} -
+
@@ -209,7 +210,7 @@
-
+
diff --git a/tests/forms/test_task_order.py b/tests/forms/test_task_order.py index d814f4de..d9ba3080 100644 --- a/tests/forms/test_task_order.py +++ b/tests/forms/test_task_order.py @@ -1,5 +1,8 @@ +import datetime + from atst.forms.task_order import CLINForm from atst.models import JEDICLINType +from atst.utils.localization import translate import tests.factories as factories @@ -9,3 +12,21 @@ def test_clin_form_jedi_clin_type(): clin = factories.CLINFactory.create(jedi_clin_type=jedi_type) clin_form = CLINForm(obj=clin) assert clin_form.jedi_clin_type.data == jedi_type.value + + +def test_clin_form_start_date_before_end_date(): + invalid_start = datetime.date(2020, 12, 12) + invalid_end = datetime.date(2020, 1, 1) + invalid_clin = factories.CLINFactory.create( + start_date=invalid_start, end_date=invalid_end + ) + clin_form = CLINForm(obj=invalid_clin) + assert not clin_form.validate() + assert translate("forms.task_order.start_date_error") in clin_form.start_date.errors + valid_start = datetime.date(2020, 1, 1) + valid_end = datetime.date(2020, 12, 12) + valid_clin = factories.CLINFactory.create( + start_date=valid_start, end_date=valid_end + ) + valid_clin_form = CLINForm(obj=valid_clin) + assert valid_clin_form.validate() diff --git a/translations.yaml b/translations.yaml index b53b18cb..09557f5e 100644 --- a/translations.yaml +++ b/translations.yaml @@ -175,6 +175,7 @@ forms: number_description: Task order number (13 digits) scope_description: 'What do you plan to do on the cloud? Some examples might include migrating an existing application or creating a prototype. You don’t need to include a detailed plan of execution, but should list key requirements. This section will be reviewed by your contracting officer, but won’t be sent to the CCPO.

Not sure how to describe your scope? Read some examples to get some inspiration.

' scope_label: Cloud project scope + start_date_error: PoP start date must be before end date. start_date_label: Start of period of performance (PoP) team_experience: built_1: Built, migrated, or consulted on 1-2 applications