feat: Implement supervisor trainee management features, including search, add, and remove functionalities
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
+124
-1
@@ -12,6 +12,7 @@ from django.db.models.functions import Coalesce, Lower
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
|
||||
from django.contrib.auth.decorators import login_required, user_passes_test
|
||||
from django.views.decorators.http import require_POST
|
||||
from django.urls import reverse_lazy
|
||||
from django.urls.base import reverse
|
||||
from django.utils import timezone
|
||||
@@ -5910,9 +5911,131 @@ def create_user(request, context=None, trainee: bool = False):
|
||||
return render(request, form_template, {"form": form})
|
||||
|
||||
|
||||
class SupervisorDetail(CidManagerRequiredMixin, DetailView):
|
||||
class SupervisorDetail(DetailView):
|
||||
model = Supervisor
|
||||
|
||||
def get_queryset(self):
|
||||
"""Allow supervisors to view their own detail page; managers see all."""
|
||||
qs = super().get_queryset()
|
||||
if not self.request.user.is_authenticated:
|
||||
return qs.none()
|
||||
if self.request.user.is_superuser or self.request.user.groups.filter(name="cid_user_manager").exists():
|
||||
return qs
|
||||
if hasattr(self.request.user, "supervisor"):
|
||||
return qs.filter(user=self.request.user)
|
||||
return qs.none()
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
"""Override to check permissions before returning object."""
|
||||
obj = super().get_object(queryset)
|
||||
if not (
|
||||
self.request.user.is_superuser
|
||||
or self.request.user.groups.filter(name="cid_user_manager").exists()
|
||||
or (hasattr(self.request.user, "supervisor") and obj.user == self.request.user)
|
||||
):
|
||||
raise PermissionDenied
|
||||
return obj
|
||||
|
||||
|
||||
@user_is_cid_user_manager
|
||||
def supervisor_trainee_search(request, pk):
|
||||
"""HTMX endpoint: search for users to add as trainees to a supervisor.
|
||||
Scope: managers and the supervisor themselves.
|
||||
"""
|
||||
supervisor = get_object_or_404(Supervisor, pk=pk)
|
||||
|
||||
if not (
|
||||
request.user.is_superuser
|
||||
or request.user.groups.filter(name="cid_user_manager").exists()
|
||||
or supervisor.user == request.user
|
||||
):
|
||||
raise PermissionDenied
|
||||
|
||||
q = request.GET.get("q", "").strip()
|
||||
if not q:
|
||||
return render(
|
||||
request,
|
||||
"generic/partials/supervisor_trainee_search_results.html",
|
||||
{"supervisor": supervisor, "results": []},
|
||||
)
|
||||
|
||||
already_trainees = supervisor.trainee.values_list("user_id", flat=True)
|
||||
results = (
|
||||
User.objects.filter(
|
||||
Q(first_name__icontains=q)
|
||||
| Q(last_name__icontains=q)
|
||||
| Q(username__icontains=q)
|
||||
| Q(email__icontains=q)
|
||||
)
|
||||
.exclude(pk__in=already_trainees)
|
||||
.order_by("first_name", "last_name", "username")[:20]
|
||||
)
|
||||
|
||||
return render(
|
||||
request,
|
||||
"generic/partials/supervisor_trainee_search_results.html",
|
||||
{"supervisor": supervisor, "results": results},
|
||||
)
|
||||
|
||||
|
||||
@require_POST
|
||||
@user_is_cid_user_manager
|
||||
def supervisor_trainee_add(request, pk, user_id):
|
||||
"""Add a trainee to a supervisor.
|
||||
Scope: managers and the supervisor themselves.
|
||||
"""
|
||||
supervisor = get_object_or_404(Supervisor, pk=pk)
|
||||
trainee_user = get_object_or_404(User, pk=user_id)
|
||||
|
||||
if not (
|
||||
request.user.is_superuser
|
||||
or request.user.groups.filter(name="cid_user_manager").exists()
|
||||
or supervisor.user == request.user
|
||||
):
|
||||
raise PermissionDenied
|
||||
|
||||
profile = trainee_user.userprofile
|
||||
profile.supervisor = supervisor
|
||||
profile.save()
|
||||
|
||||
if request.htmx:
|
||||
return render(
|
||||
request,
|
||||
"generic/partials/supervisor_trainees_list.html",
|
||||
{"supervisor": supervisor},
|
||||
)
|
||||
return redirect(supervisor.get_absolute_url())
|
||||
|
||||
|
||||
@require_POST
|
||||
@user_is_cid_user_manager
|
||||
def supervisor_trainee_remove(request, pk, user_id):
|
||||
"""Remove a trainee from a supervisor.
|
||||
Scope: managers and the supervisor themselves.
|
||||
"""
|
||||
supervisor = get_object_or_404(Supervisor, pk=pk)
|
||||
trainee_user = get_object_or_404(User, pk=user_id)
|
||||
|
||||
if not (
|
||||
request.user.is_superuser
|
||||
or request.user.groups.filter(name="cid_user_manager").exists()
|
||||
or supervisor.user == request.user
|
||||
):
|
||||
raise PermissionDenied
|
||||
|
||||
profile = trainee_user.userprofile
|
||||
if profile.supervisor == supervisor:
|
||||
profile.supervisor = None
|
||||
profile.save()
|
||||
|
||||
if request.htmx:
|
||||
return render(
|
||||
request,
|
||||
"generic/partials/supervisor_trainees_list.html",
|
||||
{"supervisor": supervisor},
|
||||
)
|
||||
return redirect(supervisor.get_absolute_url())
|
||||
|
||||
|
||||
class SupervisorDelete(CidManagerRequiredMixin, DeleteView):
|
||||
model = Supervisor
|
||||
|
||||
Reference in New Issue
Block a user