# Copyright (C) 2019 Alban Gruin # # celcatsanitizer is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # celcatsanitizer is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with celcatsanitizer. If not, see . import datetime from django.db.models import Count from django.db.models.functions import ExtractWeek, ExtractYear from django.utils import timezone from rest_framework import viewsets from rest_framework.decorators import action, detail_route from rest_framework.response import Response from ..forms import QSJPSForm from ..models import Course, Group, Room, Source, Timetable, Year from ..utils import get_current_or_next_week, get_week from .serializers import CourseSerializer, GroupSerializer, RoomSerializer, \ SourceSerializer, TimetableSerializer, YearSerializer class YearViewSet(viewsets.ReadOnlyModelViewSet): queryset = Year.objects.all().order_by("name") serializer_class = YearSerializer @detail_route(methods=["get"], url_path="timetables") def timetable_list(self, request, pk): year = self.get_object() timetables = Timetable.objects.filter(year=year).distinct() \ .order_by("name") timetables_json = TimetableSerializer( self.paginate_queryset(timetables), many=True) return self.get_paginated_response(timetables_json.data) class SourceViewSet(viewsets.ReadOnlyModelViewSet): queryset = Source.objects.all().order_by("pk") serializer_class = SourceSerializer @detail_route(methods=["get"], url_path="timetables") def timetable_list(self, request, pk): source = self.get_object() timetables = Timetable.objects.filter(source=source).distinct() \ .order_by("name") timetables_json = TimetableSerializer( self.paginate_queryset(timetables), many=True) return self.get_paginated_response(timetables_json.data) class TimetableViewSet(viewsets.ReadOnlyModelViewSet): queryset = Timetable.objects.all().select_related("source") \ .order_by("year", "name") serializer_class = TimetableSerializer @detail_route(methods=["get"], url_path="groups") def group_list(self, request, pk): timetable = self.get_object() groups = Group.objects.filter(source=timetable.source).distinct() \ .order_by("name") groups_json = GroupSerializer(self.paginate_queryset(groups), many=True) return self.get_paginated_response(groups_json.data) class CourseListGroupSet(viewsets.ReadOnlyModelViewSet): @detail_route(methods=["get"], url_path="courses") def course_list(self, request, pk): obj = self.get_object() courses = Course.objects.get_courses(obj).prefetch_related("groups") courses_json = CourseSerializer(self.paginate_queryset(courses), many=True) return self.get_paginated_response(courses_json.data) @detail_route(methods=["get"], url_path="courses/weeks/current") def current_week(self, request, pk): obj = self.get_object() start, end = get_week(*get_current_or_next_week()) courses = Course.objects.get_courses(obj, begin__gte=start, end__lt=end) \ .prefetch_related("groups") courses_json = CourseSerializer(self.paginate_queryset(courses), many=True) return self.get_paginated_response(courses_json.data) @detail_route(methods=["get"], url_path="courses/weeks/(?P\d+)/(?P\d+)") def other_week(self, request, pk, year, week): obj = self.get_object() errors = {} if not year.isdigit(): errors["year"] = "Rentrez une année valide" if not week.isdigit() or not 0 < int(week) <= 53: errors["week"] = "Rentrez une semaine valide" if errors: return Response(errors, status=400) start, end = get_week(int(year), int(week)) courses = Course.objects.get_courses(obj, begin__gte=start, end__lt=end) \ .prefetch_related("groups") courses_json = CourseSerializer(self.paginate_queryset(courses), many=True) return self.get_paginated_response(courses_json.data) class GroupViewSet(CourseListGroupSet): queryset = Group.objects.all().order_by("name") serializer_class = GroupSerializer @detail_route(methods=["get"], url_path="courses/weeks") def weeks(self, request, pk): group = self.get_object() groups = Group.objects.get_parents(group) courses = Course.objects.filter(groups__in=groups) \ .order_by("year", "week") \ .annotate(year=ExtractYear("begin"), week=ExtractWeek("begin")) \ .values("year", "week") \ .annotate(c=Count("*")) weeks = [get_week(course["year"], course["week"])[0] for course in courses] return Response(weeks) class RoomViewSet(CourseListGroupSet): queryset = Room.objects.all().order_by("name") serializer_class = RoomSerializer @action( methods=["get"], detail=False, url_path="qsjps/(?P[0-9\-]+)/(?P[0-9:]+)/(?P[0-9:]+)") def qsjps(self, request, day, begin, end): form = QSJPSForm({"day": day, "begin": begin, "end": end}) if not form.is_valid(): return Response(form.errors, status=400) day = form.cleaned_data["day"] begin_hour = form.cleaned_data["begin"] end_hour = form.cleaned_data["end"] begin = timezone.make_aware(datetime.datetime.combine(day, begin_hour)) end = timezone.make_aware(datetime.datetime.combine(day, end_hour)) rooms = Room.objects.qsjps(begin, end) rooms_json = RoomSerializer(rooms, many=True) return Response(rooms_json.data) class CourseViewSet(viewsets.ReadOnlyModelViewSet): queryset = Course.objects.all().prefetch_related("groups", "rooms") serializer_class = CourseSerializer