mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-16 09:37:03 +02:00
WIP unit testing
This commit is contained in:
parent
717f71f038
commit
c89d76fb47
9 changed files with 547 additions and 241 deletions
|
@ -374,8 +374,8 @@ def analytics(request):
|
||||||
avg_approval_time = last_30_days_approved_applications.annotate(
|
avg_approval_time = last_30_days_approved_applications.annotate(
|
||||||
approval_time=F("approved_domain__created_at") - F("submission_date")
|
approval_time=F("approved_domain__created_at") - F("submission_date")
|
||||||
).aggregate(Avg("approval_time"))["approval_time__avg"]
|
).aggregate(Avg("approval_time"))["approval_time__avg"]
|
||||||
# format the timedelta?
|
# Format the timedelta to display only days
|
||||||
avg_approval_time = str(avg_approval_time)
|
avg_approval_time = f"{avg_approval_time.days} days"
|
||||||
|
|
||||||
start_date = request.GET.get("start_date", "")
|
start_date = request.GET.get("start_date", "")
|
||||||
end_date = request.GET.get("end_date", "")
|
end_date = request.GET.get("end_date", "")
|
||||||
|
@ -383,75 +383,69 @@ def analytics(request):
|
||||||
start_date_formatted = csv_export.format_start_date(start_date)
|
start_date_formatted = csv_export.format_start_date(start_date)
|
||||||
end_date_formatted = csv_export.format_end_date(end_date)
|
end_date_formatted = csv_export.format_end_date(end_date)
|
||||||
|
|
||||||
# Managed vs Unmanaged
|
|
||||||
filter_managed_domains_start_date = {
|
filter_managed_domains_start_date = {
|
||||||
"domain__permissions__isnull": False,
|
"domain__permissions__isnull": False,
|
||||||
"domain__first_ready__lte": start_date_formatted,
|
"domain__first_ready__lte": start_date_formatted,
|
||||||
}
|
}
|
||||||
|
filter_managed_domains_end_date = {
|
||||||
|
"domain__permissions__isnull": False,
|
||||||
|
"domain__first_ready__lte": end_date_formatted,
|
||||||
|
}
|
||||||
managed_domains_sliced_at_start_date = csv_export.get_sliced_domains(filter_managed_domains_start_date)
|
managed_domains_sliced_at_start_date = csv_export.get_sliced_domains(filter_managed_domains_start_date)
|
||||||
|
managed_domains_sliced_at_end_date = csv_export.get_sliced_domains(filter_managed_domains_end_date)
|
||||||
|
|
||||||
filter_unmanaged_domains_start_date = {
|
filter_unmanaged_domains_start_date = {
|
||||||
"domain__permissions__isnull": True,
|
"domain__permissions__isnull": True,
|
||||||
"domain__first_ready__lte": start_date_formatted,
|
"domain__first_ready__lte": start_date_formatted,
|
||||||
}
|
}
|
||||||
unmanaged_domains_sliced_at_start_date = csv_export.get_sliced_domains(filter_unmanaged_domains_start_date)
|
|
||||||
filter_managed_domains_end_date = {
|
|
||||||
"domain__permissions__isnull": False,
|
|
||||||
"domain__first_ready__lte": end_date_formatted,
|
|
||||||
}
|
|
||||||
managed_domains_sliced_at_end_date = csv_export.get_sliced_domains(filter_managed_domains_end_date)
|
|
||||||
filter_unmanaged_domains_end_date = {
|
filter_unmanaged_domains_end_date = {
|
||||||
"domain__permissions__isnull": True,
|
"domain__permissions__isnull": True,
|
||||||
"domain__first_ready__lte": end_date_formatted,
|
"domain__first_ready__lte": end_date_formatted,
|
||||||
}
|
}
|
||||||
|
unmanaged_domains_sliced_at_start_date = csv_export.get_sliced_domains(filter_unmanaged_domains_start_date)
|
||||||
unmanaged_domains_sliced_at_end_date = csv_export.get_sliced_domains(filter_unmanaged_domains_end_date)
|
unmanaged_domains_sliced_at_end_date = csv_export.get_sliced_domains(filter_unmanaged_domains_end_date)
|
||||||
|
|
||||||
# Ready and Deleted domains
|
|
||||||
filter_ready_domains_start_date = {
|
filter_ready_domains_start_date = {
|
||||||
"domain__state__in": [Domain.State.READY],
|
"domain__state__in": [Domain.State.READY],
|
||||||
"domain__first_ready__lte": start_date_formatted,
|
"domain__first_ready__lte": start_date_formatted,
|
||||||
}
|
}
|
||||||
|
filter_ready_domains_end_date = {
|
||||||
|
"domain__state__in": [Domain.State.READY],
|
||||||
|
"domain__first_ready__lte": end_date_formatted,
|
||||||
|
}
|
||||||
ready_domains_sliced_at_start_date = csv_export.get_sliced_domains(filter_ready_domains_start_date)
|
ready_domains_sliced_at_start_date = csv_export.get_sliced_domains(filter_ready_domains_start_date)
|
||||||
|
ready_domains_sliced_at_end_date = csv_export.get_sliced_domains(filter_ready_domains_end_date)
|
||||||
|
|
||||||
filter_deleted_domains_start_date = {
|
filter_deleted_domains_start_date = {
|
||||||
"domain__state__in": [Domain.State.DELETED],
|
"domain__state__in": [Domain.State.DELETED],
|
||||||
"domain__deleted__lte": start_date_formatted,
|
"domain__deleted__lte": start_date_formatted,
|
||||||
}
|
}
|
||||||
deleted_domains_sliced_at_start_date = csv_export.get_sliced_domains(filter_deleted_domains_start_date)
|
|
||||||
|
|
||||||
filter_ready_domains_end_date = {
|
|
||||||
"domain__state__in": [Domain.State.READY],
|
|
||||||
"domain__first_ready__lte": end_date_formatted,
|
|
||||||
}
|
|
||||||
ready_domains_sliced_at_end_date = csv_export.get_sliced_domains(filter_ready_domains_end_date)
|
|
||||||
|
|
||||||
filter_deleted_domains_end_date = {
|
filter_deleted_domains_end_date = {
|
||||||
"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_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
|
||||||
filter_requests_start_date = {
|
filter_requests_start_date = {
|
||||||
"created_at__lte": start_date_formatted,
|
"created_at__lte": start_date_formatted,
|
||||||
}
|
}
|
||||||
|
filter_requests_end_date = {
|
||||||
|
"created_at__lte": end_date_formatted,
|
||||||
|
}
|
||||||
requests_sliced_at_start_date = csv_export.get_sliced_requests(filter_requests_start_date)
|
requests_sliced_at_start_date = csv_export.get_sliced_requests(filter_requests_start_date)
|
||||||
|
requests_sliced_at_end_date = csv_export.get_sliced_requests(filter_requests_end_date)
|
||||||
|
|
||||||
filter_submitted_requests_start_date = {
|
filter_submitted_requests_start_date = {
|
||||||
"status": DomainApplication.ApplicationStatus.SUBMITTED,
|
"status": DomainApplication.ApplicationStatus.SUBMITTED,
|
||||||
"submission_date__lte": start_date_formatted,
|
"submission_date__lte": start_date_formatted,
|
||||||
}
|
}
|
||||||
submitted_requests_sliced_at_start_date = csv_export.get_sliced_requests(filter_submitted_requests_start_date)
|
|
||||||
|
|
||||||
filter_requests_end_date = {
|
|
||||||
"created_at__lte": end_date_formatted,
|
|
||||||
}
|
|
||||||
requests_sliced_at_end_date = csv_export.get_sliced_requests(filter_requests_end_date)
|
|
||||||
|
|
||||||
filter_submitted_requests_end_date = {
|
filter_submitted_requests_end_date = {
|
||||||
"status": DomainApplication.ApplicationStatus.SUBMITTED,
|
"status": DomainApplication.ApplicationStatus.SUBMITTED,
|
||||||
"submission_date__lte": end_date_formatted,
|
"submission_date__lte": end_date_formatted,
|
||||||
}
|
}
|
||||||
|
submitted_requests_sliced_at_start_date = csv_export.get_sliced_requests(filter_submitted_requests_start_date)
|
||||||
submitted_requests_sliced_at_end_date = csv_export.get_sliced_requests(filter_submitted_requests_end_date)
|
submitted_requests_sliced_at_end_date = csv_export.get_sliced_requests(filter_submitted_requests_end_date)
|
||||||
|
|
||||||
context = dict(
|
context = dict(
|
||||||
|
@ -459,6 +453,7 @@ def analytics(request):
|
||||||
data=dict(
|
data=dict(
|
||||||
user_count=models.User.objects.all().count(),
|
user_count=models.User.objects.all().count(),
|
||||||
domain_count=models.Domain.objects.all().count(),
|
domain_count=models.Domain.objects.all().count(),
|
||||||
|
ready_domain_count=models.Domain.objects.all().filter(state=models.Domain.State.READY).count(),
|
||||||
last_30_days_applications=last_30_days_applications.count(),
|
last_30_days_applications=last_30_days_applications.count(),
|
||||||
last_30_days_approved_applications=last_30_days_approved_applications.count(),
|
last_30_days_approved_applications=last_30_days_approved_applications.count(),
|
||||||
average_application_approval_time_last_30_days=avg_approval_time,
|
average_application_approval_time_last_30_days=avg_approval_time,
|
||||||
|
@ -1096,7 +1091,7 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
||||||
search_help_text = "Search by domain or submitter."
|
search_help_text = "Search by domain or submitter."
|
||||||
|
|
||||||
fieldsets = [
|
fieldsets = [
|
||||||
(None, {"fields": ["status", "rejection_reason", "investigator", "creator", "approved_domain", "notes"]}),
|
(None, {"fields": ["status", "rejection_reason", "submission_date", "investigator", "creator", "approved_domain", "notes"]}),
|
||||||
(
|
(
|
||||||
"Type of organization",
|
"Type of organization",
|
||||||
{
|
{
|
||||||
|
@ -1448,7 +1443,7 @@ class DomainAdmin(ListHeaderAdmin):
|
||||||
search_fields = ["name"]
|
search_fields = ["name"]
|
||||||
search_help_text = "Search by domain name."
|
search_help_text = "Search by domain name."
|
||||||
change_form_template = "django/admin/domain_change_form.html"
|
change_form_template = "django/admin/domain_change_form.html"
|
||||||
readonly_fields = ["state", "expiration_date", "first_ready", "deleted"]
|
readonly_fields = ["state", "expiration_date", "deleted"]
|
||||||
|
|
||||||
# Table ordering
|
# Table ordering
|
||||||
ordering = ["name"]
|
ordering = ["name"]
|
||||||
|
|
|
@ -319,6 +319,9 @@ input.admin-confirm-button {
|
||||||
.usa-icon {
|
.usa-icon {
|
||||||
top: 2px;
|
top: 2px;
|
||||||
}
|
}
|
||||||
|
a.button:active, a.button:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.module--custom {
|
.module--custom {
|
||||||
|
|
|
@ -1022,7 +1022,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
|
|
||||||
first_ready = DateField(
|
first_ready = DateField(
|
||||||
null=True,
|
null=True,
|
||||||
editable=False,
|
editable=True,
|
||||||
help_text="The last time this domain moved into the READY state",
|
help_text="The last time this domain moved into the READY state",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li>User Count: {{ data.user_count }}</li>
|
<li>User Count: {{ data.user_count }}</li>
|
||||||
<li>Domain Count: {{ data.domain_count }}</li>
|
<li>Domain Count: {{ data.domain_count }}</li>
|
||||||
|
<li>Domains in READY state: {{ data.ready_domain_count }}</li>
|
||||||
<li>Domain applications (last 30 days): {{ data.last_30_days_applications }}</li>
|
<li>Domain applications (last 30 days): {{ data.last_30_days_applications }}</li>
|
||||||
<li>Approved applications (last 30 days): {{ data.last_30_days_approved_applications }}</li>
|
<li>Approved applications (last 30 days): {{ data.last_30_days_approved_applications }}</li>
|
||||||
<li>Average approval time for applications (last 30 days): {{ data.average_application_approval_time_last_30_days }}</li>
|
<li>Average approval time for applications (last 30 days): {{ data.average_application_approval_time_last_30_days }}</li>
|
||||||
|
@ -63,8 +64,6 @@
|
||||||
{% comment %}
|
{% comment %}
|
||||||
Inputs of type date suck for accessibility.
|
Inputs of type date suck for accessibility.
|
||||||
We'll need to replace those guys with a django form once we figure out how to hook one onto this page.
|
We'll need to replace those guys with a django form once we figure out how to hook one onto this page.
|
||||||
The challenge is in the path definition in urls. It does NOT like admin/export_domain_growth/
|
|
||||||
|
|
||||||
See the commit "Review for ticket #999"
|
See the commit "Review for ticket #999"
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
<div class="display-flex flex-align-baseline margin-top-1 margin-bottom-2">
|
<div class="display-flex flex-align-baseline margin-top-1 margin-bottom-2">
|
||||||
|
@ -107,7 +106,7 @@
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="usa-button-group__item">
|
<li class="usa-button-group__item">
|
||||||
<button class="button exportLink" data-export-url="{% url 'analytics' %}" type="button">
|
<button class="button exportLink usa-button--accent-cool" data-export-url="{% url 'analytics' %}" type="button">
|
||||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24" height="24">
|
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24" height="24">
|
||||||
<use xlink:href="{%static 'img/sprite.svg'%}#assessment"></use>
|
<use xlink:href="{%static 'img/sprite.svg'%}#assessment"></use>
|
||||||
</svg><span class="margin-left-05">Update charts</span>
|
</svg><span class="margin-left-05">Update charts</span>
|
||||||
|
@ -116,18 +115,18 @@
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="grid-row grid-gap-2 margin-y-2">
|
<div class="grid-row grid-gap-2 margin-y-2">
|
||||||
<div class="grid-col">
|
|
||||||
<canvas id="myChart" width="400" height="200"
|
|
||||||
data-list-one="{{data.unmanaged_domains_sliced_at_start_date}}"
|
|
||||||
data-list-two="{{data.unmanaged_domains_sliced_at_end_date}}"
|
|
||||||
></canvas>
|
|
||||||
</div>
|
|
||||||
<div class="grid-col">
|
<div class="grid-col">
|
||||||
<canvas id="myChart2" width="400" height="200"
|
<canvas id="myChart2" width="400" height="200"
|
||||||
data-list-one="{{data.managed_domains_sliced_at_start_date}}"
|
data-list-one="{{data.managed_domains_sliced_at_start_date}}"
|
||||||
data-list-two="{{data.managed_domains_sliced_at_end_date}}"
|
data-list-two="{{data.managed_domains_sliced_at_end_date}}"
|
||||||
></canvas>
|
></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grid-col">
|
||||||
|
<canvas id="myChart" width="400" height="200"
|
||||||
|
data-list-one="{{data.unmanaged_domains_sliced_at_start_date}}"
|
||||||
|
data-list-two="{{data.unmanaged_domains_sliced_at_end_date}}"
|
||||||
|
></canvas>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid-row grid-gap-2 margin-y-2">
|
<div class="grid-row grid-gap-2 margin-y-2">
|
||||||
|
|
|
@ -71,5 +71,5 @@
|
||||||
|
|
||||||
<div class="module module--custom">
|
<div class="module module--custom">
|
||||||
<h2>Analytics</h2>
|
<h2>Analytics</h2>
|
||||||
<a class="display-block padding-y-1 padding-x-2" href="{% url 'analytics' %}">Dashboard</a>
|
<a class="display-block padding-y-1 padding-x-1" href="{% url 'analytics' %}">Dashboard</a>
|
||||||
</div>
|
</div>
|
232
src/registrar/tests/data/mocks.py
Normal file
232
src/registrar/tests/data/mocks.py
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from registrar.models.domain_application import DomainApplication
|
||||||
|
from registrar.models.domain_information import DomainInformation
|
||||||
|
from registrar.models.domain import Domain
|
||||||
|
from registrar.models.user_domain_role import UserDomainRole
|
||||||
|
from registrar.models.public_contact import PublicContact
|
||||||
|
from registrar.models.user import User
|
||||||
|
from datetime import date, datetime, timedelta
|
||||||
|
from django.utils import timezone
|
||||||
|
from registrar.tests.common import MockEppLib
|
||||||
|
|
||||||
|
class MockDb(MockEppLib):
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
username = "test_user"
|
||||||
|
first_name = "First"
|
||||||
|
last_name = "Last"
|
||||||
|
email = "info@example.com"
|
||||||
|
self.user = get_user_model().objects.create(
|
||||||
|
username=username, first_name=first_name, last_name=last_name, email=email
|
||||||
|
)
|
||||||
|
|
||||||
|
self.domain_1, _ = Domain.objects.get_or_create(
|
||||||
|
name="cdomain1.gov", state=Domain.State.READY, first_ready=timezone.now()
|
||||||
|
)
|
||||||
|
self.domain_2, _ = Domain.objects.get_or_create(name="adomain2.gov", state=Domain.State.DNS_NEEDED)
|
||||||
|
self.domain_3, _ = Domain.objects.get_or_create(name="ddomain3.gov", state=Domain.State.ON_HOLD)
|
||||||
|
self.domain_4, _ = Domain.objects.get_or_create(name="bdomain4.gov", state=Domain.State.UNKNOWN)
|
||||||
|
self.domain_4, _ = Domain.objects.get_or_create(name="bdomain4.gov", state=Domain.State.UNKNOWN)
|
||||||
|
self.domain_5, _ = Domain.objects.get_or_create(
|
||||||
|
name="bdomain5.gov", state=Domain.State.DELETED, deleted=timezone.make_aware(datetime(2023, 11, 1))
|
||||||
|
)
|
||||||
|
self.domain_6, _ = Domain.objects.get_or_create(
|
||||||
|
name="bdomain6.gov", state=Domain.State.DELETED, deleted=timezone.make_aware(datetime(1980, 10, 16))
|
||||||
|
)
|
||||||
|
self.domain_7, _ = Domain.objects.get_or_create(
|
||||||
|
name="xdomain7.gov", state=Domain.State.DELETED, deleted=timezone.now()
|
||||||
|
)
|
||||||
|
self.domain_8, _ = Domain.objects.get_or_create(
|
||||||
|
name="sdomain8.gov", state=Domain.State.DELETED, deleted=timezone.now()
|
||||||
|
)
|
||||||
|
# We use timezone.make_aware to sync to server time a datetime object with the current date (using date.today())
|
||||||
|
# and a specific time (using datetime.min.time()).
|
||||||
|
# Deleted yesterday
|
||||||
|
self.domain_9, _ = Domain.objects.get_or_create(
|
||||||
|
name="zdomain9.gov",
|
||||||
|
state=Domain.State.DELETED,
|
||||||
|
deleted=timezone.make_aware(datetime.combine(date.today() - timedelta(days=1), datetime.min.time())),
|
||||||
|
)
|
||||||
|
# ready tomorrow
|
||||||
|
self.domain_10, _ = Domain.objects.get_or_create(
|
||||||
|
name="adomain10.gov",
|
||||||
|
state=Domain.State.READY,
|
||||||
|
first_ready=timezone.make_aware(datetime.combine(date.today() + timedelta(days=1), datetime.min.time())),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.domain_information_1, _ = DomainInformation.objects.get_or_create(
|
||||||
|
creator=self.user,
|
||||||
|
domain=self.domain_1,
|
||||||
|
organization_type="federal",
|
||||||
|
federal_agency="World War I Centennial Commission",
|
||||||
|
federal_type="executive",
|
||||||
|
is_election_board=True
|
||||||
|
)
|
||||||
|
self.domain_information_2, _ = DomainInformation.objects.get_or_create(
|
||||||
|
creator=self.user,
|
||||||
|
domain=self.domain_2,
|
||||||
|
organization_type="interstate",
|
||||||
|
is_election_board=True
|
||||||
|
)
|
||||||
|
self.domain_information_3, _ = DomainInformation.objects.get_or_create(
|
||||||
|
creator=self.user,
|
||||||
|
domain=self.domain_3,
|
||||||
|
organization_type="federal",
|
||||||
|
federal_agency="Armed Forces Retirement Home",
|
||||||
|
is_election_board=True
|
||||||
|
)
|
||||||
|
self.domain_information_4, _ = DomainInformation.objects.get_or_create(
|
||||||
|
creator=self.user,
|
||||||
|
domain=self.domain_4,
|
||||||
|
organization_type="federal",
|
||||||
|
federal_agency="Armed Forces Retirement Home",
|
||||||
|
is_election_board=True
|
||||||
|
)
|
||||||
|
self.domain_information_5, _ = DomainInformation.objects.get_or_create(
|
||||||
|
creator=self.user,
|
||||||
|
domain=self.domain_5,
|
||||||
|
organization_type="federal",
|
||||||
|
federal_agency="Armed Forces Retirement Home",
|
||||||
|
is_election_board=False
|
||||||
|
)
|
||||||
|
self.domain_information_6, _ = DomainInformation.objects.get_or_create(
|
||||||
|
creator=self.user,
|
||||||
|
domain=self.domain_6,
|
||||||
|
organization_type="federal",
|
||||||
|
federal_agency="Armed Forces Retirement Home",
|
||||||
|
is_election_board=False
|
||||||
|
)
|
||||||
|
self.domain_information_7, _ = DomainInformation.objects.get_or_create(
|
||||||
|
creator=self.user,
|
||||||
|
domain=self.domain_7,
|
||||||
|
organization_type="federal",
|
||||||
|
federal_agency="Armed Forces Retirement Home",
|
||||||
|
is_election_board=False
|
||||||
|
)
|
||||||
|
self.domain_information_8, _ = DomainInformation.objects.get_or_create(
|
||||||
|
creator=self.user,
|
||||||
|
domain=self.domain_8,
|
||||||
|
organization_type="federal",
|
||||||
|
federal_agency="Armed Forces Retirement Home",
|
||||||
|
is_election_board=False
|
||||||
|
)
|
||||||
|
self.domain_information_9, _ = DomainInformation.objects.get_or_create(
|
||||||
|
creator=self.user,
|
||||||
|
domain=self.domain_9,
|
||||||
|
organization_type="federal",
|
||||||
|
federal_agency="Armed Forces Retirement Home",
|
||||||
|
is_election_board=False
|
||||||
|
)
|
||||||
|
self.domain_information_10, _ = DomainInformation.objects.get_or_create(
|
||||||
|
creator=self.user,
|
||||||
|
domain=self.domain_10,
|
||||||
|
organization_type="federal",
|
||||||
|
federal_agency="Armed Forces Retirement Home",
|
||||||
|
is_election_board=False
|
||||||
|
)
|
||||||
|
|
||||||
|
meoward_user = get_user_model().objects.create(
|
||||||
|
username="meoward_username", first_name="first_meoward", last_name="last_meoward", email="meoward@rocks.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
lebowski_user = get_user_model().objects.create(
|
||||||
|
username="big_lebowski", first_name="big", last_name="lebowski", email="big_lebowski@dude.co"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test for more than 1 domain manager
|
||||||
|
_, created = UserDomainRole.objects.get_or_create(
|
||||||
|
user=meoward_user, domain=self.domain_1, role=UserDomainRole.Roles.MANAGER
|
||||||
|
)
|
||||||
|
|
||||||
|
_, created = UserDomainRole.objects.get_or_create(
|
||||||
|
user=self.user, domain=self.domain_1, role=UserDomainRole.Roles.MANAGER
|
||||||
|
)
|
||||||
|
|
||||||
|
_, created = UserDomainRole.objects.get_or_create(
|
||||||
|
user=lebowski_user, domain=self.domain_1, role=UserDomainRole.Roles.MANAGER
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test for just 1 domain manager
|
||||||
|
_, created = UserDomainRole.objects.get_or_create(
|
||||||
|
user=meoward_user, domain=self.domain_2, role=UserDomainRole.Roles.MANAGER
|
||||||
|
)
|
||||||
|
|
||||||
|
# self.domain_request_1, _ = DomainApplication.objects.get_or_create(
|
||||||
|
# creator=self.user,
|
||||||
|
# requested_domain=self.domain_1.name,
|
||||||
|
# organization_type="federal",
|
||||||
|
# federal_agency="World War I Centennial Commission",
|
||||||
|
# federal_type="executive",
|
||||||
|
# is_election_board=True
|
||||||
|
# )
|
||||||
|
# self.domain_request_2, _ = DomainApplication.objects.get_or_create(
|
||||||
|
# creator=self.user,
|
||||||
|
# domain=self.domain_2,
|
||||||
|
# organization_type="interstate",
|
||||||
|
# is_election_board=True
|
||||||
|
# )
|
||||||
|
# self.domain_request_3, _ = DomainApplication.objects.get_or_create(
|
||||||
|
# creator=self.user,
|
||||||
|
# domain=self.domain_3,
|
||||||
|
# organization_type="federal",
|
||||||
|
# federal_agency="Armed Forces Retirement Home",
|
||||||
|
# is_election_board=True
|
||||||
|
# )
|
||||||
|
# self.domain_request_4, _ = DomainApplication.objects.get_or_create(
|
||||||
|
# creator=self.user,
|
||||||
|
# domain=self.domain_4,
|
||||||
|
# organization_type="federal",
|
||||||
|
# federal_agency="Armed Forces Retirement Home",
|
||||||
|
# is_election_board=True
|
||||||
|
# )
|
||||||
|
# self.domain_request_5, _ = DomainApplication.objects.get_or_create(
|
||||||
|
# creator=self.user,
|
||||||
|
# domain=self.domain_5,
|
||||||
|
# organization_type="federal",
|
||||||
|
# federal_agency="Armed Forces Retirement Home",
|
||||||
|
# is_election_board=False
|
||||||
|
# )
|
||||||
|
# self.domain_request_6, _ = DomainApplication.objects.get_or_create(
|
||||||
|
# creator=self.user,
|
||||||
|
# domain=self.domain_6,
|
||||||
|
# organization_type="federal",
|
||||||
|
# federal_agency="Armed Forces Retirement Home",
|
||||||
|
# is_election_board=False
|
||||||
|
# )
|
||||||
|
# self.domain_request_7, _ = DomainApplication.objects.get_or_create(
|
||||||
|
# creator=self.user,
|
||||||
|
# domain=self.domain_7,
|
||||||
|
# organization_type="federal",
|
||||||
|
# federal_agency="Armed Forces Retirement Home",
|
||||||
|
# is_election_board=False
|
||||||
|
# )
|
||||||
|
# self.domain_request_8, _ = DomainApplication.objects.get_or_create(
|
||||||
|
# creator=self.user,
|
||||||
|
# domain=self.domain_8,
|
||||||
|
# organization_type="federal",
|
||||||
|
# federal_agency="Armed Forces Retirement Home",
|
||||||
|
# is_election_board=False
|
||||||
|
# )
|
||||||
|
# self.domain_information_9, _ = DomainApplication.objects.get_or_create(
|
||||||
|
# creator=self.user,
|
||||||
|
# domain=self.domain_9,
|
||||||
|
# organization_type="federal",
|
||||||
|
# federal_agency="Armed Forces Retirement Home",
|
||||||
|
# is_election_board=False
|
||||||
|
# )
|
||||||
|
# self.domain_information_10, _ = DomainApplication.objects.get_or_create(
|
||||||
|
# creator=self.user,
|
||||||
|
# domain=self.domain_10,
|
||||||
|
# organization_type="federal",
|
||||||
|
# federal_agency="Armed Forces Retirement Home",
|
||||||
|
# is_election_board=False
|
||||||
|
# )
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
PublicContact.objects.all().delete()
|
||||||
|
Domain.objects.all().delete()
|
||||||
|
DomainInformation.objects.all().delete()
|
||||||
|
User.objects.all().delete()
|
||||||
|
UserDomainRole.objects.all().delete()
|
||||||
|
super().tearDown()
|
|
@ -3,7 +3,7 @@ from django.urls import reverse
|
||||||
from registrar.tests.common import create_superuser
|
from registrar.tests.common import create_superuser
|
||||||
|
|
||||||
|
|
||||||
class TestViews(TestCase):
|
class TestAdminViews(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.client = Client(HTTP_HOST="localhost:8080")
|
self.client = Client(HTTP_HOST="localhost:8080")
|
||||||
self.superuser = create_superuser()
|
self.superuser = create_superuser()
|
||||||
|
@ -26,7 +26,7 @@ class TestViews(TestCase):
|
||||||
|
|
||||||
# Construct the URL for the export data view with start_date and end_date parameters:
|
# Construct the URL for the export data view with start_date and end_date parameters:
|
||||||
# This stuff is currently done in JS
|
# This stuff is currently done in JS
|
||||||
export_data_url = reverse("admin:admin_export_domain_growth") + f"?start_date={start_date}&end_date={end_date}"
|
export_data_url = reverse("export_domains_growth") + f"?start_date={start_date}&end_date={end_date}"
|
||||||
|
|
||||||
# Make a GET request to the export data page
|
# Make a GET request to the export data page
|
||||||
response = self.client.get(export_data_url)
|
response = self.client.get(export_data_url)
|
||||||
|
|
|
@ -8,9 +8,12 @@ from registrar.models.public_contact import PublicContact
|
||||||
from registrar.models.user import User
|
from registrar.models.user import User
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from registrar.models.user_domain_role import UserDomainRole
|
from registrar.models.user_domain_role import UserDomainRole
|
||||||
from registrar.tests.common import MockEppLib
|
from registrar.tests.data.mocks import MockDb
|
||||||
from registrar.utility.csv_export import (
|
from registrar.utility.csv_export import (
|
||||||
write_csv,
|
format_end_date,
|
||||||
|
format_start_date,
|
||||||
|
get_sliced_domains,
|
||||||
|
write_domains_csv,
|
||||||
get_default_start_date,
|
get_default_start_date,
|
||||||
get_default_end_date,
|
get_default_end_date,
|
||||||
)
|
)
|
||||||
|
@ -231,136 +234,11 @@ class CsvReportsTest(TestCase):
|
||||||
self.assertEqual(expected_file_content, response.content)
|
self.assertEqual(expected_file_content, response.content)
|
||||||
|
|
||||||
|
|
||||||
class ExportDataTest(MockEppLib):
|
class ExportDataTest(MockDb):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
username = "test_user"
|
|
||||||
first_name = "First"
|
|
||||||
last_name = "Last"
|
|
||||||
email = "info@example.com"
|
|
||||||
self.user = get_user_model().objects.create(
|
|
||||||
username=username, first_name=first_name, last_name=last_name, email=email
|
|
||||||
)
|
|
||||||
|
|
||||||
self.domain_1, _ = Domain.objects.get_or_create(
|
|
||||||
name="cdomain1.gov", state=Domain.State.READY, first_ready=timezone.now()
|
|
||||||
)
|
|
||||||
self.domain_2, _ = Domain.objects.get_or_create(name="adomain2.gov", state=Domain.State.DNS_NEEDED)
|
|
||||||
self.domain_3, _ = Domain.objects.get_or_create(name="ddomain3.gov", state=Domain.State.ON_HOLD)
|
|
||||||
self.domain_4, _ = Domain.objects.get_or_create(name="bdomain4.gov", state=Domain.State.UNKNOWN)
|
|
||||||
self.domain_4, _ = Domain.objects.get_or_create(name="bdomain4.gov", state=Domain.State.UNKNOWN)
|
|
||||||
self.domain_5, _ = Domain.objects.get_or_create(
|
|
||||||
name="bdomain5.gov", state=Domain.State.DELETED, deleted=timezone.make_aware(datetime(2023, 11, 1))
|
|
||||||
)
|
|
||||||
self.domain_6, _ = Domain.objects.get_or_create(
|
|
||||||
name="bdomain6.gov", state=Domain.State.DELETED, deleted=timezone.make_aware(datetime(1980, 10, 16))
|
|
||||||
)
|
|
||||||
self.domain_7, _ = Domain.objects.get_or_create(
|
|
||||||
name="xdomain7.gov", state=Domain.State.DELETED, deleted=timezone.now()
|
|
||||||
)
|
|
||||||
self.domain_8, _ = Domain.objects.get_or_create(
|
|
||||||
name="sdomain8.gov", state=Domain.State.DELETED, deleted=timezone.now()
|
|
||||||
)
|
|
||||||
# We use timezone.make_aware to sync to server time a datetime object with the current date (using date.today())
|
|
||||||
# and a specific time (using datetime.min.time()).
|
|
||||||
# Deleted yesterday
|
|
||||||
self.domain_9, _ = Domain.objects.get_or_create(
|
|
||||||
name="zdomain9.gov",
|
|
||||||
state=Domain.State.DELETED,
|
|
||||||
deleted=timezone.make_aware(datetime.combine(date.today() - timedelta(days=1), datetime.min.time())),
|
|
||||||
)
|
|
||||||
# ready tomorrow
|
|
||||||
self.domain_10, _ = Domain.objects.get_or_create(
|
|
||||||
name="adomain10.gov",
|
|
||||||
state=Domain.State.READY,
|
|
||||||
first_ready=timezone.make_aware(datetime.combine(date.today() + timedelta(days=1), datetime.min.time())),
|
|
||||||
)
|
|
||||||
|
|
||||||
self.domain_information_1, _ = DomainInformation.objects.get_or_create(
|
|
||||||
creator=self.user,
|
|
||||||
domain=self.domain_1,
|
|
||||||
organization_type="federal",
|
|
||||||
federal_agency="World War I Centennial Commission",
|
|
||||||
federal_type="executive",
|
|
||||||
)
|
|
||||||
self.domain_information_2, _ = DomainInformation.objects.get_or_create(
|
|
||||||
creator=self.user,
|
|
||||||
domain=self.domain_2,
|
|
||||||
organization_type="interstate",
|
|
||||||
)
|
|
||||||
self.domain_information_3, _ = DomainInformation.objects.get_or_create(
|
|
||||||
creator=self.user,
|
|
||||||
domain=self.domain_3,
|
|
||||||
organization_type="federal",
|
|
||||||
federal_agency="Armed Forces Retirement Home",
|
|
||||||
)
|
|
||||||
self.domain_information_4, _ = DomainInformation.objects.get_or_create(
|
|
||||||
creator=self.user,
|
|
||||||
domain=self.domain_4,
|
|
||||||
organization_type="federal",
|
|
||||||
federal_agency="Armed Forces Retirement Home",
|
|
||||||
)
|
|
||||||
self.domain_information_5, _ = DomainInformation.objects.get_or_create(
|
|
||||||
creator=self.user,
|
|
||||||
domain=self.domain_5,
|
|
||||||
organization_type="federal",
|
|
||||||
federal_agency="Armed Forces Retirement Home",
|
|
||||||
)
|
|
||||||
self.domain_information_6, _ = DomainInformation.objects.get_or_create(
|
|
||||||
creator=self.user,
|
|
||||||
domain=self.domain_6,
|
|
||||||
organization_type="federal",
|
|
||||||
federal_agency="Armed Forces Retirement Home",
|
|
||||||
)
|
|
||||||
self.domain_information_7, _ = DomainInformation.objects.get_or_create(
|
|
||||||
creator=self.user,
|
|
||||||
domain=self.domain_7,
|
|
||||||
organization_type="federal",
|
|
||||||
federal_agency="Armed Forces Retirement Home",
|
|
||||||
)
|
|
||||||
self.domain_information_8, _ = DomainInformation.objects.get_or_create(
|
|
||||||
creator=self.user,
|
|
||||||
domain=self.domain_8,
|
|
||||||
organization_type="federal",
|
|
||||||
federal_agency="Armed Forces Retirement Home",
|
|
||||||
)
|
|
||||||
self.domain_information_9, _ = DomainInformation.objects.get_or_create(
|
|
||||||
creator=self.user,
|
|
||||||
domain=self.domain_9,
|
|
||||||
organization_type="federal",
|
|
||||||
federal_agency="Armed Forces Retirement Home",
|
|
||||||
)
|
|
||||||
self.domain_information_10, _ = DomainInformation.objects.get_or_create(
|
|
||||||
creator=self.user,
|
|
||||||
domain=self.domain_10,
|
|
||||||
organization_type="federal",
|
|
||||||
federal_agency="Armed Forces Retirement Home",
|
|
||||||
)
|
|
||||||
|
|
||||||
meoward_user = get_user_model().objects.create(
|
|
||||||
username="meoward_username", first_name="first_meoward", last_name="last_meoward", email="meoward@rocks.com"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test for more than 1 domain manager
|
|
||||||
_, created = UserDomainRole.objects.get_or_create(
|
|
||||||
user=meoward_user, domain=self.domain_1, role=UserDomainRole.Roles.MANAGER
|
|
||||||
)
|
|
||||||
|
|
||||||
_, created = UserDomainRole.objects.get_or_create(
|
|
||||||
user=self.user, domain=self.domain_1, role=UserDomainRole.Roles.MANAGER
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test for just 1 domain manager
|
|
||||||
_, created = UserDomainRole.objects.get_or_create(
|
|
||||||
user=meoward_user, domain=self.domain_2, role=UserDomainRole.Roles.MANAGER
|
|
||||||
)
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
PublicContact.objects.all().delete()
|
|
||||||
Domain.objects.all().delete()
|
|
||||||
DomainInformation.objects.all().delete()
|
|
||||||
User.objects.all().delete()
|
|
||||||
UserDomainRole.objects.all().delete()
|
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
|
|
||||||
def test_export_domains_to_writer_security_emails(self):
|
def test_export_domains_to_writer_security_emails(self):
|
||||||
|
@ -403,7 +281,7 @@ class ExportDataTest(MockEppLib):
|
||||||
}
|
}
|
||||||
self.maxDiff = None
|
self.maxDiff = None
|
||||||
# Call the export functions
|
# Call the export functions
|
||||||
write_csv(
|
write_domains_csv(
|
||||||
writer, columns, sort_fields, filter_condition, get_domain_managers=False, should_write_header=True
|
writer, columns, sort_fields, filter_condition, get_domain_managers=False, should_write_header=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -427,7 +305,7 @@ class ExportDataTest(MockEppLib):
|
||||||
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_csv(self):
|
def test_write_domains_csv(self):
|
||||||
"""Test that write_body returns the
|
"""Test that write_body returns the
|
||||||
existing domain, test that sort by domain name works,
|
existing domain, test that sort by domain name works,
|
||||||
test that filter works"""
|
test that filter works"""
|
||||||
|
@ -462,7 +340,7 @@ class ExportDataTest(MockEppLib):
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
# Call the export functions
|
# Call the export functions
|
||||||
write_csv(
|
write_domains_csv(
|
||||||
writer, columns, sort_fields, filter_condition, get_domain_managers=False, should_write_header=True
|
writer, columns, sort_fields, filter_condition, get_domain_managers=False, should_write_header=True
|
||||||
)
|
)
|
||||||
# Reset the CSV file's position to the beginning
|
# Reset the CSV file's position to the beginning
|
||||||
|
@ -486,7 +364,7 @@ class ExportDataTest(MockEppLib):
|
||||||
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_body_additional(self):
|
def test_write_domains_body_additional(self):
|
||||||
"""An additional test for filters and multi-column sort"""
|
"""An additional test for filters and multi-column sort"""
|
||||||
with less_console_noise():
|
with less_console_noise():
|
||||||
# Create a CSV file in memory
|
# Create a CSV file in memory
|
||||||
|
@ -512,7 +390,7 @@ class ExportDataTest(MockEppLib):
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
# Call the export functions
|
# Call the export functions
|
||||||
write_csv(
|
write_domains_csv(
|
||||||
writer, columns, sort_fields, filter_condition, get_domain_managers=False, should_write_header=True
|
writer, columns, sort_fields, filter_condition, get_domain_managers=False, should_write_header=True
|
||||||
)
|
)
|
||||||
# Reset the CSV file's position to the beginning
|
# Reset the CSV file's position to the beginning
|
||||||
|
@ -535,7 +413,7 @@ class ExportDataTest(MockEppLib):
|
||||||
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_body_with_date_filter_pulls_domains_in_range(self):
|
def test_write_domains_body_with_date_filter_pulls_domains_in_range(self):
|
||||||
"""Test that domains that are
|
"""Test that domains that are
|
||||||
1. READY and their first_ready dates are in range
|
1. READY and their first_ready dates are in range
|
||||||
2. DELETED and their deleted dates are in range
|
2. DELETED and their deleted dates are in range
|
||||||
|
@ -546,7 +424,7 @@ class ExportDataTest(MockEppLib):
|
||||||
and would have been easy to set up, but expected_content would contain created_at dates
|
and would have been easy to set up, but expected_content would contain created_at dates
|
||||||
which are hard to mock.
|
which are hard to mock.
|
||||||
|
|
||||||
TODO: Simplify is created_at is not needed for the report."""
|
TODO: Simplify if created_at is not needed for the report."""
|
||||||
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()
|
||||||
|
@ -591,7 +469,7 @@ class ExportDataTest(MockEppLib):
|
||||||
}
|
}
|
||||||
|
|
||||||
# Call the export functions
|
# Call the export functions
|
||||||
write_csv(
|
write_domains_csv(
|
||||||
writer,
|
writer,
|
||||||
columns,
|
columns,
|
||||||
sort_fields,
|
sort_fields,
|
||||||
|
@ -599,7 +477,7 @@ class ExportDataTest(MockEppLib):
|
||||||
get_domain_managers=False,
|
get_domain_managers=False,
|
||||||
should_write_header=True,
|
should_write_header=True,
|
||||||
)
|
)
|
||||||
write_csv(
|
write_domains_csv(
|
||||||
writer,
|
writer,
|
||||||
columns,
|
columns,
|
||||||
sort_fields_for_deleted_domains,
|
sort_fields_for_deleted_domains,
|
||||||
|
@ -664,7 +542,7 @@ class ExportDataTest(MockEppLib):
|
||||||
}
|
}
|
||||||
self.maxDiff = None
|
self.maxDiff = None
|
||||||
# Call the export functions
|
# Call the export functions
|
||||||
write_csv(
|
write_domains_csv(
|
||||||
writer, columns, sort_fields, filter_condition, get_domain_managers=True, should_write_header=True
|
writer, columns, sort_fields, filter_condition, get_domain_managers=True, should_write_header=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -677,11 +555,11 @@ class ExportDataTest(MockEppLib):
|
||||||
expected_content = (
|
expected_content = (
|
||||||
"Domain name,Status,Expiration date,Domain type,Agency,"
|
"Domain name,Status,Expiration date,Domain type,Agency,"
|
||||||
"Organization name,City,State,AO,AO email,"
|
"Organization name,City,State,AO,AO email,"
|
||||||
"Security contact email,Domain manager email 1,Domain manager email 2,\n"
|
"Security contact email,Domain manager email 1,Domain manager email 2,Domain manager email 3\n"
|
||||||
"adomain10.gov,Ready,,Federal,Armed Forces Retirement Home,,,, , ,\n"
|
"adomain10.gov,Ready,,Federal,Armed Forces Retirement Home,,,, , ,\n"
|
||||||
"adomain2.gov,Dns needed,,Interstate,,,,, , , ,meoward@rocks.com\n"
|
"adomain2.gov,Dns needed,,Interstate,,,,, , , ,meoward@rocks.com\n"
|
||||||
"cdomain1.gov,Ready,,Federal - Executive,World War I Centennial Commission,,,"
|
"cdomain1.gov,Ready,,Federal - Executive,World War I Centennial Commission,,,"
|
||||||
", , , ,meoward@rocks.com,info@example.com\n"
|
", , , ,meoward@rocks.com,info@example.com,big_lebowski@dude.co\n"
|
||||||
"ddomain3.gov,On hold,,Federal,Armed Forces Retirement Home,,,, , , ,,\n"
|
"ddomain3.gov,On hold,,Federal,Armed Forces Retirement Home,,,, , , ,,\n"
|
||||||
)
|
)
|
||||||
# Normalize line endings and remove commas,
|
# Normalize line endings and remove commas,
|
||||||
|
@ -690,6 +568,210 @@ class ExportDataTest(MockEppLib):
|
||||||
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_managed_domains_to_csv(self):
|
||||||
|
""""""
|
||||||
|
with less_console_noise():
|
||||||
|
# Create a CSV file in memory
|
||||||
|
csv_file = StringIO()
|
||||||
|
writer = csv.writer(csv_file)
|
||||||
|
end_date = timezone.make_aware(datetime.combine(date.today() + timedelta(days=2), datetime.min.time()))
|
||||||
|
start_date = timezone.make_aware(datetime.combine(date.today() - timedelta(days=2), datetime.min.time()))
|
||||||
|
# Define columns, sort fields, and filter condition
|
||||||
|
columns = [
|
||||||
|
"Domain name",
|
||||||
|
"Domain type",
|
||||||
|
]
|
||||||
|
sort_fields = [
|
||||||
|
"domain__name",
|
||||||
|
]
|
||||||
|
filter_managed_domains_start_date = {
|
||||||
|
"domain__permissions__isnull": False,
|
||||||
|
"domain__first_ready__lte": start_date,
|
||||||
|
}
|
||||||
|
managed_domains_sliced_at_start_date = get_sliced_domains(filter_managed_domains_start_date)
|
||||||
|
# Call the export functions
|
||||||
|
writer.writerow(["MANAGED DOMAINS COUNTS AT START DATE"])
|
||||||
|
writer.writerow(
|
||||||
|
[
|
||||||
|
"Total",
|
||||||
|
"Federal",
|
||||||
|
"Interstate",
|
||||||
|
"State or territory",
|
||||||
|
"Tribal",
|
||||||
|
"County",
|
||||||
|
"City",
|
||||||
|
"Special district",
|
||||||
|
"School district",
|
||||||
|
"Election office",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
writer.writerow(managed_domains_sliced_at_start_date)
|
||||||
|
writer.writerow([])
|
||||||
|
|
||||||
|
filter_managed_domains_end_date = {
|
||||||
|
"domain__permissions__isnull": False,
|
||||||
|
"domain__first_ready__lte": end_date,
|
||||||
|
}
|
||||||
|
managed_domains_sliced_at_end_date = get_sliced_domains(filter_managed_domains_end_date)
|
||||||
|
|
||||||
|
writer.writerow(["MANAGED DOMAINS COUNTS AT END DATE"])
|
||||||
|
writer.writerow(
|
||||||
|
[
|
||||||
|
"Total",
|
||||||
|
"Federal",
|
||||||
|
"Interstate",
|
||||||
|
"State or territory",
|
||||||
|
"Tribal",
|
||||||
|
"County",
|
||||||
|
"City",
|
||||||
|
"Special district",
|
||||||
|
"School district",
|
||||||
|
"Election office",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
writer.writerow(managed_domains_sliced_at_end_date)
|
||||||
|
writer.writerow([])
|
||||||
|
|
||||||
|
write_domains_csv(
|
||||||
|
writer,
|
||||||
|
columns,
|
||||||
|
sort_fields,
|
||||||
|
filter_managed_domains_end_date,
|
||||||
|
get_domain_managers=True,
|
||||||
|
should_write_header=True,
|
||||||
|
)
|
||||||
|
# Reset the CSV file's position to the beginning
|
||||||
|
csv_file.seek(0)
|
||||||
|
# Read the content into a variable
|
||||||
|
csv_content = csv_file.read()
|
||||||
|
|
||||||
|
self.maxDiff=None
|
||||||
|
|
||||||
|
# We expect the READY domain names with the domain managers: Their counts, and listing at end_date.
|
||||||
|
expected_content = (
|
||||||
|
"MANAGED DOMAINS COUNTS AT START DATE\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"
|
||||||
|
"\n"
|
||||||
|
"MANAGED DOMAINS COUNTS AT END DATE\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"
|
||||||
|
"\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"
|
||||||
|
)
|
||||||
|
# Normalize line endings and remove commas,
|
||||||
|
# spaces and leading/trailing whitespace
|
||||||
|
csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip()
|
||||||
|
expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip()
|
||||||
|
self.assertEqual(csv_content, expected_content)
|
||||||
|
|
||||||
|
def test_export_data_unmanaged_domains_to_csv(self):
|
||||||
|
""""""
|
||||||
|
with less_console_noise():
|
||||||
|
# Create a CSV file in memory
|
||||||
|
csv_file = StringIO()
|
||||||
|
writer = csv.writer(csv_file)
|
||||||
|
end_date = timezone.make_aware(datetime.combine(date.today() + timedelta(days=2), datetime.min.time()))
|
||||||
|
start_date = timezone.make_aware(datetime.combine(date.today() - timedelta(days=2), datetime.min.time()))
|
||||||
|
# Define columns, sort fields, and filter condition
|
||||||
|
columns = [
|
||||||
|
"Domain name",
|
||||||
|
"Domain type",
|
||||||
|
]
|
||||||
|
sort_fields = [
|
||||||
|
"domain__name",
|
||||||
|
]
|
||||||
|
filter_unmanaged_domains_start_date = {
|
||||||
|
"domain__permissions__isnull": True,
|
||||||
|
"domain__first_ready__lte": start_date,
|
||||||
|
}
|
||||||
|
unmanaged_domains_sliced_at_start_date = get_sliced_domains(filter_unmanaged_domains_start_date)
|
||||||
|
# Call the export functions
|
||||||
|
writer.writerow(["UNMANAGED DOMAINS COUNTS AT START DATE"])
|
||||||
|
writer.writerow(
|
||||||
|
[
|
||||||
|
"Total",
|
||||||
|
"Federal",
|
||||||
|
"Interstate",
|
||||||
|
"State or territory",
|
||||||
|
"Tribal",
|
||||||
|
"County",
|
||||||
|
"City",
|
||||||
|
"Special district",
|
||||||
|
"School district",
|
||||||
|
"Election office",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
writer.writerow(unmanaged_domains_sliced_at_start_date)
|
||||||
|
writer.writerow([])
|
||||||
|
|
||||||
|
filter_unmanaged_domains_end_date = {
|
||||||
|
"domain__permissions__isnull": True,
|
||||||
|
"domain__first_ready__lte": end_date,
|
||||||
|
}
|
||||||
|
unmanaged_domains_sliced_at_end_date = get_sliced_domains(filter_unmanaged_domains_end_date)
|
||||||
|
|
||||||
|
writer.writerow(["UNMANAGED DOMAINS COUNTS AT END DATE"])
|
||||||
|
writer.writerow(
|
||||||
|
[
|
||||||
|
"Total",
|
||||||
|
"Federal",
|
||||||
|
"Interstate",
|
||||||
|
"State or territory",
|
||||||
|
"Tribal",
|
||||||
|
"County",
|
||||||
|
"City",
|
||||||
|
"Special district",
|
||||||
|
"School district",
|
||||||
|
"Election office",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
writer.writerow(unmanaged_domains_sliced_at_end_date)
|
||||||
|
writer.writerow([])
|
||||||
|
|
||||||
|
write_domains_csv(
|
||||||
|
writer,
|
||||||
|
columns,
|
||||||
|
sort_fields,
|
||||||
|
filter_unmanaged_domains_end_date,
|
||||||
|
get_domain_managers=False,
|
||||||
|
should_write_header=True,
|
||||||
|
)
|
||||||
|
# Reset the CSV file's position to the beginning
|
||||||
|
csv_file.seek(0)
|
||||||
|
# Read the content into a variable
|
||||||
|
csv_content = csv_file.read()
|
||||||
|
|
||||||
|
self.maxDiff=None
|
||||||
|
|
||||||
|
# We expect the READY domain names with the domain managers: Their counts, and listing at end_date.
|
||||||
|
expected_content = (
|
||||||
|
"UNMANAGED DOMAINS COUNTS AT START DATE\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"
|
||||||
|
"\n"
|
||||||
|
"UNMANAGED DOMAINS COUNTS AT END DATE\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"
|
||||||
|
"\n"
|
||||||
|
"Domain name,Domain type\n"
|
||||||
|
"adomain10.gov,Federal\n"
|
||||||
|
)
|
||||||
|
# Normalize line endings and remove commas,
|
||||||
|
# spaces and leading/trailing whitespace
|
||||||
|
csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip()
|
||||||
|
expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip()
|
||||||
|
self.assertEqual(csv_content, expected_content)
|
||||||
|
|
||||||
|
def test_write_requests_body_with_date_filter_pulls_requests_in_range(self):
|
||||||
|
"""Test that requests that are
|
||||||
|
1. SUBMITTED and their submission_date are in range
|
||||||
|
are pulled when the growth report conditions are applied to export_requests_to_writed.
|
||||||
|
Test that requests are sorted by requested domain name.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
class HelperFunctions(TestCase):
|
class HelperFunctions(TestCase):
|
||||||
"""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."""
|
||||||
|
@ -704,3 +786,11 @@ class HelperFunctions(TestCase):
|
||||||
expected_date = timezone.now()
|
expected_date = timezone.now()
|
||||||
actual_date = get_default_end_date()
|
actual_date = get_default_end_date()
|
||||||
self.assertEqual(actual_date.date(), expected_date.date())
|
self.assertEqual(actual_date.date(), expected_date.date())
|
||||||
|
|
||||||
|
def get_sliced_domains(self):
|
||||||
|
"""Should get fitered domains counts sliced by org type and election office."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_get_sliced_requests(self):
|
||||||
|
"""Should get fitered requests counts sliced by org type and election office."""
|
||||||
|
pass
|
|
@ -25,9 +25,10 @@ def write_header(writer, columns):
|
||||||
|
|
||||||
def get_domain_infos(filter_condition, sort_fields):
|
def get_domain_infos(filter_condition, sort_fields):
|
||||||
domain_infos = (
|
domain_infos = (
|
||||||
DomainInformation.objects.select_related("domain", "authorizing_official")
|
DomainInformation.objects.prefetch_related("domain", "authorizing_official", "domain__permissions")
|
||||||
.filter(**filter_condition)
|
.filter(**filter_condition)
|
||||||
.order_by(*sort_fields)
|
.order_by(*sort_fields)
|
||||||
|
.distinct()
|
||||||
)
|
)
|
||||||
|
|
||||||
# Do a mass concat of the first and last name fields for authorizing_official.
|
# Do a mass concat of the first and last name fields for authorizing_official.
|
||||||
|
@ -44,7 +45,7 @@ def get_domain_infos(filter_condition, sort_fields):
|
||||||
return domain_infos_cleaned
|
return domain_infos_cleaned
|
||||||
|
|
||||||
|
|
||||||
def parse_row(columns, domain_info: DomainInformation, security_emails_dict=None, get_domain_managers=False):
|
def parse_domain_row(columns, domain_info: DomainInformation, security_emails_dict=None, get_domain_managers=False):
|
||||||
"""Given a set of columns, generate a new row from cleaned column data"""
|
"""Given a set of columns, generate a new row from cleaned column data"""
|
||||||
|
|
||||||
# Domain should never be none when parsing this information
|
# Domain should never be none when parsing this information
|
||||||
|
@ -136,7 +137,7 @@ def update_columns_with_domain_managers(columns, max_dm_count):
|
||||||
columns.append(f"Domain manager email {i}")
|
columns.append(f"Domain manager email {i}")
|
||||||
|
|
||||||
|
|
||||||
def write_csv(
|
def write_domains_csv(
|
||||||
writer,
|
writer,
|
||||||
columns,
|
columns,
|
||||||
sort_fields,
|
sort_fields,
|
||||||
|
@ -145,8 +146,8 @@ def write_csv(
|
||||||
should_write_header=True,
|
should_write_header=True,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Receives params from the parent methods and outputs a CSV with fltered and sorted domains.
|
Receives params from the parent methods and outputs a CSV with filtered and sorted domains.
|
||||||
Works with write_header as longas the same writer object is passed.
|
Works with write_header as long as the same writer object is passed.
|
||||||
get_domain_managers: Conditional bc we only use domain manager info for export_data_full_to_csv
|
get_domain_managers: Conditional bc we only use domain manager info for export_data_full_to_csv
|
||||||
should_write_header: Conditional bc export_data_domain_growth_to_csv calls write_body twice
|
should_write_header: Conditional bc export_data_domain_growth_to_csv calls write_body twice
|
||||||
"""
|
"""
|
||||||
|
@ -172,7 +173,7 @@ def write_csv(
|
||||||
rows = []
|
rows = []
|
||||||
for domain_info in page.object_list:
|
for domain_info in page.object_list:
|
||||||
try:
|
try:
|
||||||
row = parse_row(columns, domain_info, security_emails_dict, get_domain_managers)
|
row = parse_domain_row(columns, domain_info, security_emails_dict, get_domain_managers)
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# This should not happen. If it does, just skip this row.
|
# This should not happen. If it does, just skip this row.
|
||||||
|
@ -188,7 +189,6 @@ def write_csv(
|
||||||
|
|
||||||
def get_requests(filter_condition, sort_fields):
|
def get_requests(filter_condition, sort_fields):
|
||||||
requests = DomainApplication.objects.all().filter(**filter_condition).order_by(*sort_fields)
|
requests = DomainApplication.objects.all().filter(**filter_condition).order_by(*sort_fields)
|
||||||
|
|
||||||
return requests
|
return requests
|
||||||
|
|
||||||
|
|
||||||
|
@ -235,7 +235,8 @@ def write_requests_csv(
|
||||||
filter_condition,
|
filter_condition,
|
||||||
should_write_header=True,
|
should_write_header=True,
|
||||||
):
|
):
|
||||||
""" """
|
"""Receives params from the parent methods and outputs a CSV with filtered and sorted requests.
|
||||||
|
Works with write_header as long as the same writer object is passed."""
|
||||||
|
|
||||||
all_requetsts = get_requests(filter_condition, sort_fields)
|
all_requetsts = get_requests(filter_condition, sort_fields)
|
||||||
|
|
||||||
|
@ -295,7 +296,7 @@ def export_data_type_to_csv(csv_file):
|
||||||
Domain.State.ON_HOLD,
|
Domain.State.ON_HOLD,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
write_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):
|
||||||
|
@ -326,7 +327,7 @@ def export_data_full_to_csv(csv_file):
|
||||||
Domain.State.ON_HOLD,
|
Domain.State.ON_HOLD,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
write_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):
|
||||||
|
@ -358,7 +359,7 @@ def export_data_federal_to_csv(csv_file):
|
||||||
Domain.State.ON_HOLD,
|
Domain.State.ON_HOLD,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
write_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():
|
||||||
|
@ -426,8 +427,8 @@ 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_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_csv(
|
write_domains_csv(
|
||||||
writer,
|
writer,
|
||||||
columns,
|
columns,
|
||||||
sort_fields_for_deleted_domains,
|
sort_fields_for_deleted_domains,
|
||||||
|
@ -440,19 +441,19 @@ def export_data_domain_growth_to_csv(csv_file, start_date, end_date):
|
||||||
def get_sliced_domains(filter_condition):
|
def get_sliced_domains(filter_condition):
|
||||||
"""Get fitered domains counts sliced by org type and election office."""
|
"""Get fitered domains counts sliced by org type and election office."""
|
||||||
|
|
||||||
domains = DomainInformation.objects.all().filter(**filter_condition)
|
domains = DomainInformation.objects.all().filter(**filter_condition).distinct()
|
||||||
domains_count = domains.count()
|
domains_count = domains.count()
|
||||||
federal = domains.filter(organization_type=DomainApplication.OrganizationChoices.FEDERAL).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 = domains.filter(
|
||||||
organization_type=DomainApplication.OrganizationChoices.STATE_OR_TERRITORY
|
organization_type=DomainApplication.OrganizationChoices.STATE_OR_TERRITORY
|
||||||
).count()
|
).distinct().count()
|
||||||
tribal = domains.filter(organization_type=DomainApplication.OrganizationChoices.TRIBAL).count()
|
tribal = domains.filter(organization_type=DomainApplication.OrganizationChoices.TRIBAL).distinct().count()
|
||||||
county = domains.filter(organization_type=DomainApplication.OrganizationChoices.COUNTY).count()
|
county = domains.filter(organization_type=DomainApplication.OrganizationChoices.COUNTY).distinct().count()
|
||||||
city = domains.filter(organization_type=DomainApplication.OrganizationChoices.CITY).count()
|
city = domains.filter(organization_type=DomainApplication.OrganizationChoices.CITY).distinct().count()
|
||||||
special_district = domains.filter(organization_type=DomainApplication.OrganizationChoices.SPECIAL_DISTRICT).count()
|
special_district = domains.filter(organization_type=DomainApplication.OrganizationChoices.SPECIAL_DISTRICT).distinct().count()
|
||||||
school_district = domains.filter(organization_type=DomainApplication.OrganizationChoices.SCHOOL_DISTRICT).count()
|
school_district = domains.filter(organization_type=DomainApplication.OrganizationChoices.SCHOOL_DISTRICT).distinct().count()
|
||||||
election_board = domains.filter(is_election_board=True).count()
|
election_board = domains.filter(is_election_board=True).distinct().count()
|
||||||
|
|
||||||
return [
|
return [
|
||||||
domains_count,
|
domains_count,
|
||||||
|
@ -471,19 +472,19 @@ def get_sliced_domains(filter_condition):
|
||||||
def get_sliced_requests(filter_condition):
|
def get_sliced_requests(filter_condition):
|
||||||
"""Get fitered requests counts sliced by org type and election office."""
|
"""Get fitered requests counts sliced by org type and election office."""
|
||||||
|
|
||||||
requests = DomainApplication.objects.all().filter(**filter_condition)
|
requests = DomainApplication.objects.all().filter(**filter_condition).distinct()
|
||||||
requests_count = requests.count()
|
requests_count = requests.count()
|
||||||
federal = requests.filter(organization_type=DomainApplication.OrganizationChoices.FEDERAL).count()
|
federal = requests.filter(organization_type=DomainApplication.OrganizationChoices.FEDERAL).distinct().count()
|
||||||
interstate = requests.filter(organization_type=DomainApplication.OrganizationChoices.INTERSTATE).count()
|
interstate = requests.filter(organization_type=DomainApplication.OrganizationChoices.INTERSTATE).distinct().count()
|
||||||
state_or_territory = requests.filter(
|
state_or_territory = requests.filter(
|
||||||
organization_type=DomainApplication.OrganizationChoices.STATE_OR_TERRITORY
|
organization_type=DomainApplication.OrganizationChoices.STATE_OR_TERRITORY
|
||||||
).count()
|
).distinct().count()
|
||||||
tribal = requests.filter(organization_type=DomainApplication.OrganizationChoices.TRIBAL).count()
|
tribal = requests.filter(organization_type=DomainApplication.OrganizationChoices.TRIBAL).distinct().count()
|
||||||
county = requests.filter(organization_type=DomainApplication.OrganizationChoices.COUNTY).count()
|
county = requests.filter(organization_type=DomainApplication.OrganizationChoices.COUNTY).distinct().count()
|
||||||
city = requests.filter(organization_type=DomainApplication.OrganizationChoices.CITY).count()
|
city = requests.filter(organization_type=DomainApplication.OrganizationChoices.CITY).distinct().count()
|
||||||
special_district = requests.filter(organization_type=DomainApplication.OrganizationChoices.SPECIAL_DISTRICT).count()
|
special_district = requests.filter(organization_type=DomainApplication.OrganizationChoices.SPECIAL_DISTRICT).distinct().count()
|
||||||
school_district = requests.filter(organization_type=DomainApplication.OrganizationChoices.SCHOOL_DISTRICT).count()
|
school_district = requests.filter(organization_type=DomainApplication.OrganizationChoices.SCHOOL_DISTRICT).distinct().count()
|
||||||
election_board = requests.filter(is_election_board=True).count()
|
election_board = requests.filter(is_election_board=True).distinct().count()
|
||||||
|
|
||||||
return [
|
return [
|
||||||
requests_count,
|
requests_count,
|
||||||
|
@ -500,7 +501,8 @@ def get_sliced_requests(filter_condition):
|
||||||
|
|
||||||
|
|
||||||
def export_data_managed_domains_to_csv(csv_file, start_date, end_date):
|
def export_data_managed_domains_to_csv(csv_file, start_date, end_date):
|
||||||
"""Get domains have domain managers for two different dates."""
|
"""Get counts for domains that have domain managers for two different dates,
|
||||||
|
get list of domains at end_date."""
|
||||||
|
|
||||||
start_date_formatted = format_start_date(start_date)
|
start_date_formatted = format_start_date(start_date)
|
||||||
end_date_formatted = format_end_date(end_date)
|
end_date_formatted = format_end_date(end_date)
|
||||||
|
@ -512,14 +514,13 @@ def export_data_managed_domains_to_csv(csv_file, start_date, end_date):
|
||||||
sort_fields = [
|
sort_fields = [
|
||||||
"domain__name",
|
"domain__name",
|
||||||
]
|
]
|
||||||
|
|
||||||
filter_managed_domains_start_date = {
|
filter_managed_domains_start_date = {
|
||||||
"domain__permissions__isnull": False,
|
"domain__permissions__isnull": False,
|
||||||
"domain__first_ready__lte": start_date_formatted,
|
"domain__first_ready__lte": start_date_formatted,
|
||||||
}
|
}
|
||||||
managed_domains_sliced_at_start_date = get_sliced_domains(filter_managed_domains_start_date)
|
managed_domains_sliced_at_start_date = get_sliced_domains(filter_managed_domains_start_date)
|
||||||
|
|
||||||
writer.writerow(["MANAGED DOMAINS COUNTS AT SRAT DATE"])
|
writer.writerow(["MANAGED DOMAINS COUNTS AT START DATE"])
|
||||||
writer.writerow(
|
writer.writerow(
|
||||||
[
|
[
|
||||||
"Total",
|
"Total",
|
||||||
|
@ -537,16 +538,6 @@ def export_data_managed_domains_to_csv(csv_file, start_date, end_date):
|
||||||
writer.writerow(managed_domains_sliced_at_start_date)
|
writer.writerow(managed_domains_sliced_at_start_date)
|
||||||
writer.writerow([])
|
writer.writerow([])
|
||||||
|
|
||||||
write_csv(
|
|
||||||
writer,
|
|
||||||
columns,
|
|
||||||
sort_fields,
|
|
||||||
filter_managed_domains_start_date,
|
|
||||||
get_domain_managers=True,
|
|
||||||
should_write_header=True,
|
|
||||||
)
|
|
||||||
writer.writerow([])
|
|
||||||
|
|
||||||
filter_managed_domains_end_date = {
|
filter_managed_domains_end_date = {
|
||||||
"domain__permissions__isnull": False,
|
"domain__permissions__isnull": False,
|
||||||
"domain__first_ready__lte": end_date_formatted,
|
"domain__first_ready__lte": end_date_formatted,
|
||||||
|
@ -571,7 +562,7 @@ def export_data_managed_domains_to_csv(csv_file, start_date, end_date):
|
||||||
writer.writerow(managed_domains_sliced_at_end_date)
|
writer.writerow(managed_domains_sliced_at_end_date)
|
||||||
writer.writerow([])
|
writer.writerow([])
|
||||||
|
|
||||||
write_csv(
|
write_domains_csv(
|
||||||
writer,
|
writer,
|
||||||
columns,
|
columns,
|
||||||
sort_fields,
|
sort_fields,
|
||||||
|
@ -582,7 +573,8 @@ def export_data_managed_domains_to_csv(csv_file, start_date, end_date):
|
||||||
|
|
||||||
|
|
||||||
def export_data_unmanaged_domains_to_csv(csv_file, start_date, end_date):
|
def export_data_unmanaged_domains_to_csv(csv_file, start_date, end_date):
|
||||||
"""Get domains that do not have domain managers for two different dates."""
|
"""Get counts for domains that do not have domain managers for two different dates,
|
||||||
|
get list of domains at end_date."""
|
||||||
|
|
||||||
start_date_formatted = format_start_date(start_date)
|
start_date_formatted = format_start_date(start_date)
|
||||||
end_date_formatted = format_end_date(end_date)
|
end_date_formatted = format_end_date(end_date)
|
||||||
|
@ -619,16 +611,6 @@ def export_data_unmanaged_domains_to_csv(csv_file, start_date, end_date):
|
||||||
writer.writerow(unmanaged_domains_sliced_at_start_date)
|
writer.writerow(unmanaged_domains_sliced_at_start_date)
|
||||||
writer.writerow([])
|
writer.writerow([])
|
||||||
|
|
||||||
write_csv(
|
|
||||||
writer,
|
|
||||||
columns,
|
|
||||||
sort_fields,
|
|
||||||
filter_unmanaged_domains_start_date,
|
|
||||||
get_domain_managers=True,
|
|
||||||
should_write_header=True,
|
|
||||||
)
|
|
||||||
writer.writerow([])
|
|
||||||
|
|
||||||
filter_unmanaged_domains_end_date = {
|
filter_unmanaged_domains_end_date = {
|
||||||
"domain__permissions__isnull": True,
|
"domain__permissions__isnull": True,
|
||||||
"domain__first_ready__lte": end_date_formatted,
|
"domain__first_ready__lte": end_date_formatted,
|
||||||
|
@ -653,18 +635,23 @@ def export_data_unmanaged_domains_to_csv(csv_file, start_date, end_date):
|
||||||
writer.writerow(unmanaged_domains_sliced_at_end_date)
|
writer.writerow(unmanaged_domains_sliced_at_end_date)
|
||||||
writer.writerow([])
|
writer.writerow([])
|
||||||
|
|
||||||
write_csv(
|
write_domains_csv(
|
||||||
writer,
|
writer,
|
||||||
columns,
|
columns,
|
||||||
sort_fields,
|
sort_fields,
|
||||||
filter_unmanaged_domains_end_date,
|
filter_unmanaged_domains_end_date,
|
||||||
get_domain_managers=True,
|
get_domain_managers=False,
|
||||||
should_write_header=True,
|
should_write_header=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def export_data_requests_growth_to_csv(csv_file, start_date, end_date):
|
def export_data_requests_growth_to_csv(csv_file, start_date, end_date):
|
||||||
""" """
|
"""
|
||||||
|
Growth report:
|
||||||
|
Receive start and end dates from the view, parse them.
|
||||||
|
Request from write_requests_body SUBMITTED requests that are created between
|
||||||
|
the start and end dates. Specify sort params.
|
||||||
|
"""
|
||||||
|
|
||||||
start_date_formatted = format_start_date(start_date)
|
start_date_formatted = format_start_date(start_date)
|
||||||
end_date_formatted = format_end_date(end_date)
|
end_date_formatted = format_end_date(end_date)
|
||||||
|
@ -676,7 +663,7 @@ def export_data_requests_growth_to_csv(csv_file, start_date, end_date):
|
||||||
"Submission date",
|
"Submission date",
|
||||||
]
|
]
|
||||||
sort_fields = [
|
sort_fields = [
|
||||||
# "domain__name",
|
"requested_domain__name",
|
||||||
]
|
]
|
||||||
filter_condition = {
|
filter_condition = {
|
||||||
"status": DomainApplication.ApplicationStatus.SUBMITTED,
|
"status": DomainApplication.ApplicationStatus.SUBMITTED,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue