diff options
Diffstat (limited to 'api/views.py')
-rw-r--r-- | api/views.py | 124 |
1 files changed, 122 insertions, 2 deletions
diff --git a/api/views.py b/api/views.py index c58c9c0..f6aa620 100644 --- a/api/views.py +++ b/api/views.py @@ -13,8 +13,20 @@ # You should have received a copy of the GNU Affero General Public License # along with celcatsanitizer. If not, see <http://www.gnu.org/licenses/>. +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 @@ -23,27 +35,135 @@ 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<year>\d+)/(?P<week>\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) -class GroupViewSet(viewsets.ReadOnlyModelViewSet): + 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(viewsets.ReadOnlyModelViewSet): + +class RoomViewSet(CourseListGroupSet): queryset = Room.objects.all().order_by("name") serializer_class = RoomSerializer + @action( + methods=["get"], + detail=False, + url_path="qsjps/(?P<day>[0-9\-]+)/(?P<begin>[0-9:]+)/(?P<end>[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") |