2023-08-15 00:45:00 +08:00
|
|
|
from rest_framework import serializers, exceptions
|
2023-06-26 23:50:55 +08:00
|
|
|
from .models import StudentStatus
|
2023-07-09 19:00:47 +08:00
|
|
|
from subjects.models import Subject
|
|
|
|
from django.contrib.gis.geos import Point
|
2023-07-14 23:55:54 +08:00
|
|
|
from drf_extra_fields.geo_fields import PointField
|
|
|
|
from landmarks.models import Landmark
|
2023-09-28 21:03:34 +08:00
|
|
|
from study_groups.models import StudyGroup
|
2023-06-26 22:06:05 +08:00
|
|
|
|
|
|
|
|
|
|
|
class StudentStatusSerializer(serializers.ModelSerializer):
|
2023-07-09 19:00:47 +08:00
|
|
|
subject = serializers.SlugRelatedField(
|
2023-09-03 17:46:36 +08:00
|
|
|
queryset=Subject.objects.all(), slug_field='name', required=True, many=False)
|
2023-07-01 16:09:20 +08:00
|
|
|
user = serializers.CharField(source='user.full_name', read_only=True)
|
2023-08-06 14:35:39 +08:00
|
|
|
location = PointField(required=True)
|
2023-07-14 23:55:54 +08:00
|
|
|
landmark = serializers.SlugRelatedField(
|
|
|
|
queryset=Landmark.objects.all(), many=False, slug_field='name', required=False, allow_null=True)
|
2023-08-15 18:53:10 +08:00
|
|
|
|
|
|
|
timestamp = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
|
2023-08-07 15:36:37 +08:00
|
|
|
active = serializers.BooleanField(required=True)
|
2023-09-28 21:03:34 +08:00
|
|
|
study_group = serializers.SlugRelatedField(queryset=StudyGroup.objects.all(
|
|
|
|
), many=False, slug_field='name', required=False, allow_null=True)
|
2023-06-27 13:40:31 +08:00
|
|
|
|
2023-06-26 22:06:05 +08:00
|
|
|
class Meta:
|
|
|
|
model = StudentStatus
|
2023-08-15 18:53:10 +08:00
|
|
|
fields = ['user', 'subject', 'location',
|
2023-09-01 14:09:19 +08:00
|
|
|
'timestamp', 'active', 'study_group', 'landmark']
|
2023-07-14 23:55:54 +08:00
|
|
|
read_only_fields = ['user', 'landmark']
|
2023-06-26 23:50:55 +08:00
|
|
|
|
|
|
|
def create(self, validated_data):
|
|
|
|
user = self.context['request'].user
|
2023-06-27 13:40:31 +08:00
|
|
|
student_status = StudentStatus.objects.create(
|
2023-06-26 23:50:55 +08:00
|
|
|
user=user, defaults=validated_data)
|
|
|
|
return student_status
|
2023-07-01 16:09:20 +08:00
|
|
|
|
2023-06-27 13:40:31 +08:00
|
|
|
def update(self, instance, validated_data):
|
2023-08-07 15:16:57 +08:00
|
|
|
|
2023-06-27 13:40:31 +08:00
|
|
|
active = validated_data.get('active', None)
|
2023-09-29 11:33:48 +08:00
|
|
|
# If status is set as false in PATCH, clear the student status
|
2023-08-07 15:37:47 +08:00
|
|
|
if active is False:
|
2023-07-09 19:00:47 +08:00
|
|
|
validated_data['location'] = Point(0, 0)
|
2023-06-27 13:40:31 +08:00
|
|
|
validated_data['subject'] = None
|
2023-07-14 23:55:54 +08:00
|
|
|
validated_data['landmark'] = None
|
2023-09-26 18:59:33 +08:00
|
|
|
validated_data['study_group'] = None
|
2023-09-29 11:33:48 +08:00
|
|
|
# If status is set as true in PATCH
|
|
|
|
elif active is True:
|
|
|
|
# Check if subject is attached in PATCH, if not return error
|
2023-08-15 00:45:00 +08:00
|
|
|
if 'subject' not in validated_data:
|
|
|
|
raise serializers.ValidationError(
|
|
|
|
{'subject': 'This field may not be empty if active is true'})
|
2023-09-29 11:33:48 +08:00
|
|
|
# Then check the location if it matches any landmarks
|
2023-07-14 23:55:54 +08:00
|
|
|
for landmark in Landmark.objects.all():
|
|
|
|
if landmark.location.contains(validated_data['location']):
|
|
|
|
validated_data['landmark'] = landmark
|
|
|
|
break
|
2023-06-27 13:40:31 +08:00
|
|
|
|
2023-09-29 11:33:48 +08:00
|
|
|
# Get new value for study group in PATCH
|
|
|
|
study_group = validated_data.get('study_group', None)
|
|
|
|
# Get old value in db
|
|
|
|
old_study_group = instance.study_group
|
|
|
|
|
|
|
|
# Commit changes
|
|
|
|
instance = super().update(instance, validated_data)
|
|
|
|
|
|
|
|
# If student has left study group, check if the old study_group no longer has any students
|
|
|
|
if study_group is None and old_study_group is not None:
|
|
|
|
if not old_study_group.students.exists():
|
|
|
|
# If there are no students left in the old StudyGroup, delete it
|
|
|
|
old_study_group.delete()
|
|
|
|
|
|
|
|
return instance
|
2023-09-01 14:09:19 +08:00
|
|
|
|
|
|
|
|
|
|
|
class StudentStatusLocationSerializer(serializers.ModelSerializer):
|
2023-09-02 13:24:55 +08:00
|
|
|
user = serializers.CharField(source='user.full_name', read_only=True)
|
|
|
|
subject = serializers.SlugRelatedField(
|
|
|
|
queryset=Subject.objects.all(), slug_field='name', required=True)
|
2023-09-01 14:09:19 +08:00
|
|
|
location = PointField(required=True)
|
2023-09-02 13:24:55 +08:00
|
|
|
distance = serializers.SerializerMethodField()
|
|
|
|
landmark = serializers.SlugRelatedField(
|
|
|
|
queryset=Landmark.objects.all(), many=False, slug_field='name', required=False, allow_null=True)
|
2023-09-28 21:03:34 +08:00
|
|
|
study_group = serializers.SlugRelatedField(queryset=StudyGroup.objects.all(
|
|
|
|
), many=False, slug_field='name', required=False, allow_null=True)
|
2023-09-01 14:09:19 +08:00
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = StudentStatus
|
2023-09-02 13:24:55 +08:00
|
|
|
fields = ['user', 'location', 'distance',
|
|
|
|
'subject', 'active', 'study_group', 'landmark']
|
|
|
|
read_only_fields = ['user', 'distance', 'subject',
|
|
|
|
'active', 'study_group', 'landmark']
|
|
|
|
|
|
|
|
def get_distance(self, obj):
|
|
|
|
return obj.distance.km
|
|
|
|
|
|
|
|
def to_representation(self, instance):
|
|
|
|
representation = super().to_representation(instance)
|
|
|
|
representation['distance'] = self.get_distance(instance)
|
|
|
|
return representation
|