From 07b3c6842283648e9596b465d68178e8d83a85ae Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Thu, 3 Oct 2019 16:12:49 -0400 Subject: [PATCH 1/3] Add min and max range values to date selector so a more accurate error message can be displayed when a date is out of the range --- atst/forms/task_order.py | 24 +++++++++++++-- js/components/__tests__/date_selector.test.js | 29 +++++++++++++++++++ js/components/date_selector.js | 19 ++++++++++++ js/test_templates/clin_fields.html | 16 ++++++++-- js/test_templates/pop_date_range.html | 16 ++++++++-- js/test_templates/to_form.html | 16 ++++++---- templates/components/pop_date_range.html | 16 ++++++++-- tests/forms/test_task_order.py | 4 +-- translations.yaml | 6 ++-- 9 files changed, 126 insertions(+), 20 deletions(-) diff --git a/atst/forms/task_order.py b/atst/forms/task_order.py index fe764f27..d0e9aae5 100644 --- a/atst/forms/task_order.py +++ b/atst/forms/task_order.py @@ -91,6 +91,8 @@ class CLINForm(FlaskForm): self.start_date.data and self.end_date.data and self.start_date.data > self.end_date.data + and self.start_date.data <= contract_end + and self.end_date.data >= contract_start ): self.start_date.errors.append( translate("forms.task_order.pop_errors.date_order") @@ -100,7 +102,7 @@ class CLINForm(FlaskForm): if self.start_date.data and self.start_date.data <= contract_start: self.start_date.errors.append( translate( - "forms.task_order.pop_errors.start", + "forms.task_order.pop_errors.start_pre_contract", {"date": contract_start.strftime("%b %d, %Y")}, ) ) @@ -109,12 +111,30 @@ class CLINForm(FlaskForm): if self.end_date.data and self.end_date.data >= contract_end: self.end_date.errors.append( translate( - "forms.task_order.pop_errors.end", + "forms.task_order.pop_errors.end_past_contract", {"date": contract_end.strftime("%b %d, %Y")}, ) ) valid = False + if self.start_date.data and self.start_date.data > contract_end: + self.start_date.errors.append( + translate( + "forms.task_order.pop_errors.start_past_contract", + {"date": contract_end.strftime("%b %d, %Y")}, + ) + ) + valid = False + + if self.end_date.data and self.end_date.data < contract_start: + self.end_date.errors.append( + translate( + "forms.task_order.pop_errors.end_pre_contract", + {"date": contract_start.strftime("%b %d, %Y")}, + ) + ) + valid = False + return valid diff --git a/js/components/__tests__/date_selector.test.js b/js/components/__tests__/date_selector.test.js index 348a4726..24d4aed5 100644 --- a/js/components/__tests__/date_selector.test.js +++ b/js/components/__tests__/date_selector.test.js @@ -250,4 +250,33 @@ describe('DateSelector', () => { expect(component.maxError).toEqual(false) }) }) + + describe('outsideRange', () => { + it('should return true if the date is before the minrange', () => { + component.minrange = '2020-01-01' + component.maxrange = '2025-01-01' + component.day = 1 + component.month = 1 + component.year = 2005 + expect(component.outsideRange).toEqual(true) + }) + + it('should return true if the date is after the maxrange', () => { + component.minrange = '2020-01-01' + component.maxrange = '2025-01-01' + component.day = 1 + component.month = 1 + component.year = 2030 + expect(component.outsideRange).toEqual(true) + }) + + it('should return false if the date is betwen minrange and maxrange', () => { + component.minrange = '2020-01-01' + component.maxrange = '2025-01-01' + component.day = 1 + component.month = 1 + component.year = 2022 + expect(component.outsideRange).toEqual(false) + }) + }) }) diff --git a/js/components/date_selector.js b/js/components/date_selector.js index 2717c033..a8257f10 100644 --- a/js/components/date_selector.js +++ b/js/components/date_selector.js @@ -19,6 +19,8 @@ export default { initialyear: { type: String }, mindate: { type: String }, maxdate: { type: String }, + minrange: { type: String }, + maxrange: { type: String }, nameTag: { type: String }, optional: { type: Boolean, @@ -179,6 +181,15 @@ export default { return false }, + outsideRange: function() { + if (!!this.maxrange && !!this.minrange && this.isDateComplete) { + return ( + this.dateParsed < this.minRangeParsed || + this.dateParsed > this.maxRangeParsed + ) + } + }, + maxDateParsed: function() { return new Date(this.maxdate) }, @@ -187,6 +198,14 @@ export default { return new Date(this.mindate) }, + maxRangeParsed: function() { + return new Date(this.maxrange) + }, + + minRangeParsed: function() { + return new Date(this.minrange) + }, + dateParsed: function() { return new Date(this.formattedDate) }, diff --git a/js/test_templates/clin_fields.html b/js/test_templates/clin_fields.html index 57fefe2c..abcd43f3 100644 --- a/js/test_templates/clin_fields.html +++ b/js/test_templates/clin_fields.html @@ -332,6 +332,8 @@ +
+ PoP start date must be before or on September 14, 2022. +
PoP start date must be on or after September 14, 2019.
-
+
PoP start date must be before end date.
@@ -431,6 +436,8 @@ -
+
+ PoP end date must be on or after September 14, 2019. +
+
PoP end date must be after start date.
- PoP end date must be on or after September 14, 2022. + PoP end date must be before or on September 14, 2022.
diff --git a/js/test_templates/pop_date_range.html b/js/test_templates/pop_date_range.html index 2d53ad9b..3b88eb63 100644 --- a/js/test_templates/pop_date_range.html +++ b/js/test_templates/pop_date_range.html @@ -19,6 +19,8 @@ +
+ PoP start date must be before or on September 14, 2022. +
PoP start date must be on or after September 14, 2019.
-
+
PoP start date must be before end date.
@@ -118,6 +123,8 @@ -
+
+ PoP end date must be on or after September 14, 2019. +
+
PoP end date must be after start date.
- PoP end date must be on or after September 14, 2022. + PoP end date must be before or on September 14, 2022.
diff --git a/js/test_templates/to_form.html b/js/test_templates/to_form.html index a22dc16f..930c4d1d 100644 --- a/js/test_templates/to_form.html +++ b/js/test_templates/to_form.html @@ -203,7 +203,7 @@
- +
@@ -212,10 +212,13 @@

For example: 07 04 1776

+
+ PoP start date must be before or on September 14, 2022. +
PoP start date must be on or after September 14, 2019.
-
+
PoP start date must be before end date.
@@ -251,7 +254,7 @@
- +
@@ -267,11 +270,14 @@

For example: 07 04 1776

-
+
+ PoP end date must be on or after September 14, 2019. +
+
PoP end date must be after start date.
- PoP end date must be on or after September 14, 2022. + PoP end date must be before or on September 14, 2022.
diff --git a/templates/components/pop_date_range.html b/templates/components/pop_date_range.html index 676c7c69..4f4901eb 100644 --- a/templates/components/pop_date_range.html +++ b/templates/components/pop_date_range.html @@ -24,6 +24,8 @@ +
+ PoP start date must be before or on {{ maxdate | formattedDate(formatter="%B %d, %Y") }}. +
PoP start date must be on or after {{ mindate | formattedDate(formatter="%B %d, %Y") }}.
-
+
PoP start date must be before end date.
@@ -118,6 +123,8 @@ -
+
+ PoP end date must be on or after {{ mindate | formattedDate(formatter="%B %d, %Y") }}. +
+
PoP end date must be after start date.
- PoP end date must be on or after {{ formatted_end_date }}. + PoP end date must be before or on {{ formatted_end_date }}.
diff --git a/tests/forms/test_task_order.py b/tests/forms/test_task_order.py index 85a7c6af..7b7d028f 100644 --- a/tests/forms/test_task_order.py +++ b/tests/forms/test_task_order.py @@ -50,13 +50,13 @@ def test_clin_form_pop_dates_within_contract_dates(): assert not clin_form.validate() assert ( translate( - "forms.task_order.pop_errors.start", + "forms.task_order.pop_errors.start_pre_contract", {"date": CONTRACT_START_DATE.strftime("%b %d, %Y")}, ) ) in clin_form.start_date.errors assert ( translate( - "forms.task_order.pop_errors.end", + "forms.task_order.pop_errors.end_past_contract", {"date": CONTRACT_END_DATE.strftime("%b %d, %Y")}, ) ) in clin_form.end_date.errors diff --git a/translations.yaml b/translations.yaml index 83cbe0ad..aa199313 100644 --- a/translations.yaml +++ b/translations.yaml @@ -210,8 +210,10 @@ forms: number_description: Task order number (13 digits) pop_errors: date_order: PoP start date must be before end date. - end: PoP end date must be before or on {date}. - start: PoP start date must be on or after {date}. + end_past_contract: PoP end date must be before or on {date}. + end_pre_contract: PoP end date must be after or on {date}. + start_past_contract: PoP start date must be before or on {date}. + start_pre_contract: PoP start date must be on or after {date}. 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 clin_funding_errors: From f4855c0ae3accf63f746bcb5d04c7003a6b8fd68 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Tue, 8 Oct 2019 10:30:04 -0400 Subject: [PATCH 2/3] Use validator on the field for checking that the pop dates are within the contract date range --- atst/forms/task_order.py | 60 ++++++++++------------------------ tests/forms/test_task_order.py | 15 ++++++--- translations.yaml | 1 + 3 files changed, 30 insertions(+), 46 deletions(-) diff --git a/atst/forms/task_order.py b/atst/forms/task_order.py index d0e9aae5..3ac5640b 100644 --- a/atst/forms/task_order.py +++ b/atst/forms/task_order.py @@ -38,6 +38,22 @@ def validate_funding(form, field): ) +def validate_date_in_range(form, field): + contract_start = app.config.get("CONTRACT_START_DATE") + contract_end = app.config.get("CONTRACT_END_DATE") + + if field.data and (field.data < contract_start or field.data > contract_end): + raise ValidationError( + translate( + "forms.task_order.pop_errors.range", + { + "start": contract_start.strftime("%b %d, %Y"), + "end": contract_end.strftime("%b %d, %Y"), + }, + ) + ) + + class CLINForm(FlaskForm): jedi_clin_type = SelectField( translate("task_orders.form.clin_type_label"), @@ -52,13 +68,13 @@ class CLINForm(FlaskForm): translate("task_orders.form.pop_start"), description=translate("task_orders.form.pop_example"), format="%m/%d/%Y", - validators=[Optional()], + validators=[validate_date_in_range], ) end_date = DateField( translate("task_orders.form.pop_end"), description=translate("task_orders.form.pop_example"), format="%m/%d/%Y", - validators=[Optional()], + validators=[validate_date_in_range], ) total_amount = DecimalField( label=translate("task_orders.form.total_funds_label"), @@ -84,57 +100,17 @@ class CLINForm(FlaskForm): def validate(self, *args, **kwargs): valid = super().validate(*args, **kwargs) - contract_start = app.config.get("CONTRACT_START_DATE") - contract_end = app.config.get("CONTRACT_END_DATE") if ( self.start_date.data and self.end_date.data and self.start_date.data > self.end_date.data - and self.start_date.data <= contract_end - and self.end_date.data >= contract_start ): self.start_date.errors.append( translate("forms.task_order.pop_errors.date_order") ) valid = False - if self.start_date.data and self.start_date.data <= contract_start: - self.start_date.errors.append( - translate( - "forms.task_order.pop_errors.start_pre_contract", - {"date": contract_start.strftime("%b %d, %Y")}, - ) - ) - valid = False - - if self.end_date.data and self.end_date.data >= contract_end: - self.end_date.errors.append( - translate( - "forms.task_order.pop_errors.end_past_contract", - {"date": contract_end.strftime("%b %d, %Y")}, - ) - ) - valid = False - - if self.start_date.data and self.start_date.data > contract_end: - self.start_date.errors.append( - translate( - "forms.task_order.pop_errors.start_past_contract", - {"date": contract_end.strftime("%b %d, %Y")}, - ) - ) - valid = False - - if self.end_date.data and self.end_date.data < contract_start: - self.end_date.errors.append( - translate( - "forms.task_order.pop_errors.end_pre_contract", - {"date": contract_start.strftime("%b %d, %Y")}, - ) - ) - valid = False - return valid diff --git a/tests/forms/test_task_order.py b/tests/forms/test_task_order.py index 7b7d028f..de95e555 100644 --- a/tests/forms/test_task_order.py +++ b/tests/forms/test_task_order.py @@ -47,17 +47,24 @@ def test_clin_form_pop_dates_within_contract_dates(): start_date=invalid_start, end_date=invalid_end ) clin_form = CLINForm(obj=invalid_clin) + assert not clin_form.validate() assert ( translate( - "forms.task_order.pop_errors.start_pre_contract", - {"date": CONTRACT_START_DATE.strftime("%b %d, %Y")}, + "forms.task_order.pop_errors.range", + { + "start": CONTRACT_START_DATE.strftime("%b %d, %Y"), + "end": CONTRACT_END_DATE.strftime("%b %d, %Y"), + }, ) ) in clin_form.start_date.errors assert ( translate( - "forms.task_order.pop_errors.end_past_contract", - {"date": CONTRACT_END_DATE.strftime("%b %d, %Y")}, + "forms.task_order.pop_errors.range", + { + "start": CONTRACT_START_DATE.strftime("%b %d, %Y"), + "end": CONTRACT_END_DATE.strftime("%b %d, %Y"), + }, ) ) in clin_form.end_date.errors diff --git a/translations.yaml b/translations.yaml index aa199313..8eb2c9c1 100644 --- a/translations.yaml +++ b/translations.yaml @@ -210,6 +210,7 @@ forms: number_description: Task order number (13 digits) pop_errors: date_order: PoP start date must be before end date. + range: Date must be between {start} and {end}. end_past_contract: PoP end date must be before or on {date}. end_pre_contract: PoP end date must be after or on {date}. start_past_contract: PoP start date must be before or on {date}. From 7f0a25ea1709d5fddcea4ce4f9c4fe1d55812600 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Tue, 8 Oct 2019 10:30:37 -0400 Subject: [PATCH 3/3] Use translations --- js/test_templates/pop_date_range.html | 55 ++++++++++++------------ templates/components/pop_date_range.html | 17 ++++---- 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/js/test_templates/pop_date_range.html b/js/test_templates/pop_date_range.html index 3b88eb63..1eabb4ea 100644 --- a/js/test_templates/pop_date_range.html +++ b/js/test_templates/pop_date_range.html @@ -2,15 +2,15 @@
@@ -21,12 +21,12 @@ :maxdate="maxStartProp" :minrange='initialMinStartDate' :maxrange='initialMaxEndDate' - + name-tag='start_date' initialmonth="" initialday="" initialyear="" - + :optional='true' v-on:date-change='handleDateChange' inline-template> @@ -42,6 +42,7 @@

+ {{ ""}} PoP start date must be before or on September 14, 2022.
@@ -99,17 +100,17 @@
- + - +
- + - +
@@ -125,12 +126,12 @@ :maxdate="initialMaxEndDate" :minrange='initialMinStartDate' :maxrange='initialMaxEndDate' - + name-tag='end_date' initialmonth="" initialday="" initialyear="" - + :optional='true' v-on:date-change='handleDateChange' inline-template> @@ -140,26 +141,26 @@
End Date
- - - + + + @@ -222,17 +223,17 @@
- + - +
- + - +
diff --git a/templates/components/pop_date_range.html b/templates/components/pop_date_range.html index 4f4901eb..0eea2271 100644 --- a/templates/components/pop_date_range.html +++ b/templates/components/pop_date_range.html @@ -2,6 +2,8 @@ {% from 'components/icon.html' import Icon %} {% macro PopDateRange(start_field=None, end_field=None, mindate=mindate, maxdate=maxdate, optional=True, index=None) %} + {% set formatted_end = maxdate | formattedDate(formatter="%B %d, %Y") %} + {% set formatted_start = mindate | formattedDate(formatter="%B %d, %Y") %}
- PoP start date must be before or on {{ maxdate | formattedDate(formatter="%B %d, %Y") }}. + {{ "forms.task_order.pop_errors.start_past_contract" | translate({"date": formatted_end}) }}
- PoP start date must be on or after {{ mindate | formattedDate(formatter="%B %d, %Y") }}. + {{ "forms.task_order.pop_errors.start_pre_contract" | translate({"date": formatted_start}) }}
- PoP start date must be before end date. + {{ "forms.task_order.pop_errors.date_order" | translate }}
@@ -142,21 +144,20 @@
{{ 'task_orders.form.pop_end' | translate }}
- {% set formatted_end_date = maxdate | formattedDate(formatter="%B %d, %Y") %} - {{ Alert(message="task_orders.form.pop_end_alert" | translate({'end_date': formatted_end_date })) }} + {{ Alert(message="task_orders.form.pop_end_alert" | translate({'end_date': formatted_end })) }}

{{ 'task_orders.form.pop_example' | translate }}

- PoP end date must be on or after {{ mindate | formattedDate(formatter="%B %d, %Y") }}. + {{ "forms.task_order.pop_errors.end_pre_contract" | translate({"date": formatted_start}) }}
- PoP end date must be after start date. + {{ "forms.task_order.pop_errors.date_order" | translate }}
- PoP end date must be before or on {{ formatted_end_date }}. + {{ "forms.task_order.pop_errors.end_past_contract" | translate({"date": formatted_end}) }}