indici/src/core/models.py
2022-07-29 07:59:39 -06:00

280 lines
7.2 KiB
Python

from datetime import date
from django.db import models
from django.urls import reverse
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import (
GenericForeignKey, GenericRelation
)
from django.db.models import (
Exists, OuterRef, Prefetch, Subquery, Count, Sum, Avg, F, Q, Value
)
class SchoolYear(models.Model):
year = models.PositiveIntegerField(unique=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f'{self.year}'
@property
def is_current_year(self):
return True if self.year == int(date.today().year) else False
def get_absolute_url(self):
return reverse('core:schoolyear-detail', kwargs={
'year': self.year
})
class StudentTag(models.Model):
name = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
# class StudentManager(models.Manager):
# def get_queryset(self):
# today = date.today()
# return super().get_queryset().filter(
# school_year__start_date__year__gte=today.year,
# school_year__end_date__year__lte=today.year
# )
class Student(models.Model):
school_year = models.ForeignKey(
SchoolYear,
blank=True,
null=True,
on_delete=models.SET_NULL
)
student_id = models.IntegerField()
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
address = models.TextField(blank=True)
dob = models.DateField()
allergies = models.CharField(max_length=255, blank=True)
tags = models.ManyToManyField(StudentTag, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
@property
def full_name(self):
return f'{self.first_name} {self.last_name}'
@property
def age(self):
today = date.today()
return today.year - self.dob.year - (
(today.month, today.day) < (self.dob.month, self.dob.day)
)
def __str__(self):
return f'{self.first_name} {self.last_name}'
def get_absolute_url(self):
return reverse('core:student-detail', kwargs={
'year': self.school_year.year,
'pk': self.pk
})
class Meta:
ordering = ['student_id', 'first_name']
class Subject(models.Model):
school_year = models.ForeignKey(
SchoolYear,
blank=True,
null=True,
on_delete=models.SET_NULL
)
name = models.CharField(max_length=250)
description = models.CharField(max_length=250, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('core:subject-detail', kwargs={
'year': self.school_year.year,
'pk': self.pk
})
class Meta:
ordering = ['name']
class Tag(models.Model):
name = models.CharField(max_length=50)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('tag-detail', kwargs={'pk': self.pk})
class Meta:
ordering = ['name']
class Component(models.Model):
QZ = 'QUIZ'
AS = 'ASSIGNMENT'
TS = 'TEST'
CATEGORY_CHOICES = [
(QZ, 'Quiz'),
(AS, 'Assignment'),
(TS, 'Test'),
]
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
category = models.CharField(
max_length=255,
choices=CATEGORY_CHOICES,
default=AS,
)
due_date = models.DateField()
grade_total = models.PositiveIntegerField()
finished_grading = models.BooleanField(default=False)
tags = models.ManyToManyField(Tag, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
@property
def is_due(self):
return True if self.due_date < date.today() else False
@property
def grade_avg(self):
avg = Score.objects.filter(component=self.pk).aggregate(
Avg('value')
)
if avg['value__avg'] is not None:
return round(avg['value__avg'], 2)
else:
return 'No scores yet.'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('core:component-detail', kwargs={
'year': self.school_year.year,
'pk': self.subject.pk,
'component_pk': self.pk
})
class Meta:
ordering = ['due_date']
class Score(models.Model):
component = models.ForeignKey(Component, on_delete=models.CASCADE)
student = models.ForeignKey(Student, on_delete=models.CASCADE)
value = models.PositiveIntegerField()
@property
def grade(self):
return f'{self.value} / {self.component.grade_total}'
@property
def grade_as_percentage(self):
return round(self.value / self.component.grade_total * 100, 2)
def __str__(self):
return f'{self.student} scored: {self.value} / {self.component.grade_total}'
def get_absolute_url(self):
return reverse('core:component-detail', kwargs={
'year': self.component.subject.school_year.year,
'pk': self.component.subject.pk,
'component_pk': self.component.pk
})
class Meta:
ordering = ['student']
class SchoolDay(models.Model):
school_year = models.ForeignKey(
SchoolYear,
blank=True,
null=True,
on_delete=models.SET_NULL
)
date = models.DateField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def get_absolute_url(self):
return reverse('core:schoolday-detail', kwargs={
'year': self.school_year.year,
'pk': self.pk
})
def __str__(self):
return f'{self.date}'
class Meta:
ordering = ['-date']
class AttendanceEntry(models.Model):
PRESENT = 'P'
TARDY = 'T'
ABSENT = 'A'
STATUS_CHOICES = [
(PRESENT, 'Present'),
(TARDY, 'Tardy'),
(ABSENT, 'Absent'),
]
school_day = models.ForeignKey(SchoolDay, on_delete=models.CASCADE)
student = models.ForeignKey(Student, on_delete=models.CASCADE)
status = models.CharField(
max_length=1,
choices=STATUS_CHOICES,
default=PRESENT
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def get_absolute_url(self):
return reverse('core:schoolday-detail', kwargs={
'year': self.school_day.school_year.year,
'pk': self.school_day.pk,
'entry_pk': self.pk
})
def __str__(self):
return f"{self.school_day} | {self.student} | {self.status}"
class Meta:
verbose_name_plural = 'entries'
ordering = ['student']