This commit is contained in:
Rachid Mrad 2024-03-05 14:41:34 -05:00
parent f7856d52fe
commit 2081f5c564
No known key found for this signature in database
4 changed files with 86 additions and 62 deletions

View file

@ -424,7 +424,7 @@ def analytics(request):
"domain__state__in": [Domain.State.DELETED], "domain__state__in": [Domain.State.DELETED],
"domain__deleted__lte": end_date_formatted, "domain__deleted__lte": end_date_formatted,
} }
deleted_domains_sliced_at_start_date = csv_export.get_sliced_domains(filter_deleted_domains_start_date) deleted_domains_sliced_at_start_date = csv_export.get_sliced_domains(filter_deleted_domains_start_date)
deleted_domains_sliced_at_end_date = csv_export.get_sliced_domains(filter_deleted_domains_end_date) deleted_domains_sliced_at_end_date = csv_export.get_sliced_domains(filter_deleted_domains_end_date)
# Created and Submitted requests # Created and Submitted requests

View file

@ -1,4 +1,3 @@
import datetime
import os import os
import logging import logging
@ -473,7 +472,8 @@ class AuditedAdminMockData:
application.alternative_domains.add(alt) application.alternative_domains.add(alt)
return application return application
class MockDb(TestCase): class MockDb(TestCase):
"""Hardcoded mocks make test case assertions sraightforward.""" """Hardcoded mocks make test case assertions sraightforward."""
@ -535,69 +535,66 @@ class MockDb(TestCase):
organization_type="federal", organization_type="federal",
federal_agency="World War I Centennial Commission", federal_agency="World War I Centennial Commission",
federal_type="executive", federal_type="executive",
is_election_board=True is_election_board=True,
) )
self.domain_information_2, _ = DomainInformation.objects.get_or_create( self.domain_information_2, _ = DomainInformation.objects.get_or_create(
creator=self.user, creator=self.user, domain=self.domain_2, organization_type="interstate", is_election_board=True
domain=self.domain_2,
organization_type="interstate",
is_election_board=True
) )
self.domain_information_3, _ = DomainInformation.objects.get_or_create( self.domain_information_3, _ = DomainInformation.objects.get_or_create(
creator=self.user, creator=self.user,
domain=self.domain_3, domain=self.domain_3,
organization_type="federal", organization_type="federal",
federal_agency="Armed Forces Retirement Home", federal_agency="Armed Forces Retirement Home",
is_election_board=True is_election_board=True,
) )
self.domain_information_4, _ = DomainInformation.objects.get_or_create( self.domain_information_4, _ = DomainInformation.objects.get_or_create(
creator=self.user, creator=self.user,
domain=self.domain_4, domain=self.domain_4,
organization_type="federal", organization_type="federal",
federal_agency="Armed Forces Retirement Home", federal_agency="Armed Forces Retirement Home",
is_election_board=True is_election_board=True,
) )
self.domain_information_5, _ = DomainInformation.objects.get_or_create( self.domain_information_5, _ = DomainInformation.objects.get_or_create(
creator=self.user, creator=self.user,
domain=self.domain_5, domain=self.domain_5,
organization_type="federal", organization_type="federal",
federal_agency="Armed Forces Retirement Home", federal_agency="Armed Forces Retirement Home",
is_election_board=False is_election_board=False,
) )
self.domain_information_6, _ = DomainInformation.objects.get_or_create( self.domain_information_6, _ = DomainInformation.objects.get_or_create(
creator=self.user, creator=self.user,
domain=self.domain_6, domain=self.domain_6,
organization_type="federal", organization_type="federal",
federal_agency="Armed Forces Retirement Home", federal_agency="Armed Forces Retirement Home",
is_election_board=False is_election_board=False,
) )
self.domain_information_7, _ = DomainInformation.objects.get_or_create( self.domain_information_7, _ = DomainInformation.objects.get_or_create(
creator=self.user, creator=self.user,
domain=self.domain_7, domain=self.domain_7,
organization_type="federal", organization_type="federal",
federal_agency="Armed Forces Retirement Home", federal_agency="Armed Forces Retirement Home",
is_election_board=False is_election_board=False,
) )
self.domain_information_8, _ = DomainInformation.objects.get_or_create( self.domain_information_8, _ = DomainInformation.objects.get_or_create(
creator=self.user, creator=self.user,
domain=self.domain_8, domain=self.domain_8,
organization_type="federal", organization_type="federal",
federal_agency="Armed Forces Retirement Home", federal_agency="Armed Forces Retirement Home",
is_election_board=False is_election_board=False,
) )
self.domain_information_9, _ = DomainInformation.objects.get_or_create( self.domain_information_9, _ = DomainInformation.objects.get_or_create(
creator=self.user, creator=self.user,
domain=self.domain_9, domain=self.domain_9,
organization_type="federal", organization_type="federal",
federal_agency="Armed Forces Retirement Home", federal_agency="Armed Forces Retirement Home",
is_election_board=False is_election_board=False,
) )
self.domain_information_10, _ = DomainInformation.objects.get_or_create( self.domain_information_10, _ = DomainInformation.objects.get_or_create(
creator=self.user, creator=self.user,
domain=self.domain_10, domain=self.domain_10,
organization_type="federal", organization_type="federal",
federal_agency="Armed Forces Retirement Home", federal_agency="Armed Forces Retirement Home",
is_election_board=False is_election_board=False,
) )
meoward_user = get_user_model().objects.create( meoward_user = get_user_model().objects.create(
@ -625,11 +622,21 @@ class MockDb(TestCase):
) )
with less_console_noise(): with less_console_noise():
self.domain_request_1 = completed_application(status=DomainApplication.ApplicationStatus.STARTED, name="city1.gov") self.domain_request_1 = completed_application(
self.domain_request_2 = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW, name="city2.gov") status=DomainApplication.ApplicationStatus.STARTED, name="city1.gov"
self.domain_request_3 = completed_application(status=DomainApplication.ApplicationStatus.STARTED, name="city3.gov") )
self.domain_request_4 = completed_application(status=DomainApplication.ApplicationStatus.STARTED, name="city4.gov") self.domain_request_2 = completed_application(
self.domain_request_5 = completed_application(status=DomainApplication.ApplicationStatus.APPROVED, name="city5.gov") status=DomainApplication.ApplicationStatus.IN_REVIEW, name="city2.gov"
)
self.domain_request_3 = completed_application(
status=DomainApplication.ApplicationStatus.STARTED, name="city3.gov"
)
self.domain_request_4 = completed_application(
status=DomainApplication.ApplicationStatus.STARTED, name="city4.gov"
)
self.domain_request_5 = completed_application(
status=DomainApplication.ApplicationStatus.APPROVED, name="city5.gov"
)
self.domain_request_3.submit() self.domain_request_3.submit()
self.domain_request_3.save() self.domain_request_3.save()
self.domain_request_4.submit() self.domain_request_4.submit()

