Newer
Older
from datetime import datetime, timedelta
from django.db.models import Count, Q
from django.http import HttpRequest, HttpResponseNotFound
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.utils import timezone
from guardian.core import ObjectPermissionChecker
from aleksis.core.models import Announcement, Group, Person, Room
from aleksis.core.util.core_helpers import get_site_preferences
from aleksis.core.util.predicates import check_global_permission
from ..models import (
Absence,
LessonPeriod,
LessonSubstitution,
Supervision,
SupervisionSubstitution,
TimePeriod,
)
from .build import build_substitutions_list
from .js import date_unix
if TYPE_CHECKING:
from django.contrib.auth import get_user_model
User = get_user_model() # noqa
def get_el_by_pk(
request: HttpRequest,
type_: str,
pk: int,
Group.objects.prefetch_related("owners", "parent_groups") if prefetch else Group,
pk=pk,
elif type_ == TimetableType.TEACHER.value:
return get_object_or_404(Person, pk=pk)
elif type_ == TimetableType.ROOM.value:
return get_object_or_404(Room, pk=pk)
else:
return HttpResponseNotFound()
def get_substitution_by_id(request: HttpRequest, id_: int, week: int):
lesson_period = get_object_or_404(LessonPeriod, pk=id_)
wanted_week = lesson_period.lesson.get_calendar_week(week)
return LessonSubstitution.objects.filter(
week=wanted_week.week, year=wanted_week.year, lesson_period=lesson_period
def get_supervision_substitution_by_id(request: HttpRequest, id_: int, date: datetime.date):
supervision = get_object_or_404(Supervision, pk=id_)
return SupervisionSubstitution.objects.filter(date=date, supervision=supervision).first()
"""Get the teachers whose timetables are allowed to be seen by current user."""
checker = ObjectPermissionChecker(user)
teachers = (
Person.objects.annotate(lessons_count=Count("lesson_events_as_teacher"))
.filter(lessons_count__gt=0)
.order_by("short_name", "last_name")
)
if not check_global_permission(user, "chronos.view_all_person_timetables"):
checker.prefetch_perms(teachers)
wanted_teachers = set()
for teacher in teachers:
if checker.has_perm("core.view_person_timetable", teacher):
wanted_teachers.add(teacher.pk)
teachers = teachers.filter(Q(pk=user.person.pk) | Q(pk__in=wanted_teachers))
teachers = teachers.distinct()
return teachers
def get_groups(user: "User"):
"""Get the groups whose timetables are allowed to be seen by current user."""
checker = ObjectPermissionChecker(user)
groups = (
Group.objects.for_current_school_term_or_all()
.annotate(
lessons_count=Count("lesson_events"),
child_lessons_count=Count("child_groups__lesson_events"),
)
.filter(Q(lessons_count__gt=0) | Q(child_lessons_count__gt=0))
)
group_types = get_site_preferences()["chronos__group_types_timetables"]
if group_types:
groups = groups.filter(group_type__in=group_types)
groups = groups.order_by("short_name", "name")
if not check_global_permission(user, "chronos.view_all_group_timetables"):
checker.prefetch_perms(groups)
wanted_classes = set()
for _class in groups:
if checker.has_perm("core.view_group_timetable", _class):
wanted_classes.add(_class.pk)
groups = groups.filter(
Q(pk__in=wanted_classes) | Q(members=user.person) | Q(owners=user.person)
)
groups = groups.filter(Q(pk=user.person.primary_group.pk))
groups = groups.distinct()
return groups
"""Get the rooms whose timetables are allowed to be seen by current user."""
checker = ObjectPermissionChecker(user)
rooms = (
Room.objects.annotate(lessons_count=Count("lesson_events"))
.filter(lessons_count__gt=0)
.order_by("short_name", "name")
)
if not check_global_permission(user, "chronos.view_all_room_timetables"):
checker.prefetch_perms(rooms)
wanted_rooms = set()
for room in rooms:
if checker.has_perm("core.view_room_timetable", room):
wanted_rooms.add(room.pk)
rooms = rooms.filter(Q(pk__in=wanted_rooms))
rooms = rooms.distinct()
return rooms
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
def get_substitutions_context_data(
request: Optional[HttpRequest] = None,
year: Optional[int] = None,
month: Optional[int] = None,
day: Optional[int] = None,
is_print: bool = False,
number_of_days: Optional[int] = None,
show_header_box: Optional[bool] = None,
):
"""Get context data for the substitutions table."""
context = {}
if day:
wanted_day = timezone.datetime(year=year, month=month, day=day).date()
wanted_day = TimePeriod.get_next_relevant_day(wanted_day)
else:
wanted_day = TimePeriod.get_next_relevant_day(timezone.now().date(), timezone.now().time())
day_number = (
number_of_days or get_site_preferences()["chronos__substitutions_print_number_of_days"]
)
show_header_box = (
show_header_box
if show_header_box is not None
else get_site_preferences()["chronos__substitutions_show_header_box"]
)
day_contexts = {}
if is_print:
next_day = wanted_day
day_contexts[next_day] = {"day": next_day}
next_day = TimePeriod.get_next_relevant_day(next_day + timedelta(days=1))
else:
day_contexts = {wanted_day: {"day": wanted_day}}
for day in day_contexts:
subs = build_substitutions_list(day)
day_contexts[day]["substitutions"] = subs
day_contexts[day]["announcements"] = Announcement.for_timetables().on_date(day)
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
if show_header_box:
subs = LessonSubstitution.objects.on_day(day).order_by(
"lesson_period__lesson__groups", "lesson_period__period"
)
absences = Absence.objects.on_day(day)
day_contexts[day]["absent_teachers"] = absences.absent_teachers()
day_contexts[day]["absent_groups"] = absences.absent_groups()
day_contexts[day]["affected_teachers"] = subs.affected_teachers()
affected_groups = subs.affected_groups()
if get_site_preferences()["chronos__affected_groups_parent_groups"]:
groups_with_parent_groups = affected_groups.filter(parent_groups__isnull=False)
groups_without_parent_groups = affected_groups.filter(parent_groups__isnull=True)
affected_groups = Group.objects.filter(
Q(child_groups__pk__in=groups_with_parent_groups.values_list("pk", flat=True))
| Q(pk__in=groups_without_parent_groups.values_list("pk", flat=True))
).distinct()
day_contexts[day]["affected_groups"] = affected_groups
if not is_print:
context = day_contexts[wanted_day]
context["datepicker"] = {
"date": date_unix(wanted_day),
"dest": reverse("substitutions"),
}
context["url_prev"], context["url_next"] = TimePeriod.get_prev_next_by_day(
wanted_day, "substitutions_by_date"
)
else:
context["days"] = day_contexts
return context