import nested_admin from django.forms import Form from django.db.models.query import QuerySet from django.http import HttpRequest, HttpResponse from django.contrib import admin, messages from django.utils.translation import ngettext from django.utils.safestring import SafeText from ..models.courses import CourseTypes from ..models.students import Student from ..models.missions import Training from ..models.weekpref import WeekPreference from .training_adm import TrainingInLIne from .hourbuilding_adm import HourBuildingInLine from ..custom.colortag import course_color from ..custom.student_permissions import has_edit_permission, has_week_add_permission from ..actions.exportweek import export_selected from datetime import date, datetime from typing import Dict, List, Tuple, Any class WeekPreferenceAdmin(nested_admin.NestedPolymorphicModelAdmin): #list_display = ("week", "student__surname", "student__name", "student__course", "course_color", "student_brief_mix", "inserted") list_filter = ("week", "student__course", ) search_fields = ("student__surname","student__name", ) actions = ("export", ) readonly_fields = ("inserted", ) @admin.action(description="Export Selected Preferences") def export(self, request: HttpRequest, queryset: QuerySet[WeekPreference]) -> HttpResponse | None: if queryset.count() == 0: return None self.message_user(request, ngettext("Exporting %d row", "Exporting %d rows", queryset.count()) % queryset.count(), messages.SUCCESS) return export_selected(request=request, queryset=queryset) @admin.display(description="Mission Count") def student_brief_mix(self, obj: WeekPreference) -> SafeText: if not obj.student.course: return SafeText("") return SafeText(f"{Training.objects.filter(weekpref = obj.id).count()}") @admin.display(description="Color") def course_color(self, obj: WeekPreference) -> SafeText: if not obj.student.course: return SafeText("") return course_color(obj.student.course.color) # Hide brief mix count and inserted fields for students def get_list_display(self, request: HttpRequest) -> Tuple: if hasattr(request.user, "student"): return ("week", "student__surname", "student__name", "student__course", "course_color", ) return ("week", "student__surname", "student__name", "student__course", "course_color", "student_brief_mix", "inserted") # If a user is registered as student hide filters def get_list_filter(self, request: HttpRequest) -> List[str]: list_filter = super().get_list_filter(request) if hasattr(request.user, "student"): return [] return list_filter # Get available mission or HB depending on student course def get_inline_instances(self, request: HttpRequest, obj: WeekPreference | None = None): if hasattr(request.user, "student"): student: Student = request.user.student # Only ATPL students are able to book HourBuilding Missions if student.course and student.course.ctype in (CourseTypes.ATPL, CourseTypes.DISTANCE): return ( TrainingInLIne(self.model, self.admin_site), HourBuildingInLine(self.model, self.admin_site), ) # All other courses have only training return (TrainingInLIne(self.model, self.admin_site), ) else: return ( TrainingInLIne(self.model, self.admin_site), HourBuildingInLine(self.model, self.admin_site), ) # If a user is registered as student do not show actions def get_actions(self, request: HttpRequest) -> Dict[str, Any]: actions = super().get_actions(request) if hasattr(request.user, "student"): return {} return actions # If a user is registered as student show only their preferences def get_queryset(self, request: HttpRequest) -> QuerySet[WeekPreference]: qs = super().get_queryset(request).order_by("-week", "-student__course", "student__surname", "student__name") if hasattr(request.user, "student"): return qs.filter(student=request.user.student) # If admin show everything return qs def get_form(self, request: HttpRequest, obj: WeekPreference | None = None, **kwargs: Dict[str, Any]) -> Form: form: Form = super().get_form(request, obj, **kwargs) current_week = date.today().isocalendar().week # If form contains the week field if "week" in form.base_fields: # Set default value as current week form.base_fields["week"].initial = current_week # If student is current user making request if hasattr(request.user, "student"): student: Student = request.user.student if "student" in form.base_fields: form.base_fields["student"].initial = student form.base_fields["student"].disabled = True form.base_fields["week"].disabled = True # student cannot change week return form # If user is a student deny edit permission for week past the current one def has_change_permission(self, request: HttpRequest, obj: WeekPreference | None = None) -> bool: return has_edit_permission(request=request, obj=obj) # If user is a student deny edit permission for week past the current one def has_add_permission(self, request: HttpRequest, obj: WeekPreference | None = None) -> bool: return has_week_add_permission(request=request) and has_edit_permission(request=request, obj=obj) # If user is a student deny edit permission for week past the current one def has_delete_permission(self, request: HttpRequest, obj: WeekPreference | None = None)-> bool: return self.has_change_permission(request, obj) def changeform_view(self, request: HttpRequest, object_id: int | None = None, form_url: str = "", extra_context = None): extra_context = extra_context or {} if hasattr(request.user, "student") and object_id: weekpref = WeekPreference.objects.get(id=object_id) if not has_edit_permission(request=request, obj=weekpref): extra_context["show_save"] = False extra_context["show_save_and_continue"] = False extra_context["show_save_and_add_another"] = False extra_context["show_delete"] = False return super().changeform_view(request, object_id, form_url, extra_context) def save_model(self, request: HttpRequest, obj: WeekPreference, form: Form, change: bool): # Imposta automaticamente lo studente se non è già valorizzato if hasattr(request.user, "student") and not obj.student_id: obj.student = request.user.student super().save_model(request, obj, form, change)