Skip to content
Snippets Groups Projects
Verified Commit fc19c951 authored by Jonathan Weth's avatar Jonathan Weth :keyboard:
Browse files

Update models

parent 428c5a8c
No related branches found
No related tags found
3 merge requests!352Draft: Resolve "Add dialog with each lesson's students",!350Resolve "Add simple course book list",!339Draft: Resolve "Migrate to new data model"
......@@ -35,6 +35,8 @@ from aleksis.apps.chronos.mixins import WeekRelatedMixin
from aleksis.apps.chronos.models import Event, ExtraLesson, LessonEvent, LessonPeriod, TimePeriod
from aleksis.apps.chronos.util.format import format_m2m
from aleksis.apps.cursus.models import Course, Subject
from aleksis.apps.kolego.models import Absence as KolegoAbsence
from aleksis.apps.kolego.models import AbsenceReason
from aleksis.core.data_checks import field_validation_data_check_factory
from aleksis.core.mixins import ExtensibleModel, GlobalPermissionModel
from aleksis.core.models import CalendarEvent, Group, SchoolTerm
......@@ -451,11 +453,21 @@ class Documentation(CalendarEvent):
# FIXME: DataCheck
course = models.ForeignKey(
Course, models.CASCADE, related_name="documentations", blank=True, null=True, verbose_name=_("Course")
Course,
models.CASCADE,
related_name="documentations",
blank=True,
null=True,
verbose_name=_("Course"),
)
lesson_event = models.ForeignKey(
LessonEvent, models.CASCADE, related_name="documentation", blank=True, null=True, verbose_name=_("Lesson Event")
LessonEvent,
models.CASCADE,
related_name="documentation",
blank=True,
null=True,
verbose_name=_("Lesson Event"),
)
subject = models.ForeignKey(
......@@ -499,26 +511,29 @@ class Documentation(CalendarEvent):
]
class Participation(RegisterObjectRelatedMixin, ExtensibleModel):
"""A personal note about a single person.
class Participation(ExtensibleModel):
"""A participation record about a single person.
Used in the class register to note participation and remarks about a student
Used in the class register to note participation of a student
in a documented unit (e.g. a single lesson event or a custom time frame; see Documentation).
"""
# FIXME: DataChecks
person = models.ForeignKey("core.Person", models.CASCADE, related_name="participations", verbose_name=_("Person"))
groups_of_person = models.ManyToManyField("core.Group", related_name="+", verbose_name=_("Groups of Person"))
person = models.ForeignKey(
"core.Person", models.CASCADE, related_name="participations", verbose_name=_("Person")
)
groups_of_person = models.ManyToManyField(
"core.Group", related_name="+", verbose_name=_("Groups of Person")
)
documentation = models.ForeignKey(
Documentation, models.CASCADE, related_name="participations", verbose_name=_("Documentation")
Documentation,
models.CASCADE,
related_name="participations",
verbose_name=_("Documentation"),
)
remarks = models.CharField(max_length=255, blank=True, verbose_name=_("Remarks"))
extra_marks = models.ManyToManyField("ExtraMark", blank=True, verbose_name=_("Extra Marks"))
def __str__(self) -> str:
return f"{self.documentation}, {self.person}"
......@@ -538,6 +553,88 @@ class Participation(RegisterObjectRelatedMixin, ExtensibleModel):
]
class Absence(ExtensibleModel):
"""An absence record about a single person.
Used in the class register to note absence of a student
in a documented unit (e.g. a single lesson event or a custom time frame; see Documentation).
"""
# FIXME: DataChecks
reason = models.ForeignKey(
AbsenceReason, verbose_name=_("Absence Reason"), on_delete=models.CASCADE
)
person = models.ForeignKey(
"core.Person", models.CASCADE, related_name="lesson_absences", verbose_name=_("Person")
)
groups_of_person = models.ManyToManyField(
"core.Group", related_name="+", verbose_name=_("Groups of Person")
)
documentation = models.ForeignKey(
Documentation, models.CASCADE, related_name="absences", verbose_name=_("Documentation")
)
excused = models.BooleanField(default=False, verbose_name=_("Excused"))
base_absence = models.ForeignKey(
KolegoAbsence, models.SET_NULL, related_name="absences", verbose_name=_("Base Absence")
)
def __str__(self) -> str:
return f"{self.documentation}, {self.person}"
class Meta:
verbose_name = _("Absence note")
verbose_name_plural = _("Absence notes")
ordering = [
"documentation",
"person__last_name",
"person__first_name",
]
constraints = [
models.UniqueConstraint(
fields=("documentation", "person"),
name="unique_absence_per_documentation",
),
]
class NewPersonalNote(ExtensibleModel):
person = models.ForeignKey(
"core.Person", models.CASCADE, related_name="new_personal_notes", verbose_name=_("Person")
)
documentation = models.ForeignKey(
Documentation,
models.CASCADE,
related_name="personal_notes",
verbose_name=_("Documentation"),
blank=True,
null=True,
)
note = models.TextField(blank=True, verbose_name=_("Note"))
extra_mark = models.ForeignKey(
ExtraMark, on_delete=models.CASCADE, blank=True, null=True, verbose_name=_("Extra Mark")
)
def __str__(self) -> str:
return f"{self.person}, {self.note}, {self.extra_mark}"
class Meta:
verbose_name = _("Personal Note")
verbose_name_plural = _("Personal Notes")
constraints = [
models.CheckConstraint(
check=~Q(note="") | Q(extra_mark__isnull=False),
name="unique_absence_per_documentation",
),
]
class GroupRole(ExtensibleModel):
data_checks = [field_validation_data_check_factory("alsijil", "GroupRole", "icon")]
......
......@@ -356,14 +356,12 @@ view_register_objects_list_predicate = has_person & (
add_perm("alsijil.view_register_objects_list_rule", view_register_objects_list_predicate)
view_documentation_predicate = has_person & (
has_global_perm("alsijil.view_documentation")
| can_view_documentation
has_global_perm("alsijil.view_documentation") | can_view_documentation
)
add_perm("alsijil.view_documentation_rule", view_documentation_predicate)
edit_documentation_predicate = has_person & (
has_global_perm("alsijil.change_documentation")
| can_edit_documentation
has_global_perm("alsijil.change_documentation") | can_edit_documentation
)
add_perm("alsijil.edit_documentation_rule", edit_documentation_predicate)
add_perm("alsijil.delete_documentation_rule", edit_documentation_predicate)
from django.db.models.query_utils import Q
import graphene
from graphene_django import DjangoObjectType
from django.db.models.query_utils import Q
from aleksis.core.schema.base import DjangoFilterMixin, FilterOrderList
from ..models import Documentation, Participation
from .documentation import (
DocumentationType,
DocumentationCreateMutation,
DocumentationBatchCreateMutation,
DocumentationBatchPatchMutation,
DocumentationCreateMutation,
DocumentationDeleteMutation,
DocumentationBatchPatchMutation
DocumentationType,
)
class Query(graphene.ObjectType):
documentations = FilterOrderList(DocumentationType)
documentations_by_course_id = FilterOrderList(DocumentationType, course_id=graphene.ID(required=True))
documentations_by_course_id = FilterOrderList(
DocumentationType, course_id=graphene.ID(required=True)
)
def resolve_documentations_by_course_id(root, info, course_id, **kwargs):
documentations = Documentation.objects.filter(Q(course__pk=course_id) | Q(lesson_event__course__pk=course_id))
documentations = Documentation.objects.filter(
Q(course__pk=course_id) | Q(lesson_event__course__pk=course_id)
)
return documentations
......
......@@ -24,7 +24,19 @@ from ..models import Documentation
class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectType):
class Meta:
model = Documentation
fields = ("id", "course", "lesson_event", "subject", "topic", "homework", "group_note", "datetime_start", "datetime_end", "date_start", "date_end")
fields = (
"id",
"course",
"lesson_event",
"subject",
"topic",
"homework",
"group_note",
"datetime_start",
"datetime_end",
"date_start",
"date_end",
)
filter_fields = {
"id": ["exact", "lte", "gte"],
"course__name": ["exact"],
......@@ -38,15 +50,49 @@ class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectTyp
class DocumentationCreateMutation(DjangoCreateMutation):
class Meta:
model = Documentation
fields = ("course", "lesson_event", "subject", "topic", "homework", "group_note", "datetime_start", "datetime_end", "date_start", "date_end")
optional_fields = ("course", "lesson_event", "subject", "topic", "homework", "group_note", "datetime_start", "datetime_end", "date_start", "date_end")
fields = (
"course",
"lesson_event",
"subject",
"topic",
"homework",
"group_note",
"datetime_start",
"datetime_end",
"date_start",
"date_end",
)
optional_fields = (
"course",
"lesson_event",
"subject",
"topic",
"homework",
"group_note",
"datetime_start",
"datetime_end",
"date_start",
"date_end",
)
permissions = ("alsijil.add_documentation",) # FIXME
class DocumentationBatchCreateMutation(DjangoBatchCreateMutation):
class Meta:
model = Documentation
fields = ("id", "course", "lesson_event", "subject", "topic", "homework", "group_note", "datetime_start", "datetime_end", "date_start", "date_end")
fields = (
"id",
"course",
"lesson_event",
"subject",
"topic",
"homework",
"group_note",
"datetime_start",
"datetime_end",
"date_start",
"date_end",
)
permissions = ("alsijil.add_documentation",) # FIXME
......@@ -58,5 +104,17 @@ class DocumentationDeleteMutation(DeleteMutation):
class DocumentationBatchPatchMutation(PermissionBatchPatchMixin, DjangoBatchPatchMutation):
class Meta:
model = Documentation
fields = ("id", "course", "lesson_event", "subject", "topic", "homework", "group_note", "datetime_start", "datetime_end", "date_start", "date_end")
fields = (
"id",
"course",
"lesson_event",
"subject",
"topic",
"homework",
"group_note",
"datetime_start",
"datetime_end",
"date_start",
"date_end",
)
permissions = ("alsijil.edit_documentation_rule",) # FIXME
......@@ -312,10 +312,7 @@ def is_lesson_event_teacher(user: User, obj: LessonEvent):
or a teacher of the course, if the lesson event has one.
"""
if obj:
return (
obj.course and is_course_teacher(user, obj)
or user.person in obj.all_teachers()
)
return obj.course and is_course_teacher(user, obj) or user.person in obj.all_teachers()
return False
......@@ -355,7 +352,9 @@ def can_view_documentation(user: User, obj: Documentation):
if obj.course:
return is_course_teacher(user, obj.course) | is_course_member(user, obj.course)
if obj.lesson_event:
return is_lesson_event_teacher(user, obj.course) | is_lesson_event_member(user, obj.course)
return is_lesson_event_teacher(user, obj.course) | is_lesson_event_member(
user, obj.course
)
return False
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment