mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
459 lines
18 KiB
Python
459 lines
18 KiB
Python
from rest_framework import serializers
|
|
from .models import (
|
|
RegistrationFileGroup,
|
|
RegistrationForm,
|
|
Student,
|
|
Guardian,
|
|
Sibling,
|
|
Language,
|
|
RegistrationSchoolFileMaster,
|
|
RegistrationSchoolFileTemplate,
|
|
RegistrationParentFileMaster,
|
|
RegistrationParentFileTemplate,
|
|
AbsenceManagement,
|
|
BilanCompetence
|
|
)
|
|
from School.models import SchoolClass, Fee, Discount, FeeType
|
|
from Auth.models import ProfileRole, Profile
|
|
from Auth.serializers import ProfileSerializer, ProfileRoleSerializer
|
|
from GestionNotification.models import Notification
|
|
from N3wtSchool import settings
|
|
from django.utils import timezone
|
|
import pytz
|
|
import Subscriptions.util as util
|
|
|
|
class AbsenceManagementSerializer(serializers.ModelSerializer):
|
|
student_name = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = AbsenceManagement
|
|
fields = '__all__'
|
|
# Ajoute les nouveaux champs au retour JSON
|
|
extra_fields = ['student_name']
|
|
|
|
def get_student_name(self, obj):
|
|
if obj.student:
|
|
return f"{obj.student.first_name} {obj.student.last_name}"
|
|
return None
|
|
|
|
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)
|
|
associated_class_name = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Student
|
|
fields = ['id', 'last_name', 'first_name', 'level', 'photo', 'associated_class_name']
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(StudentByParentSerializer, 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 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 BilanCompetenceSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = BilanCompetence
|
|
fields = ['id', 'file', 'period', 'created_at']
|
|
|
|
class StudentByRFCreationSerializer(serializers.ModelSerializer):
|
|
id = serializers.IntegerField(required=False)
|
|
guardians = GuardianByDICreationSerializer(many=True, required=False)
|
|
associated_class_name = serializers.SerializerMethodField()
|
|
bilans = BilanCompetenceSerializer(many=True, read_only=True)
|
|
|
|
class Meta:
|
|
model = Student
|
|
fields = ['id', 'last_name', 'first_name', 'guardians', 'level', 'associated_class_name', 'photo', 'bilans']
|
|
|
|
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__'
|
|
|