manage.get.gov/src/registrar/views/domain_requests_json.py

175 lines
6.7 KiB
Python

from django.http import JsonResponse
from django.core.paginator import Paginator
from registrar.models import DomainRequest
from django.utils.dateformat import format
from django.contrib.auth.decorators import login_required
from django.urls import reverse
from django.db.models import Q
@login_required
def get_domain_requests_json(request):
"""Given the current request,
get all domain requests that are associated with the request user and exclude the APPROVED ones.
If we are on the portfolio requests page, limit the response to only those requests associated with
the given portfolio."""
domain_request_ids = get_domain_request_ids_from_request(request)
objects = DomainRequest.objects.filter(id__in=domain_request_ids)
unfiltered_total = objects.count()
objects = apply_search(objects, request)
objects = apply_status_filter(objects, request)
objects = apply_sorting(objects, request)
paginator = Paginator(objects, 10)
page_number = request.GET.get("page", 1)
page_obj = paginator.get_page(page_number)
domain_requests = [
serialize_domain_request(request, domain_request, request.user) for domain_request in page_obj.object_list
]
return JsonResponse(
{
"domain_requests": domain_requests,
"has_next": page_obj.has_next(),
"has_previous": page_obj.has_previous(),
"page": page_obj.number,
"num_pages": paginator.num_pages,
"total": paginator.count,
"unfiltered_total": unfiltered_total,
}
)
def get_domain_request_ids_from_request(request):
"""Get domain request ids from request.
If portfolio specified, return domain request ids associated with portfolio.
Otherwise, return domain request ids associated with request.user.
"""
portfolio = request.GET.get("portfolio")
filter_condition = Q(creator=request.user)
if portfolio:
if request.user.is_org_user(request) and request.user.has_view_all_requests_portfolio_permission(portfolio):
filter_condition = Q(portfolio=portfolio)
else:
filter_condition = Q(portfolio=portfolio, creator=request.user)
domain_requests = DomainRequest.objects.filter(filter_condition).exclude(
status=DomainRequest.DomainRequestStatus.APPROVED
)
return domain_requests.values_list("id", flat=True)
def apply_search(queryset, request):
search_term = request.GET.get("search_term")
is_portfolio = request.GET.get("portfolio")
if search_term:
search_term_lower = search_term.lower()
new_domain_request_text = "new domain request"
# Check if the search term is a substring of 'New domain request'
# If yes, we should return domain requests that do not have a
# requested_domain (those display as New domain request in the UI)
if search_term_lower in new_domain_request_text:
queryset = queryset.filter(
Q(requested_domain__name__icontains=search_term) | Q(requested_domain__isnull=True)
)
elif is_portfolio:
queryset = queryset.filter(
Q(requested_domain__name__icontains=search_term)
| Q(creator__first_name__icontains=search_term)
| Q(creator__last_name__icontains=search_term)
| Q(creator__email__icontains=search_term)
)
# For non org users
else:
queryset = queryset.filter(Q(requested_domain__name__icontains=search_term))
return queryset
def apply_status_filter(queryset, request):
status_param = request.GET.get("status")
if status_param:
status_list = status_param.split(",")
statuses = [status for status in status_list if status in DomainRequest.DomainRequestStatus.values]
# Construct Q objects for statuses that can be queried through ORM
status_query = Q()
if statuses:
status_query |= Q(status__in=statuses)
# Apply the combined query
queryset = queryset.filter(status_query)
return queryset
def apply_sorting(queryset, request):
sort_by = request.GET.get("sort_by", "id") # Default to 'id'
order = request.GET.get("order", "asc") # Default to 'asc'
# Handle special case for 'creator'
if sort_by == "creator":
sort_by = "creator__email"
if order == "desc":
sort_by = f"-{sort_by}"
return queryset.order_by(sort_by)
def serialize_domain_request(request, domain_request, user):
deletable_statuses = [
DomainRequest.DomainRequestStatus.STARTED,
DomainRequest.DomainRequestStatus.WITHDRAWN,
]
# Determine action label based on user permissions and request status
editable_statuses = [
DomainRequest.DomainRequestStatus.STARTED,
DomainRequest.DomainRequestStatus.ACTION_NEEDED,
DomainRequest.DomainRequestStatus.WITHDRAWN,
]
# No portfolio action_label
if domain_request.creator == user:
action_label = "Edit" if domain_request.status in editable_statuses else "Manage"
else:
action_label = "View"
# No portfolio deletable
is_deletable = domain_request.status in deletable_statuses
# If we're working with a portfolio
if user.is_org_user(request):
portfolio = request.session.get("portfolio")
is_deletable = (
domain_request.status in deletable_statuses and user.has_edit_request_portfolio_permission(portfolio)
) and domain_request.creator == user
if user.has_edit_request_portfolio_permission(portfolio) and domain_request.creator == user:
action_label = "Edit" if domain_request.status in editable_statuses else "Manage"
else:
action_label = "View"
# Map the action label to corresponding URLs and icons
action_url_map = {
"Edit": reverse("edit-domain-request", kwargs={"id": domain_request.id}),
"Manage": reverse("domain-request-status", kwargs={"pk": domain_request.id}),
"View": reverse("domain-request-status-viewonly", kwargs={"pk": domain_request.id}),
}
svg_icon_map = {"Edit": "edit", "Manage": "settings", "View": "visibility"}
return {
"requested_domain": domain_request.requested_domain.name if domain_request.requested_domain else None,
"last_submitted_date": domain_request.last_submitted_date,
"status": domain_request.get_status_display(),
"created_at": format(domain_request.created_at, "c"), # Serialize to ISO 8601
"creator": domain_request.creator.email,
"id": domain_request.id,
"is_deletable": is_deletable,
"action_url": action_url_map.get(action_label),
"action_label": action_label,
"svg_icon": svg_icon_map.get(action_label),
}