# Create your models here. from datetime import timedelta from django.core.validators import MaxValueValidator, RegexValidator from django.db import models from django.db.models import F, Q from django.utils.translation import gettext_lazy as _ from core.models import User from core.utils import get_semester_code class Timetable(models.Model): user = models.ForeignKey( User, verbose_name=_("user"), related_name="timetables", on_delete=models.CASCADE, ) semester = models.CharField( _("semester"), default=get_semester_code, validators=[RegexValidator(r"(A|P)\d{2}")], blank=True, ) class Meta: verbose_name = _("timetable") verbose_name_plural = _("timetables") constraints = [ models.UniqueConstraint( fields=("user", "semester"), name="timetable_unique_user_semester" ) ] permissions = [("add_self_timetable", "Can add its own timetable")] def __str__(self) -> str: return f"{self.user} {self.semester}" class TimetableSlot(models.Model): MINUTES_PER_SLOT = 15 class WeekDay(models.IntegerChoices): MONDAY = 1 TUESDAY = 2 WEDNESDAY = 3 THURSDAY = 4 FRIDAY = 5 SATURDAY = 6 SUNDAY = 7 class WeekGroup(models.TextChoices): A = "A" B = "B" BOTH = "" timetable = models.ForeignKey( Timetable, verbose_name=_("timetable"), related_name="slots", on_delete=models.CASCADE, ) weekday = models.SmallIntegerField(_("weekday"), choices=WeekDay) # there are 4 * 24 = 96 quarters in a day, and we start counting at 0 start_at = models.PositiveSmallIntegerField( _("start at"), validators=[MaxValueValidator(95)] ) end_at = models.PositiveSmallIntegerField( _("end at"), validators=[MaxValueValidator(95)] ) course_type = models.CharField(_("course type"), max_length=12) room = models.CharField(_("room"), max_length=32) ue = models.CharField(_("ue"), max_length=32) week_group = models.CharField( _("week group"), max_length=1, choices=WeekGroup, default=WeekGroup.BOTH, blank=True, ) class Meta: verbose_name = _("timetable slot") verbose_name_plural = _("timetable slots") constraints = [ models.CheckConstraint( condition=Q(end_at__gt=F("start_at")), name="timetable_slot_end_after_start", ) ] def __str__(self) -> str: return f"{self.start_hour} - {self.end_hour} - {self.get_weekday_display()}" @property def start_hour(self): return timedelta(minutes=self.start_at * self.MINUTES_PER_SLOT) @property def end_hour(self): return timedelta(minutes=self.end_at * self.MINUTES_PER_SLOT)