Merge branch 'main' of https://github.com/cisagov/manage.get.gov into rh/2273-ds-record-change

This commit is contained in:
Rebecca Hsieh 2024-06-13 06:53:03 -07:00
commit db24029a83
No known key found for this signature in database
14 changed files with 336 additions and 84 deletions

View file

@ -1500,6 +1500,8 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
"authorizing_official", "authorizing_official",
"other_contacts", "other_contacts",
"no_other_contacts_rationale", "no_other_contacts_rationale",
"cisa_representative_first_name",
"cisa_representative_last_name",
"cisa_representative_email", "cisa_representative_email",
] ]
}, },
@ -1575,6 +1577,8 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
"no_other_contacts_rationale", "no_other_contacts_rationale",
"anything_else", "anything_else",
"is_policy_acknowledged", "is_policy_acknowledged",
"cisa_representative_first_name",
"cisa_representative_last_name",
"cisa_representative_email", "cisa_representative_email",
] ]
autocomplete_fields = [ autocomplete_fields = [

View file

@ -648,20 +648,27 @@ class NoOtherContactsForm(BaseDeletableRegistrarForm):
class CisaRepresentativeForm(BaseDeletableRegistrarForm): class CisaRepresentativeForm(BaseDeletableRegistrarForm):
cisa_representative_first_name = forms.CharField(
label="First name / given name",
error_messages={"required": "Enter the first name / given name of the CISA regional representative."},
)
cisa_representative_last_name = forms.CharField(
label="Last name / family name",
error_messages={"required": "Enter the last name / family name of the CISA regional representative."},
)
cisa_representative_email = forms.EmailField( cisa_representative_email = forms.EmailField(
required=True, label="Your representatives email (optional)",
max_length=None, max_length=None,
label="Your representatives email", required=False,
error_messages={
"invalid": ("Enter your representatives email address in the required format, like name@example.com."),
},
validators=[ validators=[
MaxLengthValidator( MaxLengthValidator(
320, 320,
message="Response must be less than 320 characters.", message="Response must be less than 320 characters.",
) )
], ],
error_messages={
"invalid": ("Enter your email address in the required format, like name@example.com."),
"required": ("Enter the email address of your CISA regional representative."),
},
) )

View file

@ -0,0 +1,69 @@
# Generated by Django 4.2.10 on 2024-06-12 20:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("registrar", "0100_domainrequest_action_needed_reason"),
]
operations = [
migrations.AddField(
model_name="domaininformation",
name="cisa_representative_first_name",
field=models.CharField(
blank=True, db_index=True, null=True, verbose_name="CISA regional representative first name"
),
),
migrations.AddField(
model_name="domaininformation",
name="cisa_representative_last_name",
field=models.CharField(
blank=True, db_index=True, null=True, verbose_name="CISA regional representative last name"
),
),
migrations.AddField(
model_name="domaininformation",
name="has_anything_else_text",
field=models.BooleanField(
blank=True, help_text="Determines if the user has a anything_else or not", null=True
),
),
migrations.AddField(
model_name="domaininformation",
name="has_cisa_representative",
field=models.BooleanField(
blank=True, help_text="Determines if the user has a representative email or not", null=True
),
),
migrations.AddField(
model_name="domainrequest",
name="cisa_representative_first_name",
field=models.CharField(
blank=True, db_index=True, null=True, verbose_name="CISA regional representative first name"
),
),
migrations.AddField(
model_name="domainrequest",
name="cisa_representative_last_name",
field=models.CharField(
blank=True, db_index=True, null=True, verbose_name="CISA regional representative last name"
),
),
migrations.AlterField(
model_name="domaininformation",
name="cisa_representative_email",
field=models.EmailField(
blank=True, max_length=320, null=True, verbose_name="CISA regional representative email"
),
),
migrations.AlterField(
model_name="domainrequest",
name="cisa_representative_email",
field=models.EmailField(
blank=True, max_length=320, null=True, verbose_name="CISA regional representative email"
),
),
]

View file

@ -214,13 +214,45 @@ class DomainInformation(TimeStampedModel):
verbose_name="Additional details", verbose_name="Additional details",
) )
# This is a drop-in replacement for a has_anything_else_text() function.
# In order to track if the user has clicked the yes/no field (while keeping a none default), we need
# a tertiary state. We should not display this in /admin.
has_anything_else_text = models.BooleanField(
null=True,
blank=True,
help_text="Determines if the user has a anything_else or not",
)
cisa_representative_email = models.EmailField( cisa_representative_email = models.EmailField(
null=True, null=True,
blank=True, blank=True,
verbose_name="CISA regional representative", verbose_name="CISA regional representative email",
max_length=320, max_length=320,
) )
cisa_representative_first_name = models.CharField(
null=True,
blank=True,
verbose_name="CISA regional representative first name",
db_index=True,
)
cisa_representative_last_name = models.CharField(
null=True,
blank=True,
verbose_name="CISA regional representative last name",
db_index=True,
)
# This is a drop-in replacement for an has_cisa_representative() function.
# In order to track if the user has clicked the yes/no field (while keeping a none default), we need
# a tertiary state. We should not display this in /admin.
has_cisa_representative = models.BooleanField(
null=True,
blank=True,
help_text="Determines if the user has a representative email or not",
)
is_policy_acknowledged = models.BooleanField( is_policy_acknowledged = models.BooleanField(
null=True, null=True,
blank=True, blank=True,
@ -241,6 +273,30 @@ class DomainInformation(TimeStampedModel):
except Exception: except Exception:
return "" return ""
def sync_yes_no_form_fields(self):
"""Some yes/no forms use a db field to track whether it was checked or not.
We handle that here for def save().
"""
# This ensures that if we have prefilled data, the form is prepopulated
if self.cisa_representative_first_name is not None or self.cisa_representative_last_name is not None:
self.has_cisa_representative = (
self.cisa_representative_first_name != "" and self.cisa_representative_last_name != ""
)
# This check is required to ensure that the form doesn't start out checked
if self.has_cisa_representative is not None:
self.has_cisa_representative = (
self.cisa_representative_first_name != "" and self.cisa_representative_first_name is not None
) and (self.cisa_representative_last_name != "" and self.cisa_representative_last_name is not None)
# This ensures that if we have prefilled data, the form is prepopulated
if self.anything_else is not None:
self.has_anything_else_text = self.anything_else != ""
# This check is required to ensure that the form doesn't start out checked.
if self.has_anything_else_text is not None:
self.has_anything_else_text = self.anything_else != "" and self.anything_else is not None
def sync_organization_type(self): def sync_organization_type(self):
""" """
Updates the organization_type (without saving) to match Updates the organization_type (without saving) to match
@ -275,6 +331,7 @@ class DomainInformation(TimeStampedModel):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
"""Save override for custom properties""" """Save override for custom properties"""
self.sync_yes_no_form_fields()
self.sync_organization_type() self.sync_organization_type()
super().save(*args, **kwargs) super().save(*args, **kwargs)

View file

@ -477,10 +477,24 @@ class DomainRequest(TimeStampedModel):
cisa_representative_email = models.EmailField( cisa_representative_email = models.EmailField(
null=True, null=True,
blank=True, blank=True,
verbose_name="CISA regional representative", verbose_name="CISA regional representative email",
max_length=320, max_length=320,
) )
cisa_representative_first_name = models.CharField(
null=True,
blank=True,
verbose_name="CISA regional representative first name",
db_index=True,
)
cisa_representative_last_name = models.CharField(
null=True,
blank=True,
verbose_name="CISA regional representative last name",
db_index=True,
)
# This is a drop-in replacement for an has_cisa_representative() function. # This is a drop-in replacement for an has_cisa_representative() function.
# In order to track if the user has clicked the yes/no field (while keeping a none default), we need # In order to track if the user has clicked the yes/no field (while keeping a none default), we need
# a tertiary state. We should not display this in /admin. # a tertiary state. We should not display this in /admin.
@ -577,16 +591,17 @@ class DomainRequest(TimeStampedModel):
"""Some yes/no forms use a db field to track whether it was checked or not. """Some yes/no forms use a db field to track whether it was checked or not.
We handle that here for def save(). We handle that here for def save().
""" """
# This ensures that if we have prefilled data, the form is prepopulated # This ensures that if we have prefilled data, the form is prepopulated
if self.cisa_representative_email is not None: if self.cisa_representative_first_name is not None or self.cisa_representative_last_name is not None:
self.has_cisa_representative = self.cisa_representative_email != "" self.has_cisa_representative = (
self.cisa_representative_first_name != "" and self.cisa_representative_last_name != ""
)
# This check is required to ensure that the form doesn't start out checked # This check is required to ensure that the form doesn't start out checked
if self.has_cisa_representative is not None: if self.has_cisa_representative is not None:
self.has_cisa_representative = ( self.has_cisa_representative = (
self.cisa_representative_email != "" and self.cisa_representative_email is not None self.cisa_representative_first_name != "" and self.cisa_representative_first_name is not None
) ) and (self.cisa_representative_last_name != "" and self.cisa_representative_last_name is not None)
# This ensures that if we have prefilled data, the form is prepopulated # This ensures that if we have prefilled data, the form is prepopulated
if self.anything_else is not None: if self.anything_else is not None:
@ -984,11 +999,12 @@ class DomainRequest(TimeStampedModel):
def has_additional_details(self) -> bool: def has_additional_details(self) -> bool:
"""Combines the has_anything_else_text and has_cisa_representative fields, """Combines the has_anything_else_text and has_cisa_representative fields,
then returns if this domain request has either of them.""" then returns if this domain request has either of them."""
# Split out for linter # Split out for linter
has_details = False
if self.has_anything_else_text or self.has_cisa_representative:
has_details = True has_details = True
if self.has_anything_else_text is None or self.has_cisa_representative is None:
has_details = False
return has_details return has_details
def is_federal(self) -> Union[bool, None]: def is_federal(self) -> Union[bool, None]:
@ -1097,14 +1113,19 @@ class DomainRequest(TimeStampedModel):
return True return True
return False return False
def _cisa_rep_and_email_check(self): def _cisa_rep_check(self):
# Has a CISA rep + email is NOT empty or NOT an empty string OR doesn't have CISA rep # Either does not have a CISA rep, OR has a CISA rep + both first name
return ( # and last name are NOT empty and are NOT an empty string
to_return = (
self.has_cisa_representative is True self.has_cisa_representative is True
and self.cisa_representative_email is not None and self.cisa_representative_first_name is not None
and self.cisa_representative_email != "" and self.cisa_representative_first_name != ""
and self.cisa_representative_last_name is not None
and self.cisa_representative_last_name != ""
) or self.has_cisa_representative is False ) or self.has_cisa_representative is False
return to_return
def _anything_else_radio_button_and_text_field_check(self): def _anything_else_radio_button_and_text_field_check(self):
# Anything else boolean is True + filled text field and it's not an empty string OR the boolean is No # Anything else boolean is True + filled text field and it's not an empty string OR the boolean is No
return ( return (
@ -1112,7 +1133,7 @@ class DomainRequest(TimeStampedModel):
) or self.has_anything_else_text is False ) or self.has_anything_else_text is False
def _is_additional_details_complete(self): def _is_additional_details_complete(self):
return self._cisa_rep_and_email_check() and self._anything_else_radio_button_and_text_field_check() return self._cisa_rep_check() and self._anything_else_radio_button_and_text_field_check()
def _is_policy_acknowledgement_complete(self): def _is_policy_acknowledgement_complete(self):
return self.is_policy_acknowledged is not None return self.is_policy_acknowledged is not None

View file

@ -9,7 +9,6 @@
{# commented out so it does not appear at this point on this page #} {# commented out so it does not appear at this point on this page #}
{% endblock %} {% endblock %}
<!-- TODO-NL: (refactor) Breakup into two separate components-->
{% block form_fields %} {% block form_fields %}
<fieldset class="usa-fieldset margin-top-2"> <fieldset class="usa-fieldset margin-top-2">
<legend> <legend>
@ -22,13 +21,13 @@
{% input_with_errors forms.0.has_cisa_representative %} {% input_with_errors forms.0.has_cisa_representative %}
{% endwith %} {% endwith %}
{# forms.0 is a small yes/no form that toggles the visibility of "cisa representative" formset #} {# forms.0 is a small yes/no form that toggles the visibility of "cisa representative" formset #}
<!-- TODO-NL: Hookup forms.0 to yes/no form for cisa representative (backend def)-->
</fieldset> </fieldset>
<div id="cisa-representative" class="cisa-representative-form"> <div id="cisa-representative" class="cisa-representative-form margin-top-3">
{% input_with_errors forms.1.cisa_representative_first_name %}
{% input_with_errors forms.1.cisa_representative_last_name %}
{% input_with_errors forms.1.cisa_representative_email %} {% input_with_errors forms.1.cisa_representative_email %}
{# forms.1 is a form for inputting the e-mail of a cisa representative #} {# forms.1 is a form for inputting the e-mail of a cisa representative #}
<!-- TODO-NL: Hookup forms.1 to cisa representative form (backend def) -->
</div> </div>
@ -42,7 +41,6 @@
{% input_with_errors forms.2.has_anything_else_text %} {% input_with_errors forms.2.has_anything_else_text %}
{% endwith %} {% endwith %}
{# forms.2 is a small yes/no form that toggles the visibility of "cisa representative" formset #} {# forms.2 is a small yes/no form that toggles the visibility of "cisa representative" formset #}
<!-- TODO-NL: Hookup forms.2 to yes/no form for anything else form (backend def)-->
</fieldset> </fieldset>
<div id="anything-else"> <div id="anything-else">
@ -50,6 +48,5 @@
{% input_with_errors forms.3.anything_else %} {% input_with_errors forms.3.anything_else %}
{% endwith %} {% endwith %}
{# forms.3 is a form for inputting the e-mail of a cisa representative #} {# forms.3 is a form for inputting the e-mail of a cisa representative #}
<!-- TODO-NL: Hookup forms.3 to anything else form (backend def) -->
</div> </div>
{% endblock %} {% endblock %}

View file

@ -157,9 +157,20 @@
{% if step == Step.ADDITIONAL_DETAILS %} {% if step == Step.ADDITIONAL_DETAILS %}
{% namespaced_url 'domain-request' step as domain_request_url %} {% namespaced_url 'domain-request' step as domain_request_url %}
{% with title=form_titles|get_item:step value=domain_request.requested_domain.name|default:"<span class='text-bold text-secondary-dark'>Incomplete</span>"|safe %} {% with title=form_titles|get_item:step %}
{% include "includes/summary_item.html" with title=title sub_header_text='CISA regional representative' value=domain_request.cisa_representative_email heading_level=heading_level editable=True edit_link=domain_request_url custom_text_for_value_none='No' %} {% if domain_request.has_additional_details %}
{% endwith %} {% include "includes/summary_item.html" with title="Additional Details" value=" " heading_level=heading_level editable=True edit_link=domain_request_url %}
<h3 class="register-form-review-header">CISA Regional Representative</h3>
<ul class="usa-list usa-list--unstyled margin-top-0">
{% if domain_request.cisa_representative_first_name %}
<li>{{domain_request.cisa_representative_first_name}} {{domain_request.cisa_representative_last_name}}</li>
{% if domain_request.cisa_representative_email %}
<li>{{domain_request.cisa_representative_email}}</li>
{% endif %}
{% else %}
No
{% endif %}
</ul>
<h3 class="register-form-review-header">Anything else</h3> <h3 class="register-form-review-header">Anything else</h3>
<ul class="usa-list usa-list--unstyled margin-top-0"> <ul class="usa-list usa-list--unstyled margin-top-0">
@ -169,6 +180,10 @@
No No
{% endif %} {% endif %}
</ul> </ul>
{% else %}
{% include "includes/summary_item.html" with title="Additional Details" value="<span class='text-bold text-secondary-dark'>Incomplete</span>"|safe heading_level=heading_level editable=True edit_link=domain_request_url %}
{% endif %}
{% endwith %}
{% endif %} {% endif %}

View file

@ -118,7 +118,15 @@
{# We always show this field even if None #} {# We always show this field even if None #}
{% if DomainRequest %} {% if DomainRequest %}
{% include "includes/summary_item.html" with title='Additional details' sub_header_text='CISA regional representative' value=DomainRequest.cisa_representative_email custom_text_for_value_none='No' heading_level=heading_level %} <h3 class="register-form-review-header">CISA Regional Representative</h3>
<ul class="usa-list usa-list--unstyled margin-top-0">
{% if domain_request.cisa_representative_first_name %}
{{domain_request.cisa_representative_first_name}} {{domain_request.cisa_representative_last_name}}
{% else %}
No
{% endif %}
</ul>
<h3 class="register-form-review-header">Anything else</h3> <h3 class="register-form-review-header">Anything else</h3>
<ul class="usa-list usa-list--unstyled margin-top-0"> <ul class="usa-list usa-list--unstyled margin-top-0">
{% if DomainRequest.anything_else %} {% if DomainRequest.anything_else %}
@ -128,7 +136,6 @@
{% endif %} {% endif %}
</ul> </ul>
{% endif %} {% endif %}
{% endwith %} {% endwith %}
</div> </div>

View file

@ -808,12 +808,13 @@ def create_ready_domain():
# TODO in 1793: Remove the federal agency/updated federal agency fields # TODO in 1793: Remove the federal agency/updated federal agency fields
def completed_domain_request( def completed_domain_request( # noqa
has_other_contacts=True, has_other_contacts=True,
has_current_website=True, has_current_website=True,
has_alternative_gov_domain=True, has_alternative_gov_domain=True,
has_about_your_organization=True, has_about_your_organization=True,
has_anything_else=True, has_anything_else=True,
has_cisa_representative=True,
status=DomainRequest.DomainRequestStatus.STARTED, status=DomainRequest.DomainRequestStatus.STARTED,
user=False, user=False,
submitter=False, submitter=False,
@ -895,6 +896,10 @@ def completed_domain_request(
domain_request.current_websites.add(current) domain_request.current_websites.add(current)
if has_alternative_gov_domain: if has_alternative_gov_domain:
domain_request.alternative_domains.add(alt) domain_request.alternative_domains.add(alt)
if has_cisa_representative:
domain_request.cisa_representative_first_name = "CISA-first-name"
domain_request.cisa_representative_last_name = "CISA-last-name"
domain_request.cisa_representative_email = "cisaRep@igorville.gov"
return domain_request return domain_request

View file

@ -2326,6 +2326,8 @@ class TestDomainRequestAdmin(MockEppLib):
"anything_else", "anything_else",
"has_anything_else_text", "has_anything_else_text",
"cisa_representative_email", "cisa_representative_email",
"cisa_representative_first_name",
"cisa_representative_last_name",
"has_cisa_representative", "has_cisa_representative",
"is_policy_acknowledged", "is_policy_acknowledged",
"submission_date", "submission_date",
@ -2358,6 +2360,8 @@ class TestDomainRequestAdmin(MockEppLib):
"no_other_contacts_rationale", "no_other_contacts_rationale",
"anything_else", "anything_else",
"is_policy_acknowledged", "is_policy_acknowledged",
"cisa_representative_first_name",
"cisa_representative_last_name",
"cisa_representative_email", "cisa_representative_email",
] ]

View file

@ -1802,93 +1802,129 @@ class TestDomainRequestIncomplete(TestCase):
def test_is_additional_details_complete(self): def test_is_additional_details_complete(self):
test_cases = [ test_cases = [
# CISA Rep - Yes # CISA Rep - Yes
# Firstname - Yes
# Lastname - Yes
# Email - Yes # Email - Yes
# Anything Else Radio - Yes # Anything Else Radio - Yes
# Anything Else Text - Yes # Anything Else Text - Yes
{ {
"has_cisa_representative": True, "has_cisa_representative": True,
"cisa_representative_first_name": "cisa-first-name",
"cisa_representative_last_name": "cisa-last-name",
"cisa_representative_email": "some@cisarepemail.com", "cisa_representative_email": "some@cisarepemail.com",
"has_anything_else_text": True, "has_anything_else_text": True,
"anything_else": "Some text", "anything_else": "Some text",
"expected": True, "expected": True,
}, },
# CISA Rep - Yes # CISA Rep - Yes
# Firstname - Yes
# Lastname - Yes
# Email - Yes # Email - Yes
# Anything Else Radio - Yes # Anything Else Radio - Yes
# Anything Else Text - None # Anything Else Text - None
{ {
"has_cisa_representative": True, "has_cisa_representative": True,
"cisa_representative_first_name": "cisa-first-name",
"cisa_representative_last_name": "cisa-last-name",
"cisa_representative_email": "some@cisarepemail.com", "cisa_representative_email": "some@cisarepemail.com",
"has_anything_else_text": True, "has_anything_else_text": True,
"anything_else": None, "anything_else": None,
"expected": True, "expected": True,
}, },
# CISA Rep - Yes # CISA Rep - Yes
# Email - Yes # Firstname - Yes
# Lastname - Yes
# Email - None >> e-mail is optional so it should not change anything setting this to None
# Anything Else Radio - No # Anything Else Radio - No
# Anything Else Text - No # Anything Else Text - No
{ {
"has_cisa_representative": True, "has_cisa_representative": True,
"cisa_representative_email": "some@cisarepemail.com", "cisa_representative_first_name": "cisa-first-name",
"cisa_representative_last_name": "cisa-last-name",
"cisa_representative_email": None,
"has_anything_else_text": False, "has_anything_else_text": False,
"anything_else": None, "anything_else": None,
"expected": True, "expected": True,
}, },
# CISA Rep - Yes # CISA Rep - Yes
# Email - Yes # Firstname - Yes
# Anything Else Radio - None # Lastname - Yes
# Anything Else Text - None
{
"has_cisa_representative": True,
"cisa_representative_email": "some@cisarepemail.com",
"has_anything_else_text": None,
"anything_else": None,
"expected": False,
},
# CISA Rep - Yes
# Email - None # Email - None
# Anything Else Radio - None # Anything Else Radio - None
# Anything Else Text - None # Anything Else Text - None
{ {
"has_cisa_representative": True, "has_cisa_representative": True,
"cisa_representative_first_name": "cisa-first-name",
"cisa_representative_last_name": "cisa-last-name",
"cisa_representative_email": None, "cisa_representative_email": None,
"has_anything_else_text": None, "has_anything_else_text": None,
"anything_else": None, "anything_else": None,
"expected": False, "expected": False,
}, },
# CISA Rep - Yes # CISA Rep - Yes
# Firstname - None
# Lastname - None
# Email - None
# Anything Else Radio - None
# Anything Else Text - None
{
"has_cisa_representative": True,
"cisa_representative_first_name": None,
"cisa_representative_last_name": None,
"cisa_representative_email": None,
"has_anything_else_text": None,
"anything_else": None,
"expected": False,
},
# CISA Rep - Yes
# Firstname - None
# Lastname - None
# Email - None # Email - None
# Anything Else Radio - No # Anything Else Radio - No
# Anything Else Text - No # Anything Else Text - No
# sync_yes_no will override has_cisa_representative to be False if cisa_representative_email is None # sync_yes_no will override has_cisa_representative to be False if cisa_representative_first_name is None
# therefore, our expected will be True # therefore, our expected will be True
{ {
"has_cisa_representative": True, "has_cisa_representative": True,
# Above will be overridden to False if cisa_rep_email is None bc of sync_yes_no_form_fields # Above will be overridden to False if cisa_representative_first_name is None
"cisa_representative_first_name": None,
"cisa_representative_last_name": None,
"cisa_representative_email": None, "cisa_representative_email": None,
"has_anything_else_text": False, "has_anything_else_text": False,
"anything_else": None, "anything_else": None,
"expected": True, "expected": True,
}, },
# CISA Rep - Yes # CISA Rep - Yes
# Firstname - None
# Lastname - None
# Email - None # Email - None
# Anything Else Radio - Yes # Anything Else Radio - Yes
# Anything Else Text - None # Anything Else Text - None
# NOTE: We should never have an instance where only firstname or only lastname are populated
# (they are both required)
{ {
"has_cisa_representative": True, "has_cisa_representative": True,
# Above will be overridden to False if cisa_rep_email is None bc of sync_yes_no_form_fields # Above will be overridden to False if cisa_representative_first_name is None or
# cisa_representative_last_name is None bc of sync_yes_no_form_fields
"cisa_representative_first_name": None,
"cisa_representative_last_name": None,
"cisa_representative_email": None, "cisa_representative_email": None,
"has_anything_else_text": True, "has_anything_else_text": True,
"anything_else": None, "anything_else": None,
"expected": True, "expected": True,
}, },
# CISA Rep - Yes # CISA Rep - Yes
# Firstname - None
# Lastname - None
# Email - None # Email - None
# Anything Else Radio - Yes # Anything Else Radio - Yes
# Anything Else Text - Yes # Anything Else Text - Yes
{ {
"has_cisa_representative": True, "has_cisa_representative": True,
# Above will be overridden to False if cisa_rep_email is None bc of sync_yes_no_form_fields # Above will be overridden to False if cisa_representative_first_name is None or
# cisa_representative_last_name is None bc of sync_yes_no_form_fields
"cisa_representative_first_name": None,
"cisa_representative_last_name": None,
"cisa_representative_email": None, "cisa_representative_email": None,
"has_anything_else_text": True, "has_anything_else_text": True,
"anything_else": "Some text", "anything_else": "Some text",
@ -1899,6 +1935,8 @@ class TestDomainRequestIncomplete(TestCase):
# Anything Else Text - Yes # Anything Else Text - Yes
{ {
"has_cisa_representative": False, "has_cisa_representative": False,
"cisa_representative_first_name": None,
"cisa_representative_last_name": None,
"cisa_representative_email": None, "cisa_representative_email": None,
"has_anything_else_text": True, "has_anything_else_text": True,
"anything_else": "Some text", "anything_else": "Some text",
@ -1909,6 +1947,8 @@ class TestDomainRequestIncomplete(TestCase):
# Anything Else Text - None # Anything Else Text - None
{ {
"has_cisa_representative": False, "has_cisa_representative": False,
"cisa_representative_first_name": None,
"cisa_representative_last_name": None,
"cisa_representative_email": None, "cisa_representative_email": None,
"has_anything_else_text": True, "has_anything_else_text": True,
"anything_else": None, "anything_else": None,
@ -1919,6 +1959,8 @@ class TestDomainRequestIncomplete(TestCase):
# Anything Else Text - None # Anything Else Text - None
{ {
"has_cisa_representative": False, "has_cisa_representative": False,
"cisa_representative_first_name": None,
"cisa_representative_last_name": None,
"cisa_representative_email": None, "cisa_representative_email": None,
"has_anything_else_text": None, "has_anything_else_text": None,
"anything_else": None, "anything_else": None,
@ -1930,6 +1972,8 @@ class TestDomainRequestIncomplete(TestCase):
# Anything Else Text - No # Anything Else Text - No
{ {
"has_cisa_representative": False, "has_cisa_representative": False,
"cisa_representative_first_name": None,
"cisa_representative_last_name": None,
"cisa_representative_email": None, "cisa_representative_email": None,
"has_anything_else_text": False, "has_anything_else_text": False,
"anything_else": None, "anything_else": None,
@ -1939,6 +1983,8 @@ class TestDomainRequestIncomplete(TestCase):
# Anything Else Radio - None # Anything Else Radio - None
{ {
"has_cisa_representative": None, "has_cisa_representative": None,
"cisa_representative_first_name": None,
"cisa_representative_last_name": None,
"cisa_representative_email": None, "cisa_representative_email": None,
"has_anything_else_text": None, "has_anything_else_text": None,
"anything_else": None, "anything_else": None,

View file

@ -366,6 +366,8 @@ class DomainRequestTests(TestWithUser, WebTest):
additional_details_form["additional_details-has_cisa_representative"] = "True" additional_details_form["additional_details-has_cisa_representative"] = "True"
additional_details_form["additional_details-has_anything_else_text"] = "True" additional_details_form["additional_details-has_anything_else_text"] = "True"
additional_details_form["additional_details-cisa_representative_first_name"] = "CISA-first-name"
additional_details_form["additional_details-cisa_representative_last_name"] = "CISA-last-name"
additional_details_form["additional_details-cisa_representative_email"] = "FakeEmail@gmail.com" additional_details_form["additional_details-cisa_representative_email"] = "FakeEmail@gmail.com"
additional_details_form["additional_details-anything_else"] = "Nothing else." additional_details_form["additional_details-anything_else"] = "Nothing else."
@ -374,6 +376,8 @@ class DomainRequestTests(TestWithUser, WebTest):
additional_details_result = additional_details_form.submit() additional_details_result = additional_details_form.submit()
# validate that data from this step are being saved # validate that data from this step are being saved
domain_request = DomainRequest.objects.get() # there's only one domain_request = DomainRequest.objects.get() # there's only one
self.assertEqual(domain_request.cisa_representative_first_name, "CISA-first-name")
self.assertEqual(domain_request.cisa_representative_last_name, "CISA-last-name")
self.assertEqual(domain_request.cisa_representative_email, "FakeEmail@gmail.com") self.assertEqual(domain_request.cisa_representative_email, "FakeEmail@gmail.com")
self.assertEqual(domain_request.anything_else, "Nothing else.") self.assertEqual(domain_request.anything_else, "Nothing else.")
# the post request should return a redirect to the next form in # the post request should return a redirect to the next form in
@ -719,6 +723,8 @@ class DomainRequestTests(TestWithUser, WebTest):
additional_details_form["additional_details-has_cisa_representative"] = "True" additional_details_form["additional_details-has_cisa_representative"] = "True"
additional_details_form["additional_details-has_anything_else_text"] = "True" additional_details_form["additional_details-has_anything_else_text"] = "True"
additional_details_form["additional_details-cisa_representative_first_name"] = "cisa-first-name"
additional_details_form["additional_details-cisa_representative_last_name"] = "cisa-last-name"
additional_details_form["additional_details-cisa_representative_email"] = "FakeEmail@gmail.com" additional_details_form["additional_details-cisa_representative_email"] = "FakeEmail@gmail.com"
additional_details_form["additional_details-anything_else"] = "Nothing else." additional_details_form["additional_details-anything_else"] = "Nothing else."
@ -727,6 +733,8 @@ class DomainRequestTests(TestWithUser, WebTest):
additional_details_result = additional_details_form.submit() additional_details_result = additional_details_form.submit()
# validate that data from this step are being saved # validate that data from this step are being saved
domain_request = DomainRequest.objects.get() # there's only one domain_request = DomainRequest.objects.get() # there's only one
self.assertEqual(domain_request.cisa_representative_first_name, "cisa-first-name")
self.assertEqual(domain_request.cisa_representative_last_name, "cisa-last-name")
self.assertEqual(domain_request.cisa_representative_email, "FakeEmail@gmail.com") self.assertEqual(domain_request.cisa_representative_email, "FakeEmail@gmail.com")
self.assertEqual(domain_request.anything_else, "Nothing else.") self.assertEqual(domain_request.anything_else, "Nothing else.")
# the post request should return a redirect to the next form in # the post request should return a redirect to the next form in
@ -1125,11 +1133,10 @@ class DomainRequestTests(TestWithUser, WebTest):
def test_yes_no_form_inits_yes_for_cisa_representative_and_anything_else(self): def test_yes_no_form_inits_yes_for_cisa_representative_and_anything_else(self):
"""On the Additional Details page, the yes/no form gets initialized with YES selected """On the Additional Details page, the yes/no form gets initialized with YES selected
for both yes/no radios if the domain request has a value for cisa_representative and for both yes/no radios if the domain request has a values for cisa_representative_first_name and
anything_else""" anything_else"""
domain_request = completed_domain_request(user=self.user, has_anything_else=True) domain_request = completed_domain_request(user=self.user, has_anything_else=True, has_cisa_representative=True)
domain_request.cisa_representative_email = "test@igorville.gov"
domain_request.anything_else = "1234" domain_request.anything_else = "1234"
domain_request.save() domain_request.save()
@ -1181,12 +1188,13 @@ class DomainRequestTests(TestWithUser, WebTest):
"""On the Additional details page, the form preselects "no" when has_cisa_representative """On the Additional details page, the form preselects "no" when has_cisa_representative
and anything_else is no""" and anything_else is no"""
domain_request = completed_domain_request(user=self.user, has_anything_else=False) domain_request = completed_domain_request(
user=self.user, has_anything_else=False, has_cisa_representative=False
)
# Unlike the other contacts form, the no button is tracked with these boolean fields. # Unlike the other contacts form, the no button is tracked with these boolean fields.
# This means that we should expect this to correlate with the no button. # This means that we should expect this to correlate with the no button.
domain_request.has_anything_else_text = False domain_request.has_anything_else_text = False
domain_request.has_cisa_representative = False
domain_request.save() domain_request.save()
# prime the form by visiting /edit # prime the form by visiting /edit
@ -1205,7 +1213,7 @@ class DomainRequestTests(TestWithUser, WebTest):
# Check the cisa representative yes/no field # Check the cisa representative yes/no field
yes_no_cisa = additional_details_form["additional_details-has_cisa_representative"].value yes_no_cisa = additional_details_form["additional_details-has_cisa_representative"].value
self.assertEquals(yes_no_cisa, "False") self.assertEquals(yes_no_cisa, None)
# Check the anything else yes/no field # Check the anything else yes/no field
yes_no_anything_else = additional_details_form["additional_details-has_anything_else_text"].value yes_no_anything_else = additional_details_form["additional_details-has_anything_else_text"].value
@ -1215,11 +1223,15 @@ class DomainRequestTests(TestWithUser, WebTest):
"""When a user submits the Additional Details form with no selected for all fields, """When a user submits the Additional Details form with no selected for all fields,
the domain request's data gets wiped when submitted""" the domain request's data gets wiped when submitted"""
domain_request = completed_domain_request(name="nocisareps.gov", user=self.user) domain_request = completed_domain_request(name="nocisareps.gov", user=self.user)
domain_request.cisa_representative_first_name = "cisa-firstname1"
domain_request.cisa_representative_last_name = "cisa-lastname1"
domain_request.cisa_representative_email = "fake@faketown.gov" domain_request.cisa_representative_email = "fake@faketown.gov"
domain_request.save() domain_request.save()
# Make sure we have the data we need for the test # Make sure we have the data we need for the test
self.assertEqual(domain_request.anything_else, "There is more") self.assertEqual(domain_request.anything_else, "There is more")
self.assertEqual(domain_request.cisa_representative_first_name, "cisa-firstname1")
self.assertEqual(domain_request.cisa_representative_last_name, "cisa-lastname1")
self.assertEqual(domain_request.cisa_representative_email, "fake@faketown.gov") self.assertEqual(domain_request.cisa_representative_email, "fake@faketown.gov")
# prime the form by visiting /edit # prime the form by visiting /edit
@ -1253,25 +1265,31 @@ class DomainRequestTests(TestWithUser, WebTest):
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
# Verify that the anything_else and cisa_representative have been deleted from the DB # Verify that the anything_else and cisa_representative information have been deleted from the DB
domain_request = DomainRequest.objects.get(requested_domain__name="nocisareps.gov") domain_request = DomainRequest.objects.get(requested_domain__name="nocisareps.gov")
# Check that our data has been cleared # Check that our data has been cleared
self.assertEqual(domain_request.anything_else, None) self.assertEqual(domain_request.anything_else, None)
self.assertEqual(domain_request.cisa_representative_first_name, None)
self.assertEqual(domain_request.cisa_representative_last_name, None)
self.assertEqual(domain_request.cisa_representative_email, None) self.assertEqual(domain_request.cisa_representative_email, None)
# Double check the yes/no fields # Double check the yes/no fields
self.assertEqual(domain_request.has_anything_else_text, False) self.assertEqual(domain_request.has_anything_else_text, False)
self.assertEqual(domain_request.has_cisa_representative, False) self.assertEqual(domain_request.cisa_representative_first_name, None)
self.assertEqual(domain_request.cisa_representative_last_name, None)
self.assertEqual(domain_request.cisa_representative_email, None)
def test_submitting_additional_details_populates_cisa_representative_and_anything_else(self): def test_submitting_additional_details_populates_cisa_representative_and_anything_else(self):
"""When a user submits the Additional Details form, """When a user submits the Additional Details form,
the domain request's data gets submitted""" the domain request's data gets submitted"""
domain_request = completed_domain_request(name="cisareps.gov", user=self.user, has_anything_else=False) domain_request = completed_domain_request(
name="cisareps.gov", user=self.user, has_anything_else=False, has_cisa_representative=False
)
# Make sure we have the data we need for the test # Make sure we have the data we need for the test
self.assertEqual(domain_request.anything_else, None) self.assertEqual(domain_request.anything_else, None)
self.assertEqual(domain_request.cisa_representative_email, None) self.assertEqual(domain_request.cisa_representative_first_name, None)
# These fields should not be selected at all, since we haven't initialized the form yet # These fields should not be selected at all, since we haven't initialized the form yet
self.assertEqual(domain_request.has_anything_else_text, None) self.assertEqual(domain_request.has_anything_else_text, None)
@ -1294,6 +1312,8 @@ class DomainRequestTests(TestWithUser, WebTest):
# Set fields to true, and set data on those fields # Set fields to true, and set data on those fields
additional_details_form["additional_details-has_cisa_representative"] = "True" additional_details_form["additional_details-has_cisa_representative"] = "True"
additional_details_form["additional_details-has_anything_else_text"] = "True" additional_details_form["additional_details-has_anything_else_text"] = "True"
additional_details_form["additional_details-cisa_representative_first_name"] = "cisa-firstname"
additional_details_form["additional_details-cisa_representative_last_name"] = "cisa-lastname"
additional_details_form["additional_details-cisa_representative_email"] = "test@faketest.gov" additional_details_form["additional_details-cisa_representative_email"] = "test@faketest.gov"
additional_details_form["additional_details-anything_else"] = "redandblue" additional_details_form["additional_details-anything_else"] = "redandblue"
@ -1302,10 +1322,12 @@ class DomainRequestTests(TestWithUser, WebTest):
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
# Verify that the anything_else and cisa_representative exist in the db # Verify that the anything_else and cisa_representative information exist in the db
domain_request = DomainRequest.objects.get(requested_domain__name="cisareps.gov") domain_request = DomainRequest.objects.get(requested_domain__name="cisareps.gov")
self.assertEqual(domain_request.anything_else, "redandblue") self.assertEqual(domain_request.anything_else, "redandblue")
self.assertEqual(domain_request.cisa_representative_first_name, "cisa-firstname")
self.assertEqual(domain_request.cisa_representative_last_name, "cisa-lastname")
self.assertEqual(domain_request.cisa_representative_email, "test@faketest.gov") self.assertEqual(domain_request.cisa_representative_email, "test@faketest.gov")
self.assertEqual(domain_request.has_cisa_representative, True) self.assertEqual(domain_request.has_cisa_representative, True)
@ -1313,7 +1335,9 @@ class DomainRequestTests(TestWithUser, WebTest):
def test_if_cisa_representative_yes_no_form_is_yes_then_field_is_required(self): def test_if_cisa_representative_yes_no_form_is_yes_then_field_is_required(self):
"""Applicants with a cisa representative must provide a value""" """Applicants with a cisa representative must provide a value"""
domain_request = completed_domain_request(name="cisareps.gov", user=self.user, has_anything_else=False) domain_request = completed_domain_request(
name="cisareps.gov", user=self.user, has_anything_else=False, has_cisa_representative=False
)
# prime the form by visiting /edit # prime the form by visiting /edit
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk})) self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
@ -1338,7 +1362,8 @@ class DomainRequestTests(TestWithUser, WebTest):
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
self.assertContains(response, "Enter the email address of your CISA regional representative.") self.assertContains(response, "Enter the first name / given name of the CISA regional representative.")
self.assertContains(response, "Enter the last name / family name of the CISA regional representative.")
def test_if_anything_else_yes_no_form_is_yes_then_field_is_required(self): def test_if_anything_else_yes_no_form_is_yes_then_field_is_required(self):
"""Applicants with a anything else must provide a value""" """Applicants with a anything else must provide a value"""
@ -1373,7 +1398,9 @@ class DomainRequestTests(TestWithUser, WebTest):
def test_additional_details_form_fields_required(self): def test_additional_details_form_fields_required(self):
"""When a user submits the Additional Details form without checking the """When a user submits the Additional Details form without checking the
has_cisa_representative and has_anything_else_text fields, the form should deny this action""" has_cisa_representative and has_anything_else_text fields, the form should deny this action"""
domain_request = completed_domain_request(name="cisareps.gov", user=self.user, has_anything_else=False) domain_request = completed_domain_request(
name="cisareps.gov", user=self.user, has_anything_else=False, has_cisa_representative=False
)
self.assertEqual(domain_request.has_anything_else_text, None) self.assertEqual(domain_request.has_anything_else_text, None)
self.assertEqual(domain_request.has_cisa_representative, None) self.assertEqual(domain_request.has_cisa_representative, None)

View file

@ -381,6 +381,7 @@ def export_data_type_to_csv(csv_file):
""" """
All domains report with extra columns. All domains report with extra columns.
This maps to the "All domain metadata" button. This maps to the "All domain metadata" button.
Exports domains of all statuses.
""" """
writer = csv.writer(csv_file) writer = csv.writer(csv_file)
@ -408,15 +409,8 @@ def export_data_type_to_csv(csv_file):
"federal_agency", "federal_agency",
"domain__name", "domain__name",
] ]
filter_condition = {
"domain__state__in": [
Domain.State.READY,
Domain.State.DNS_NEEDED,
Domain.State.ON_HOLD,
],
}
write_csv_for_domains( write_csv_for_domains(
writer, columns, sort_fields, filter_condition, should_get_domain_managers=True, should_write_header=True writer, columns, sort_fields, filter_condition={}, should_get_domain_managers=True, should_write_header=True
) )

View file

@ -369,7 +369,7 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
or self.domain_request.no_other_contacts_rationale is not None or self.domain_request.no_other_contacts_rationale is not None
), ),
"additional_details": ( "additional_details": (
(self.domain_request.anything_else is not None and self.domain_request.cisa_representative_email) (self.domain_request.anything_else is not None and self.domain_request.has_cisa_representative)
or self.domain_request.is_policy_acknowledged is not None or self.domain_request.is_policy_acknowledged is not None
), ),
"requirements": self.domain_request.is_policy_acknowledged is not None, "requirements": self.domain_request.is_policy_acknowledged is not None,
@ -380,7 +380,6 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
def get_context_data(self): def get_context_data(self):
"""Define context for access on all wizard pages.""" """Define context for access on all wizard pages."""
has_profile_flag = flag_is_active(self.request, "profile_feature") has_profile_flag = flag_is_active(self.request, "profile_feature")
logger.debug("PROFILE FLAG is %s" % has_profile_flag)
context_stuff = {} context_stuff = {}
if DomainRequest._form_complete(self.domain_request): if DomainRequest._form_complete(self.domain_request):