Skip to content

Commit c31dc1b

Browse files
authored
Merge pull request #20 from DevOps-Cloud-Team5/SCRUM-40-attendence
set attendence
2 parents a57202b + 5f1e6af commit c31dc1b

File tree

4 files changed

+82
-13
lines changed

4 files changed

+82
-13
lines changed

api/models.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def clean(self):
5050
super().clean()
5151
self.email = self.__class__.objects.normalize_email(self.email)
5252

53-
def get_classes(self):
53+
def get_enrolled_courses(self):
5454
return [uc.course for uc in UserCourse.objects.filter(user__id=self.id)]
5555

5656
class LectureTypes(models.TextChoices):

api/serializers.py

+19-3
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class AddLectureSerializer(serializers.Serializer):
102102

103103
def validate(self, attrs):
104104
start_time, end_time = attrs["start_time"], attrs["end_time"]
105+
105106
if start_time > end_time:
106107
raise serializers.ValidationError({"error": f"end_time has to be after start_time"})
107108

@@ -115,8 +116,23 @@ def validate(self, attrs):
115116

116117
course : Course = self.context.get("course")
117118
for lecture in course.get_lectures():
118-
for timestamp in [start_time, end_time]:
119-
if lecture.start_time < timestamp and timestamp < lecture.end_time:
120-
raise serializers.ValidationError({"error": "there is already an active lecture during this time range"})
119+
if lecture.start_time <= start_time and start_time < lecture.end_time:
120+
raise serializers.ValidationError({"error": "there is already an active lecture during this time range"})
121+
if lecture.start_time < end_time and end_time <= lecture.end_time:
122+
raise serializers.ValidationError({"error": "there is already an active lecture during this time range"})
123+
return attrs
124+
125+
class SetAttendenceTeacherSerializer(serializers.Serializer):
126+
usernames = serializers.ListField(required=True, allow_empty=False, child=serializers.CharField(max_length=150))
127+
128+
def validate_attendence(self, username):
129+
user_query = User.objects.all().filter(username=username)
130+
if not user_query: raise serializers.ValidationError({"error": f"user '{username}' does not exist"})
131+
if user_query[0].role != AccountRoles.STUDENT: raise serializers.ValidationError({"error": f"cannot set the attendence of a non-student: '{username}' is {user_query[0].role}"})
121132

133+
course : Course = self.context.get("course")
134+
if not course.is_user_enrolled(user_query[0]): raise serializers.ValidationError({"error": f"user '{username}' is not enrolled in '{course.course_name}'"})
135+
136+
def validate(self, attrs):
137+
for username in attrs["usernames"]: self.validate_enroll(username)
122138
return attrs

api/urls.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@
2020
AddLectureView,
2121
GetCourseLecturesView,
2222
GetLectureView,
23+
GetScheduleView,
2324
MassEnrollCourseView,
25+
SetStudentAttView,
26+
SetTeacherAttView,
2427
test,
2528
genAdmin,
2629

@@ -72,9 +75,10 @@
7275
# path('course/lecture/<pk>/delete', GetCourseByName.as_view(), name='lecture_add'),
7376

7477
path('lecture/<pk>/get', GetLectureView.as_view(), name='lecture_get'),
75-
path('lecture/<pk>/student_att', GetLectureView.as_view(), name='lecture_get'),
76-
path('lecture/<pk>/teacher_att', GetLectureView.as_view(), name='lecture_get'),
78+
path('lecture/<pk>/student_att', SetStudentAttView.as_view(), name='lecture_att_student'),
79+
path('lecture/<pk>/teacher_att', SetTeacherAttView.as_view(), name='lecture_att_teacher'),
7780

81+
path('schedule/get', GetScheduleView.as_view(), name='schedule_get'),
7882

7983
# Documentation
8084
path('schema/', SpectacularAPIView.as_view(), name='schema'),

api/views.py

+56-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import datetime
12
import os
23
from django.http import JsonResponse
34
from django.contrib.auth import get_user_model
@@ -14,7 +15,7 @@
1415

1516
from .permissions import IsTeacher, IsAdmin, IsStudent
1617
from .models import Course, AccountRoles, CourseLecture
17-
from .serializers import AddLectureSerializer, CustomTokenSerializer, CreateUserSerializer, LectureSerializer, MassEnrollSerializer, UserSerializer, CourseCreateSerializer, CourseSerializer
18+
from .serializers import AddLectureSerializer, CustomTokenSerializer, CreateUserSerializer, LectureSerializer, MassEnrollSerializer, SetAttendenceTeacherSerializer, UserSerializer, CourseCreateSerializer, CourseSerializer
1819

1920
import pdb
2021

