cmmc_audit/resolvers.py
2026-05-27 14:45:29 -06:00

174 lines
5.7 KiB
Python

from django.contrib.auth import get_user_model
def _get_model(app_label, model_name):
from django.apps import apps
return apps.get_model(app_label, model_name)
def _object_label(app_label, model_name, pk, formatter=None):
if pk in (None, ""):
return None
try:
obj = _get_model(app_label, model_name).objects.get(pk=pk)
except Exception:
return None
if formatter is not None:
return formatter(obj)
return str(obj)
def user_label(user):
full_name = user.get_full_name()
if full_name:
return f"{user.username} ({full_name})"
return user.username
def user_profile_label(user_profile):
try:
return user_label(user_profile.user)
except Exception:
return f"UserProfile id {user_profile.pk} (user not found)"
def user_profile_label_from_id(user_profile_id):
try:
user_profile = _get_model("user", "UserProfile").objects.select_related("user").get(pk=user_profile_id)
except Exception:
return f"UserProfile id {user_profile_id} (user not found)"
return user_profile_label(user_profile)
def _resource_allocation_prefix(resource_names):
names = [name for name in resource_names if name]
if not names:
return "Allocation"
if len(names) <= 2:
return f"{', '.join(names)} allocation"
return f"{', '.join(names[:2])} + {len(names) - 2} more allocation"
def allocation_label_from_parts(resource_names, project_reference):
return f"{_resource_allocation_prefix(resource_names)} for {project_reference}"
def project_label_from_id(project_id):
if project_id in (None, ""):
return "Project unknown"
try:
return project_label(_get_model("project", "Project").objects.get(pk=project_id))
except Exception:
return f"Project id {project_id} (not found)"
def allocation_label(allocation):
resources = list(allocation.resources.values_list("name", flat=True).order_by("name"))
try:
project_reference = project_label(allocation.project)
except Exception:
project_reference = project_label_from_id(getattr(allocation, "project_id", None))
return allocation_label_from_parts(resources, project_reference)
def allocation_change_label(allocation_change):
return f"change request for {allocation_label(allocation_change.allocation)}"
def project_user_label(project_user):
return f"{project_user.user.username} on {project_label(project_user.project)}"
def project_review_label(project_review):
return f"review for {project_label(project_review.project)}"
def project_label(project):
label = f"Project: {project.title}"
if getattr(project, "project_code", ""):
label = f"{label} (code {project.project_code})"
return label
def resolve_target_label(target_type, target_id):
formatter_map = {
"allocation.allocation": lambda obj: allocation_label(obj),
"allocation.allocationchangerequest": lambda obj: allocation_change_label(obj),
"auth.user": lambda obj: user_label(obj),
"user.userprofile": lambda obj: user_profile_label(obj),
"project.project": lambda obj: project_label(obj),
"project.projectuser": lambda obj: project_user_label(obj),
"project.projectreview": lambda obj: project_review_label(obj),
"resource.resource": lambda obj: obj.name,
}
if "." not in target_type:
return None
app_label, model_name = target_type.split(".", 1)
if target_type == "project.project":
return project_label_from_id(target_id)
return _object_label(app_label, model_name, target_id, formatter_map.get(target_type))
def _resolve_id(key, value):
if key in {"project_id", "project"}:
label = _object_label("project", "Project", value, lambda obj: project_label(obj))
elif key in {"user_id", "user"}:
label = _object_label("auth", "User", value, lambda obj: user_label(obj))
elif key in {"allocation_id", "allocation"}:
label = _object_label("allocation", "Allocation", value, lambda obj: allocation_label(obj))
elif key in {"allocation_change_request_id", "allocation_change_request"}:
label = _object_label(
"allocation",
"AllocationChangeRequest",
value,
lambda obj: allocation_change_label(obj),
)
elif key in {"resource_type_id", "resource_type"}:
label = _object_label("resource", "ResourceType", value)
elif key in {"parent_resource_id", "parent_resource"}:
label = _object_label("resource", "Resource", value, lambda obj: obj.name)
else:
label = None
if not label:
return value
return f"{label} (id {value})"
def _resolve_id_list(key, values):
if key == "resource_ids":
labels = []
for value in values:
label = _object_label("resource", "Resource", value, lambda obj: obj.name)
labels.append(f"{label} (id {value})" if label else value)
return labels
return values
def resolve_value_labels(values):
if not isinstance(values, dict):
return values
resolved = {}
for key, value in values.items():
if isinstance(value, list):
resolved[key] = _resolve_id_list(key, value)
elif key.endswith("_id") or key in {"project", "user", "allocation", "resource_type", "parent_resource"}:
resolved[key] = _resolve_id(key, value)
else:
resolved[key] = value
return resolved
def actor_label(actor):
if actor is None:
return "programmatic"
return user_label(actor)
def username_from_id(user_id):
try:
return user_label(get_user_model().objects.get(pk=user_id))
except Exception:
return str(user_id)