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)