@@ -195,12 +196,15 @@ class GetCoursesAll(generics.ListAPIView):
195196
queryset = Course.objects.all()
196197
serializer_class = CourseSerializer
197198

198-
def get(self, _):
199+
def get(self, request):
199200
queryset = self.get_queryset()
200201
serializer = self.serializer_class(queryset, many=True)
201202
if len(serializer.data) == 0:
202203
return Response({"error": "no courses found"}, status=status.HTTP_404_NOT_FOUND)
203204
else:
205+
for course_serialized in serializer.data:
206+
course : Course = queryset.filter(pk=course_serialized["id"])[0]
207+
course_serialized["enrolled"] = course.is_user_enrolled(user=request.user)
204208
return Response(serializer.data, status=status.HTTP_200_OK)
205209

206210
class EnrollCourseView(generics.GenericAPIView):
@@ -261,7 +265,7 @@ class GetCourseLecturesView(generics.ListAPIView):
261265

262266
def get(self, _, *args, **kwargs):
263267
course : Course = self.get_object()
264-
lectures = course.get_lectures()
268+
lectures = course.get_lectures()
265269
serializer = LectureSerializer(lectures, many=True)
266270
if len(serializer.data) == 0:
267271
return Response({"error": "no lectures found"}, status=status.HTTP_404_NOT_FOUND)
@@ -282,7 +286,9 @@ def post(self, request, *args, **kwargs):
282286
result.is_valid(raise_exception=True)
283287

284288
data = result.data
285-
course.add_lecture_to_course(data["start_time"], data["end_time"], data["lecture_type"])
289+
start_time = datetime.datetime.fromisoformat(data["start_time"])
290+
end_time = datetime.datetime.fromisoformat(data["end_time"])
291+
course.add_lecture_to_course(start_time, end_time, data["lecture_type"])
286292

287293
return Response({"ok": f"successfully created lecture"}, status=status.HTTP_200_OK)
288294

@@ -310,9 +316,52 @@ class SetStudentAttView(generics.GenericAPIView):
310316

311317
def post(self, request, *args, **kwargs):
312318
if request.user.role != AccountRoles.STUDENT:
313-
return Response({"error": f"only a student can set their attendence to a lecture"}, status=status.HTTP_200_OK)
319+
return Response({"error": f"cannot set the attendence of a non-student"}, status=status.HTTP_200_OK)
314320

315-
course : CourseLecture = self.get_object()
321+
lecture : CourseLecture = self.get_object()
322+
lecture.set_attendence_user(request.user, teacher=False)
316323

324+
return Response({"ok": f"successfully set attendence"}, status=status.HTTP_200_OK)
325+
326+
class SetTeacherAttView(generics.GenericAPIView):
327+
authentication_classes = [JWTAuthentication]
328+
permission_classes = [IsTeacher]
329+
lookup_field = 'pk'
330+
331+
queryset = CourseLecture.objects.all()
332+
serializer_class = CourseLecture
333+
334+
def post(self, request, *args, **kwargs):
335+
lecture : CourseLecture = self.get_object()
336+
result = SetAttendenceTeacherSerializer(data=request.data, context={ "course": lecture.course })
337+
result.is_valid(raise_exception=True)
317338

318-
return Response({"ok": f"successfully set attendence"}, status=status.HTTP_200_OK)
339+
queryset = User.objects.all()
340+
usernames = result.data["usernames"]
341+
for username in usernames:
342+
user = queryset.filter(username=username)[0]
343+
lecture.set_attendence_user(user, teacher=True)
344+
345+
return Response({"ok": f"succesfully set attendence for {len(usernames)} students"}, status=status.HTTP_200_OK)
346+
347+
class GetScheduleView(generics.GenericAPIView):
348+
authentication_classes = [JWTAuthentication]
349+
permission_classes = [IsStudent]
350+
351+
def get(self, request, *args, **kwargs):
352+
user = User.objects.all().filter(username=request.user.username)[0]
353+
courses = user.get_enrolled_courses()
354+
all_lectures = []
355+
for course in courses:
356+
lectures_obj = course.get_lectures()
357+
lectures = LectureSerializer(lectures_obj, many=True)
358+
for i, lecture_obj in enumerate(lectures_obj):
359+
att = lecture_obj.get_attendence_user(user)
360+
lectures.data[i]["attended_student"] = att.attended_student if att is not None else False
361+
lectures.data[i]["attended_teacher"] = att.attended_teacher if att is not None else False
362+
all_lectures += lectures.data
363+
364+
# Sort chronological order
365+
all_lectures.sort(key= lambda x : datetime.datetime.fromisoformat(x["start_time"]))
366+
367+
return Response(all_lectures)

0 commit comments

Comments
 (0)