View file

@ -43,7 +43,7 @@ class CsvReportsTest(MockDb):
expected_file_content = [ expected_file_content = [
call("Domain name,Domain type,Agency,Organization name,City,State,Security contact email\r\n"), call("Domain name,Domain type,Agency,Organization name,City,State,Security contact email\r\n"),
call("cdomain1.gov,Federal - Executive,World War I Centennial Commission,,,, \r\n"), call("cdomain1.gov,Federal - Executive,World War I Centennial Commission,,,, \r\n"),
call('adomain10.gov,Federal,Armed Forces Retirement Home,,,, \r\n'), call("adomain10.gov,Federal,Armed Forces Retirement Home,,,, \r\n"),
call("ddomain3.gov,Federal,Armed Forces Retirement Home,,,, \r\n"), call("ddomain3.gov,Federal,Armed Forces Retirement Home,,,, \r\n"),
] ]
# We don't actually want to write anything for a test case, # We don't actually want to write anything for a test case,
@ -64,7 +64,7 @@ class CsvReportsTest(MockDb):
expected_file_content = [ expected_file_content = [
call("Domain name,Domain type,Agency,Organization name,City,State,Security contact email\r\n"), call("Domain name,Domain type,Agency,Organization name,City,State,Security contact email\r\n"),
call("cdomain1.gov,Federal - Executive,World War I Centennial Commission,,,, \r\n"), call("cdomain1.gov,Federal - Executive,World War I Centennial Commission,,,, \r\n"),
call('adomain10.gov,Federal,Armed Forces Retirement Home,,,, \r\n'), call("adomain10.gov,Federal,Armed Forces Retirement Home,,,, \r\n"),
call("ddomain3.gov,Federal,Armed Forces Retirement Home,,,, \r\n"), call("ddomain3.gov,Federal,Armed Forces Retirement Home,,,, \r\n"),
call("adomain2.gov,Interstate,,,,, \r\n"), call("adomain2.gov,Interstate,,,,, \r\n"),
] ]
@ -525,7 +525,7 @@ class ExportDataTest(MockDb, MockEppLib):
def test_export_data_managed_domains_to_csv(self): def test_export_data_managed_domains_to_csv(self):
"""Test get counts for domains that have domain managers for two different dates, """Test get counts for domains that have domain managers for two different dates,
get list of managed domains at end_date.""" get list of managed domains at end_date."""
with less_console_noise(): with less_console_noise():
# Create a CSV file in memory # Create a CSV file in memory
@ -596,32 +596,34 @@ class ExportDataTest(MockDb, MockEppLib):
csv_file.seek(0) csv_file.seek(0)
# Read the content into a variable # Read the content into a variable
csv_content = csv_file.read() csv_content = csv_file.read()
self.maxDiff=None self.maxDiff = None
# We expect the READY domain names with the domain managers: Their counts, and listing at end_date. # We expect the READY domain names with the domain managers: Their counts, and listing at end_date.
expected_content = ( expected_content = (
"MANAGED DOMAINS COUNTS AT START DATE\n" "MANAGED DOMAINS COUNTS AT START DATE\n"
"Total,Federal,Interstate,State or territory,Tribal,County,City,Special district,School district,Election office\n" "Total,Federal,Interstate,State or territory,Tribal,County,City,Special district,"
"School district,Election office\n"
"0,0,0,0,0,0,0,0,0,0\n" "0,0,0,0,0,0,0,0,0,0\n"
"\n" "\n"
"MANAGED DOMAINS COUNTS AT END DATE\n" "MANAGED DOMAINS COUNTS AT END DATE\n"
"Total,Federal,Interstate,State or territory,Tribal,County,City,Special district,School district,Election office\n" "Total,Federal,Interstate,State or territory,Tribal,County,City,"
"Special district,School district,Election office\n"
"1,1,0,0,0,0,0,0,0,1\n" "1,1,0,0,0,0,0,0,0,1\n"
"\n" "\n"
"Domain name,Domain type,Domain manager email 1,Domain manager email 2,Domain manager email 3\n" "Domain name,Domain type,Domain manager email 1,Domain manager email 2,Domain manager email 3\n"
"cdomain1.gov,Federal - Executive,meoward@rocks.com,info@example.com,big_lebowski@dude.co\n" "cdomain1.gov,Federal - Executive,meoward@rocks.com,info@example.com,big_lebowski@dude.co\n"
) )
# Normalize line endings and remove commas, # Normalize line endings and remove commas,
# spaces and leading/trailing whitespace # spaces and leading/trailing whitespace
csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip() csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip()
expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip() expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip()
self.assertEqual(csv_content, expected_content) self.assertEqual(csv_content, expected_content)
def test_export_data_unmanaged_domains_to_csv(self): def test_export_data_unmanaged_domains_to_csv(self):
"""Test get counts for domains that do not have domain managers for two different dates, """Test get counts for domains that do not have domain managers for two different dates,
get list of unmanaged domains at end_date.""" get list of unmanaged domains at end_date."""
with less_console_noise(): with less_console_noise():
# Create a CSV file in memory # Create a CSV file in memory
csv_file = StringIO() csv_file = StringIO()
@ -691,26 +693,28 @@ class ExportDataTest(MockDb, MockEppLib):
csv_file.seek(0) csv_file.seek(0)
# Read the content into a variable # Read the content into a variable
csv_content = csv_file.read() csv_content = csv_file.read()
self.maxDiff=None self.maxDiff = None
# We expect the READY domain names with the domain managers: Their counts, and listing at end_date. # We expect the READY domain names with the domain managers: Their counts, and listing at end_date.
expected_content = ( expected_content = (
"UNMANAGED DOMAINS COUNTS AT START DATE\n" "UNMANAGED DOMAINS COUNTS AT START DATE\n"
"Total,Federal,Interstate,State or territory,Tribal,County,City,Special district,School district,Election office\n" "Total,Federal,Interstate,State or territory,Tribal,County,City,Special district,"
"School district,Election office\n"
"0,0,0,0,0,0,0,0,0,0\n" "0,0,0,0,0,0,0,0,0,0\n"
"\n" "\n"
"UNMANAGED DOMAINS COUNTS AT END DATE\n" "UNMANAGED DOMAINS COUNTS AT END DATE\n"
"Total,Federal,Interstate,State or territory,Tribal,County,City,Special district,School district,Election office\n" "Total,Federal,Interstate,State or territory,Tribal,County,City,Special district,"
"School district,Election office\n"
"1,1,0,0,0,0,0,0,0,0\n" "1,1,0,0,0,0,0,0,0,0\n"
"\n" "\n"
"Domain name,Domain type\n" "Domain name,Domain type\n"
"adomain10.gov,Federal\n" "adomain10.gov,Federal\n"
) )
# Normalize line endings and remove commas, # Normalize line endings and remove commas,
# spaces and leading/trailing whitespace # spaces and leading/trailing whitespace
csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip() csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip()
expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip() expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip()
self.assertEqual(csv_content, expected_content) self.assertEqual(csv_content, expected_content)
def test_write_requests_body_with_date_filter_pulls_requests_in_range(self): def test_write_requests_body_with_date_filter_pulls_requests_in_range(self):
@ -750,14 +754,15 @@ class ExportDataTest(MockDb, MockEppLib):
"city3.gov,Federal - Executive,2024-03-05\n" "city3.gov,Federal - Executive,2024-03-05\n"
"city4.gov,Federal - Executive,2024-03-05\n" "city4.gov,Federal - Executive,2024-03-05\n"
) )
# Normalize line endings and remove commas, # Normalize line endings and remove commas,
# spaces and leading/trailing whitespace # spaces and leading/trailing whitespace
csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip() csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip()
expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip() expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip()
self.assertEqual(csv_content, expected_content) self.assertEqual(csv_content, expected_content)
class HelperFunctions(MockDb): class HelperFunctions(MockDb):
"""This asserts that 1=1. Its limited usefulness lies in making sure the helper methods stay healthy.""" """This asserts that 1=1. Its limited usefulness lies in making sure the helper methods stay healthy."""
@ -774,28 +779,24 @@ class HelperFunctions(MockDb):
def test_get_sliced_domains(self): def test_get_sliced_domains(self):
"""Should get fitered domains counts sliced by org type and election office.""" """Should get fitered domains counts sliced by org type and election office."""
with less_console_noise(): with less_console_noise():
filter_condition = { filter_condition = {
"domain__permissions__isnull": False, "domain__permissions__isnull": False,
"domain__first_ready__lte": self.end_date, "domain__first_ready__lte": self.end_date,
} }
managed_domains_sliced_at_end_date = get_sliced_domains(filter_condition) managed_domains_sliced_at_end_date = get_sliced_domains(filter_condition)
expected_content = ( expected_content = [1, 1, 0, 0, 0, 0, 0, 0, 0, 1]
[1, 1, 0, 0, 0, 0, 0, 0, 0, 1]
)
self.assertEqual(managed_domains_sliced_at_end_date, expected_content) self.assertEqual(managed_domains_sliced_at_end_date, expected_content)
def test_get_sliced_requests(self): def test_get_sliced_requests(self):
"""Should get fitered requests counts sliced by org type and election office.""" """Should get fitered requests counts sliced by org type and election office."""
with less_console_noise(): with less_console_noise():
filter_condition = { filter_condition = {
"status": DomainApplication.ApplicationStatus.SUBMITTED, "status": DomainApplication.ApplicationStatus.SUBMITTED,
"submission_date__lte": self.end_date, "submission_date__lte": self.end_date,
} }
submitted_requests_sliced_at_end_date = get_sliced_requests(filter_condition) submitted_requests_sliced_at_end_date = get_sliced_requests(filter_condition)
expected_content = ( expected_content = [2, 2, 0, 0, 0, 0, 0, 0, 0, 0]
[2, 2, 0, 0, 0, 0, 0, 0, 0, 0] self.assertEqual(submitted_requests_sliced_at_end_date, expected_content)
)
self.assertEqual(submitted_requests_sliced_at_end_date, expected_content)

