aboutsummaryrefslogtreecommitdiff
path: root/api/views.py
diff options
context:
space:
mode:
Diffstat (limited to 'api/views.py')
-rw-r--r--api/views.py191
1 files changed, 191 insertions, 0 deletions
diff --git a/api/views.py b/api/views.py
new file mode 100644
index 0000000..2459455
--- /dev/null
+++ b/api/views.py
@@ -0,0 +1,191 @@
+# 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 <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
+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
+
+ @action(detail=True, 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
+
+ @action(detail=True, 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
+
+ @action(detail=True, 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):
+ @action(detail=True, 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)
+
+ def __get_courses(self, obj, start, end):
+ 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)
+
+ @action(detail=True, methods=["get"], url_path="courses/days/current")
+ def current_day(self, request, pk):
+ obj = self.get_object()
+ start = datetime.date.today()
+ end = start + datetime.timedelta(days=1)
+ return self.__get_courses(obj, start, end)
+
+ @action(detail=True, methods=["get"],
+ url_path="courses/days/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)")
+ def other_day(self, request, pk, year, month, day):
+ obj = self.get_object()
+
+ try:
+ start = datetime.date(int(year), int(month), int(day))
+ except ValueError as v:
+ errors = {}
+ message = v.args[0]
+ if message.split(" ")[0] == "month":
+ errors["month"] = "Rentrez un mois invalide"
+ else:
+ errors["day"] = "Numéro de jour invalide pour le mois"
+ return Response(errors, status=400)
+
+ end = start + datetime.timedelta(days=1)
+ return self.__get_courses(obj, start, end)
+
+ @action(detail=True, 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())
+ return self.__get_courses(obj, start, end)
+
+ @action(detail=True, 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)
+
+ return self.__get_courses(obj, *get_week(int(year), int(week)))
+
+
+class GroupViewSet(CourseListGroupSet):
+ queryset = Group.objects.all().order_by("name")
+ serializer_class = GroupSerializer
+
+ @action(detail=True, 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<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")
+ serializer_class = CourseSerializer