Files
n3wt-school/Back-End/Subscriptions/serializers.py
2025-05-21 20:44:37 +02:00

442 lines
18 KiB
Python

from rest_framework import serializers
from .models import (
RegistrationFileGroup,
RegistrationForm,
Student,
Guardian,
Sibling,
Language,
RegistrationSchoolFileMaster,
RegistrationSchoolFileTemplate,
RegistrationParentFileMaster,
RegistrationParentFileTemplate,
AbsenceManagement
)
from School.models import SchoolClass, Fee, Discount, FeeType
from School.serializers import FeeSerializer, DiscountSerializer
from Auth.models import ProfileRole, Profile
from Auth.serializers import ProfileSerializer, ProfileRoleSerializer
from GestionMessagerie.models import Messagerie
from GestionNotification.models import Notification
from N3wtSchool import settings
from django.utils import timezone
import pytz
from datetime import datetime
import Subscriptions.util as util
class AbsenceManagementSerializer(serializers.ModelSerializer):
class Meta:
model = AbsenceManagement
fields = '__all__'
class RegistrationSchoolFileMasterSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
class Meta:
model = RegistrationSchoolFileMaster
fields = '__all__'
class RegistrationParentFileMasterSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
class Meta:
model = RegistrationParentFileMaster
fields = '__all__'
class RegistrationSchoolFileTemplateSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
file_url = serializers.SerializerMethodField()
class Meta:
model = RegistrationSchoolFileTemplate
fields = '__all__'
def get_file_url(self, obj):
# Retourne l'URL complète du fichier si disponible
return obj.file.url if obj.file else None
class RegistrationParentFileTemplateSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
file_url = serializers.SerializerMethodField()
master_name = serializers.CharField(source='master.name', read_only=True)
master_description = serializers.CharField(source='master.description', read_only=True)
is_required = serializers.BooleanField(source='master.is_required', read_only=True)
class Meta:
model = RegistrationParentFileTemplate
fields = '__all__'
def get_file_url(self, obj):
# Retourne l'URL complète du fichier si disponible
return obj.file.url if obj.file else None
class GuardianSimpleSerializer(serializers.ModelSerializer):
associated_profile_email = serializers.SerializerMethodField()
class Meta:
model = Guardian
fields = ['id', 'associated_profile_email']
def get_associated_profile_email(self, obj):
if obj.profile_role and obj.profile_role.profile:
return obj.profile_role.profile.email
return None
class RegistrationFormSimpleSerializer(serializers.ModelSerializer):
guardians = GuardianSimpleSerializer(many=True, source='student.guardians')
last_name = serializers.SerializerMethodField()
first_name = serializers.SerializerMethodField()
class Meta:
model = RegistrationForm
fields = ['student_id', 'last_name', 'first_name', 'guardians']
def get_last_name(self, obj):
return obj.student.last_name
def get_first_name(self, obj):
return obj.student.first_name
class RegistrationFileGroupSerializer(serializers.ModelSerializer):
registration_forms = serializers.SerializerMethodField()
class Meta:
model = RegistrationFileGroup
fields = '__all__'
def get_registration_forms(self, obj):
forms = RegistrationForm.objects.filter(fileGroup=obj)
return RegistrationFormSimpleSerializer(forms, many=True).data
class LanguageSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
class Meta:
model = Language
fields = '__all__'
class SiblingSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
class Meta:
model = Sibling
fields = '__all__'
class GuardianSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
profile_role = serializers.PrimaryKeyRelatedField(queryset=ProfileRole.objects.all(), required=False)
profile_role_data = ProfileRoleSerializer(write_only=True, required=False)
associated_profile_email = serializers.SerializerMethodField()
class Meta:
model = Guardian
fields = '__all__'
def get_associated_profile_email(self, obj):
if obj.profile_role and obj.profile_role.profile:
return obj.profile_role.profile.email
return None
class StudentSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
guardians = GuardianSerializer(many=True, required=False)
siblings = SiblingSerializer(many=True, required=False)
spoken_languages = LanguageSerializer(many=True, required=False)
associated_class_id = serializers.PrimaryKeyRelatedField(queryset=SchoolClass.objects.all(), source='associated_class', required=False, write_only=False, read_only=False)
age = serializers.SerializerMethodField()
formatted_birth_date = serializers.SerializerMethodField()
birth_date = serializers.DateField(input_formats=['%d-%m-%Y', '%Y-%m-%d'], required=False, allow_null=True)
associated_class_name = serializers.SerializerMethodField()
class Meta:
model = Student
fields = '__all__'
def create_or_update_guardians(self, guardians_data):
guardians_ids = []
for guardian_data in guardians_data:
guardian_id = guardian_data.get('id', None)
profile_role_data = guardian_data.pop('profile_role_data', None)
profile_role = guardian_data.pop('profile_role', None)
if guardian_id:
# Si un ID est fourni, récupérer ou mettre à jour le Guardian existant
guardian_instance, created = Guardian.objects.update_or_create(
id=guardian_id,
defaults=guardian_data
)
guardians_ids.append(guardian_instance.id)
continue
if profile_role_data:
# Vérifiez si 'profile_data' est fourni pour créer un nouveau profil
profile_data = profile_role_data.pop('profile_data', None)
if profile_data:
# Créer un nouveau profil
profile_serializer = ProfileSerializer(data=profile_data)
profile_serializer.is_valid(raise_exception=True)
profile = profile_serializer.save()
profile.set_password(profile_data['password'])
profile.save()
profile_role_data['profile'] = profile.id # Associer le profil créé
# Vérifiez si 'profile' est un objet ou une clé primaire
if isinstance(profile_role_data.get('profile'), Profile):
profile_role_data['profile'] = profile_role_data['profile'].id
establishment_id = profile_role_data.pop('establishment').id
profile_role_data['establishment'] = establishment_id
# Vérifiez si un ProfileRole existe déjà pour ce profile et cet établissement
existing_profile_role = ProfileRole.objects.filter(
profile_id=profile_role_data['profile'],
establishment=profile_role_data['establishment'],
role_type=profile_role_data['role_type']
).first()
if existing_profile_role:
# Mettre à jour le ProfileRole existant
profile_role_serializer = ProfileRoleSerializer(existing_profile_role, data=profile_role_data)
profile_role_serializer.is_valid(raise_exception=True)
profile_role = profile_role_serializer.save()
else:
# Créer un nouveau ProfileRole si aucun n'existe
profile_role_serializer = ProfileRoleSerializer(data=profile_role_data)
profile_role_serializer.is_valid(raise_exception=True)
profile_role = profile_role_serializer.save()
elif profile_role:
# Récupérer un ProfileRole existant par son ID
profile_role = ProfileRole.objects.get(id=profile_role.id)
if profile_role:
guardian_data['profile_role'] = profile_role
# Vérifiez si un Guardian existe déjà pour ce ProfileRole
existing_guardian = Guardian.objects.filter(profile_role=profile_role).first()
if existing_guardian:
# Mettre à jour le Guardian existant
for key, value in guardian_data.items():
setattr(existing_guardian, key, value)
existing_guardian.save()
guardians_ids.append(existing_guardian.id)
else:
# Créer un nouveau Guardian
guardian_instance = Guardian.objects.create(**guardian_data)
guardians_ids.append(guardian_instance.id)
return guardians_ids
def create_or_update_siblings(self, siblings_data, student_instance):
"""
Crée ou met à jour les frères et sœurs associés à un étudiant.
Supprime les frères et sœurs qui ne sont plus présents dans siblings_data.
"""
# Si siblings_data est vide, supprimer tous les frères et sœurs associés
if not siblings_data:
student_instance.siblings.clear() # Supprime toutes les relations
return []
# Récupérer les IDs des frères et sœurs existants
existing_sibling_ids = set(student_instance.siblings.values_list('id', flat=True))
# Créer ou mettre à jour les frères et sœurs
updated_sibling_ids = []
for sibling_data in siblings_data:
sibling_instance, created = Sibling.objects.update_or_create(
id=sibling_data.get('id'),
defaults=sibling_data
)
updated_sibling_ids.append(sibling_instance.id)
# Supprimer les frères et sœurs qui ne sont plus dans siblings_data
siblings_to_delete = existing_sibling_ids - set(updated_sibling_ids)
Sibling.objects.filter(id__in=siblings_to_delete).delete()
return updated_sibling_ids
def create_or_update_languages(self, languages_data):
languages_ids = []
for language_data in languages_data:
language_instance, created = Language.objects.update_or_create(
id=language_data.get('id'),
defaults=language_data
)
languages_ids.append(language_instance.id)
return languages_ids
def create(self, validated_data):
guardians_data = validated_data.pop('guardians', [])
siblings_data = validated_data.pop('siblings', [])
languages_data = validated_data.pop('spoken_languages', [])
student = Student.objects.create(**validated_data)
student.guardians.set(self.create_or_update_guardians(guardians_data))
student.siblings.set(self.create_or_update_siblings(siblings_data, student))
student.spoken_languages.set(self.create_or_update_languages(languages_data))
return student
def update(self, instance, validated_data):
guardians_data = validated_data.pop('guardians', [])
siblings_data = validated_data.pop('siblings', [])
languages_data = validated_data.pop('spoken_languages', [])
if guardians_data:
instance.guardians.set(self.create_or_update_guardians(guardians_data))
sibling_ids = self.create_or_update_siblings(siblings_data, instance)
instance.siblings.set(sibling_ids)
if languages_data:
instance.spoken_languages.set(self.create_or_update_languages(languages_data))
for field in self.fields:
try:
setattr(instance, field, validated_data[field])
except KeyError:
pass
instance.save()
return instance
def get_age(self, obj):
return obj.age
def get_formatted_birth_date(self, obj):
return obj.formatted_birth_date
def get_associated_class_name(self, obj):
return obj.associated_class.atmosphere_name if obj.associated_class else None
class RegistrationFormSerializer(serializers.ModelSerializer):
student = StudentSerializer(many=False, required=False)
registration_file = serializers.FileField(required=False)
sepa_file = serializers.FileField(required=False)
status_label = serializers.SerializerMethodField()
formatted_last_update = serializers.SerializerMethodField()
registration_files = RegistrationSchoolFileTemplateSerializer(many=True, required=False)
fees = serializers.PrimaryKeyRelatedField(queryset=Fee.objects.all(), many=True, required=False)
discounts = serializers.PrimaryKeyRelatedField(queryset=Discount.objects.all(), many=True, required=False)
totalRegistrationFees = serializers.SerializerMethodField()
totalTuitionFees = serializers.SerializerMethodField()
class Meta:
model = RegistrationForm
fields = '__all__'
def create(self, validated_data):
student_data = validated_data.pop('student')
student = StudentSerializer.create(StudentSerializer(), student_data)
fees_data = validated_data.pop('fees', [])
discounts_data = validated_data.pop('discounts', [])
registrationForm = RegistrationForm.objects.create(student=student, **validated_data)
# Associer les IDs des objets Fee et Discount au RegistrationForm
registrationForm.fees.set([fee.id for fee in fees_data])
registrationForm.discounts.set([discount.id for discount in discounts_data])
return registrationForm
def update(self, instance, validated_data):
student_data = validated_data.pop('student', None)
fees_data = validated_data.pop('fees', None)
discounts_data = validated_data.pop('discounts', None)
if student_data:
student = instance.student
StudentSerializer.update(StudentSerializer(), student, student_data)
for field in self.fields:
try:
setattr(instance, field, validated_data[field])
except KeyError:
pass
instance.last_update = util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
instance.save()
# Associer les IDs des objets Fee et Discount au RegistrationForm
if fees_data is not None:
instance.fees.set([fee.id for fee in fees_data])
if discounts_data is not None:
instance.discounts.set([discount.id for discount in discounts_data])
return instance
def get_status_label(self, obj):
return obj.get_status_display()
def get_formatted_last_update(self, obj):
utc_time = timezone.localtime(obj.last_update) # Convert to local time
local_tz = pytz.timezone(settings.TZ_APPLI)
local_time = utc_time.astimezone(local_tz)
return local_time.strftime("%d-%m-%Y %H:%M")
def get_totalRegistrationFees(self, obj):
return sum(fee.base_amount for fee in obj.fees.filter(type=FeeType.REGISTRATION_FEE))
def get_totalTuitionFees(self, obj):
return sum(fee.base_amount for fee in obj.fees.filter(type=FeeType.TUITION_FEE))
class StudentByParentSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
class Meta:
model = Student
fields = ['id', 'last_name', 'first_name', 'level', 'photo']
def __init__(self, *args, **kwargs):
super(StudentByParentSerializer, self).__init__(*args, **kwargs)
for field in self.fields:
self.fields[field].required = False
class RegistrationFormByParentSerializer(serializers.ModelSerializer):
student = StudentByParentSerializer(many=False, required=True)
class Meta:
model = RegistrationForm
fields = ['student', 'status', 'sepa_file']
def __init__(self, *args, **kwargs):
super(RegistrationFormByParentSerializer, self).__init__(*args, **kwargs)
for field in self.fields:
self.fields[field].required = False
class GuardianByDICreationSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
associated_profile_email = serializers.SerializerMethodField()
profile = serializers.SerializerMethodField()
class Meta:
model = Guardian
fields = ['id', 'last_name', 'first_name', 'associated_profile_email', 'phone', 'profile_role', 'profile']
def get_associated_profile_email(self, obj):
if obj.profile_role and obj.profile_role.profile:
return obj.profile_role.profile.email
return None
def get_profile(self, obj):
if obj.profile_role and obj.profile_role.profile:
return obj.profile_role.profile.id # Retourne l'ID du profil associé
return None
class StudentByRFCreationSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
guardians = GuardianByDICreationSerializer(many=True, required=False)
associated_class_name = serializers.SerializerMethodField()
class Meta:
model = Student
fields = ['id', 'last_name', 'first_name', 'guardians', 'level', 'associated_class_name', 'photo']
def __init__(self, *args, **kwargs):
super(StudentByRFCreationSerializer, self).__init__(*args, **kwargs)
for field in self.fields:
self.fields[field].required = False
def get_associated_class_name(self, obj):
return obj.associated_class.atmosphere_name if obj.associated_class else None
class NotificationSerializer(serializers.ModelSerializer):
notification_type_label = serializers.ReadOnlyField()
class Meta:
model = Notification
fields = '__all__'