View file

@ -128,6 +128,7 @@ def _get_security_emails(sec_contact_ids):
return security_emails_dict return security_emails_dict
def write_domains_csv( def write_domains_csv(
writer, writer,
columns, columns,
@ -253,7 +254,6 @@ def write_requests_csv(
logger.error("csv_export -> Error when parsing row, domain was None") logger.error("csv_export -> Error when parsing row, domain was None")
continue continue
if should_write_header: if should_write_header:
write_header(writer, columns) write_header(writer, columns)
writer.writerows(rows) writer.writerows(rows)
@ -293,7 +293,9 @@ def export_data_type_to_csv(csv_file):
Domain.State.ON_HOLD, Domain.State.ON_HOLD,
], ],
} }
write_domains_csv(writer, columns, sort_fields, filter_condition, get_domain_managers=True, should_write_header=True) write_domains_csv(
writer, columns, sort_fields, filter_condition, get_domain_managers=True, should_write_header=True
)
def export_data_full_to_csv(csv_file): def export_data_full_to_csv(csv_file):
@ -324,7 +326,9 @@ def export_data_full_to_csv(csv_file):
Domain.State.ON_HOLD, Domain.State.ON_HOLD,
], ],
} }
write_domains_csv(writer, columns, sort_fields, filter_condition, get_domain_managers=False, should_write_header=True) write_domains_csv(
writer, columns, sort_fields, filter_condition, get_domain_managers=False, should_write_header=True
)
def export_data_federal_to_csv(csv_file): def export_data_federal_to_csv(csv_file):
@ -356,7 +360,9 @@ def export_data_federal_to_csv(csv_file):
Domain.State.ON_HOLD, Domain.State.ON_HOLD,
], ],
} }
write_domains_csv(writer, columns, sort_fields, filter_condition, get_domain_managers=False, should_write_header=True) write_domains_csv(
writer, columns, sort_fields, filter_condition, get_domain_managers=False, should_write_header=True
)
def get_default_start_date(): def get_default_start_date():
@ -424,7 +430,9 @@ def export_data_domain_growth_to_csv(csv_file, start_date, end_date):
"domain__deleted__gte": start_date_formatted, "domain__deleted__gte": start_date_formatted,
} }
write_domains_csv(writer, columns, sort_fields, filter_condition, get_domain_managers=False, should_write_header=True) write_domains_csv(
writer, columns, sort_fields, filter_condition, get_domain_managers=False, should_write_header=True
)
write_domains_csv( write_domains_csv(
writer, writer,
columns, columns,
@ -442,14 +450,18 @@ def get_sliced_domains(filter_condition):
domains_count = domains.count() domains_count = domains.count()
federal = domains.filter(organization_type=DomainApplication.OrganizationChoices.FEDERAL).distinct().count() federal = domains.filter(organization_type=DomainApplication.OrganizationChoices.FEDERAL).distinct().count()
interstate = domains.filter(organization_type=DomainApplication.OrganizationChoices.INTERSTATE).count() interstate = domains.filter(organization_type=DomainApplication.OrganizationChoices.INTERSTATE).count()
state_or_territory = domains.filter( state_or_territory = (
organization_type=DomainApplication.OrganizationChoices.STATE_OR_TERRITORY domains.filter(organization_type=DomainApplication.OrganizationChoices.STATE_OR_TERRITORY).distinct().count()
).distinct().count() )
tribal = domains.filter(organization_type=DomainApplication.OrganizationChoices.TRIBAL).distinct().count() tribal = domains.filter(organization_type=DomainApplication.OrganizationChoices.TRIBAL).distinct().count()
county = domains.filter(organization_type=DomainApplication.OrganizationChoices.COUNTY).distinct().count() county = domains.filter(organization_type=DomainApplication.OrganizationChoices.COUNTY).distinct().count()
city = domains.filter(organization_type=DomainApplication.OrganizationChoices.CITY).distinct().count() city = domains.filter(organization_type=DomainApplication.OrganizationChoices.CITY).distinct().count()
special_district = domains.filter(organization_type=DomainApplication.OrganizationChoices.SPECIAL_DISTRICT).distinct().count() special_district = (
school_district = domains.filter(organization_type=DomainApplication.OrganizationChoices.SCHOOL_DISTRICT).distinct().count() domains.filter(organization_type=DomainApplication.OrganizationChoices.SPECIAL_DISTRICT).distinct().count()
)
school_district = (
domains.filter(organization_type=DomainApplication.OrganizationChoices.SCHOOL_DISTRICT).distinct().count()
)
election_board = domains.filter(is_election_board=True).distinct().count() election_board = domains.filter(is_election_board=True).distinct().count()
return [ return [
@ -473,14 +485,18 @@ def get_sliced_requests(filter_condition):
requests_count = requests.count() requests_count = requests.count()
federal = requests.filter(organization_type=DomainApplication.OrganizationChoices.FEDERAL).distinct().count() federal = requests.filter(organization_type=DomainApplication.OrganizationChoices.FEDERAL).distinct().count()
interstate = requests.filter(organization_type=DomainApplication.OrganizationChoices.INTERSTATE).distinct().count() interstate = requests.filter(organization_type=DomainApplication.OrganizationChoices.INTERSTATE).distinct().count()
state_or_territory = requests.filter( state_or_territory = (
organization_type=DomainApplication.OrganizationChoices.STATE_OR_TERRITORY requests.filter(organization_type=DomainApplication.OrganizationChoices.STATE_OR_TERRITORY).distinct().count()
).distinct().count() )
tribal = requests.filter(organization_type=DomainApplication.OrganizationChoices.TRIBAL).distinct().count() tribal = requests.filter(organization_type=DomainApplication.OrganizationChoices.TRIBAL).distinct().count()
county = requests.filter(organization_type=DomainApplication.OrganizationChoices.COUNTY).distinct().count() county = requests.filter(organization_type=DomainApplication.OrganizationChoices.COUNTY).distinct().count()
city = requests.filter(organization_type=DomainApplication.OrganizationChoices.CITY).distinct().count() city = requests.filter(organization_type=DomainApplication.OrganizationChoices.CITY).distinct().count()
special_district = requests.filter(organization_type=DomainApplication.OrganizationChoices.SPECIAL_DISTRICT).distinct().count() special_district = (
school_district = requests.filter(organization_type=DomainApplication.OrganizationChoices.SCHOOL_DISTRICT).distinct().count() requests.filter(organization_type=DomainApplication.OrganizationChoices.SPECIAL_DISTRICT).distinct().count()
)
school_district = (
requests.filter(organization_type=DomainApplication.OrganizationChoices.SCHOOL_DISTRICT).distinct().count()
)
election_board = requests.filter(is_election_board=True).distinct().count() election_board = requests.filter(is_election_board=True).distinct().count()
return [ return [