From bef2a7036789895e3cdea1b6179d265c747587aa Mon Sep 17 00:00:00 2001 From: Harrison Katz Date: Tue, 2 Dec 2025 03:16:25 -0800 Subject: [PATCH] feat: add models to handle storing course tutor info --- hknweb/tutoring/admin.py | 8 +++++++- hknweb/tutoring/apps.py | 3 +++ hknweb/tutoring/models.py | 33 ++++++++++++++++++++++++++++++--- hknweb/tutoring/signals.py | 16 ++++++++++++++++ 4 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 hknweb/tutoring/signals.py diff --git a/hknweb/tutoring/admin.py b/hknweb/tutoring/admin.py index 8cb8cdd8..fbba68e0 100644 --- a/hknweb/tutoring/admin.py +++ b/hknweb/tutoring/admin.py @@ -1,6 +1,12 @@ from django.contrib import admin -from hknweb.tutoring.models import Room, TutoringLogistics, Slot +from hknweb.tutoring.models import Tutor, Room, TutoringLogistics, Slot + + +@admin.register(Tutor) +class TutorAdmin(admin.ModelAdmin): + search_fields = ("user__username", "user__first_name", "user__last_name", "user__email") + autocomplete_fields = ('user',) @admin.register(TutoringLogistics) diff --git a/hknweb/tutoring/apps.py b/hknweb/tutoring/apps.py index d7c32180..93c189bf 100644 --- a/hknweb/tutoring/apps.py +++ b/hknweb/tutoring/apps.py @@ -3,3 +3,6 @@ class TutoringConfig(AppConfig): name = "hknweb.tutoring" + + def ready(self): + from . import signals diff --git a/hknweb/tutoring/models.py b/hknweb/tutoring/models.py index 3a534850..00e2b8b9 100644 --- a/hknweb/tutoring/models.py +++ b/hknweb/tutoring/models.py @@ -6,8 +6,35 @@ from django.db.models import Value from django.db.models.functions import Concat from django.contrib.auth.models import User +from django.core.exceptions import ValidationError +from hknweb import settings from hknweb.coursesemester.models import Semester +from hknweb.models import Course + + +class Tutor(models.Model): + user = models.OneToOneField( + User, on_delete=models.CASCADE, related_name="tutoring_info" + ) + completed_courses = models.ManyToManyField( + Course, blank=True, related_name="completed_tutors" + ) + in_progress_courses = models.ManyToManyField( + Course, blank=True, related_name="in_progress_tutors" + ) + preferred_courses = models.ManyToManyField( + Course, blank=True, related_name="preferred_tutors" + ) + + def save(self, *args, **kwargs): + if not self.user.cmemberships.filter( + committee=settings.TUTORING_GROUP + ).exists(): + raise ValidationError( + f"User {self.user.username} is not in the tutoring committee." + ) + super().save(*args, **kwargs) class Room(models.Model): @@ -26,10 +53,10 @@ class Meta: Semester, on_delete=models.CASCADE, null=True, default=None ) one_hour_tutors = models.ManyToManyField( - User, blank=True, related_name="one_hour_tutoring" + Tutor, blank=True, related_name="one_hour_tutoring" ) two_hour_tutors = models.ManyToManyField( - User, blank=True, related_name="two_hour_tutoring" + Tutor, blank=True, related_name="two_hour_tutoring" ) def __str__(self) -> str: # pragma: no cover @@ -50,7 +77,7 @@ class Slot(models.Model): ) room = models.ForeignKey(Room, on_delete=models.CASCADE, null=True, default=None) num_tutors = models.IntegerField(default=0) - tutors = models.ManyToManyField(User, blank=True, related_name="tutoring_slots") + tutors = models.ManyToManyField(Tutor, blank=True, related_name="tutoring_slots") WEEKDAY_STRS = "Mon Tue Wed Thu Fri Sat Sun".split() WEEKDAY_CHOICES = list(zip(range(len(WEEKDAY_STRS)), WEEKDAY_STRS)) diff --git a/hknweb/tutoring/signals.py b/hknweb/tutoring/signals.py new file mode 100644 index 00000000..62dce039 --- /dev/null +++ b/hknweb/tutoring/signals.py @@ -0,0 +1,16 @@ +from django.db.models.signals import m2m_changed +from django.dispatch import receiver + +from hknweb import settings +from hknweb.models import Committeeship, User +from hknweb.tutoring.models import Tutor + + +@receiver(m2m_changed, sender=Committeeship.committee_members.through) +def deleteTutorIfRemovedFromCommittee(sender, instance, action, pk_set, **_): + if action == "post_remove": + Tutor.objects.filter(user__pk__in=pk_set).exclude( + user__pk__in=User.objects.filter( + pk__in=pk_set, cmembership__committee=settings.TUTORING_GROUP + ).values_list("pk", flat=True) + ).delete()