mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
838 lines
41 KiB
Python
838 lines
41 KiB
Python
from django.http.response import JsonResponse
|
||
from django.views.decorators.csrf import ensure_csrf_cookie, csrf_protect
|
||
from django.utils.decorators import method_decorator
|
||
from rest_framework.views import APIView
|
||
from rest_framework.decorators import action, api_view
|
||
from rest_framework import status
|
||
from drf_yasg.utils import swagger_auto_schema
|
||
from drf_yasg import openapi
|
||
|
||
import json
|
||
import os
|
||
from django.core.files import File
|
||
|
||
import N3wtSchool.mailManager as mailer
|
||
import Subscriptions.util as util
|
||
|
||
from Subscriptions.serializers import RegistrationFormSerializer, RegistrationSchoolFileTemplateSerializer, RegistrationParentFileTemplateSerializer
|
||
from Subscriptions.pagination import CustomSubscriptionPagination
|
||
from Subscriptions.models import (
|
||
Guardian,
|
||
RegistrationForm,
|
||
RegistrationSchoolFileTemplate,
|
||
RegistrationFileGroup,
|
||
RegistrationParentFileTemplate,
|
||
StudentCompetency
|
||
)
|
||
from Subscriptions.automate import updateStateMachine
|
||
from School.models import EstablishmentCompetency
|
||
from Establishment.models import Establishment
|
||
|
||
from N3wtSchool import settings, bdd
|
||
from django.db.models import Q
|
||
|
||
|
||
|
||
import logging
|
||
logger = logging.getLogger(__name__)
|
||
|
||
# /Subscriptions/registerForms
|
||
class RegisterFormView(APIView):
|
||
"""
|
||
Gère la liste des dossiers d’inscription, lecture et création.
|
||
"""
|
||
pagination_class = CustomSubscriptionPagination
|
||
|
||
@swagger_auto_schema(
|
||
manual_parameters=[
|
||
openapi.Parameter('filter', openapi.IN_QUERY, description="filtre", type=openapi.TYPE_STRING, enum=['current_year', 'next_year', 'historical'], required=True),
|
||
openapi.Parameter('search', openapi.IN_QUERY, description="search", type=openapi.TYPE_STRING, required=False),
|
||
openapi.Parameter('page_size', openapi.IN_QUERY, description="limite de page lors de la pagination", type=openapi.TYPE_INTEGER, required=False),
|
||
openapi.Parameter('establishment_id', openapi.IN_QUERY, description="ID de l'établissement", type=openapi.TYPE_INTEGER, required=True),
|
||
],
|
||
responses={200: RegistrationFormSerializer(many=True)},
|
||
operation_description="Récupère les dossier d'inscriptions en fonction du filtre passé.",
|
||
operation_summary="Récupérer les dossier d'inscriptions",
|
||
examples={
|
||
"application/json": [
|
||
{
|
||
"id": 1,
|
||
"student": {
|
||
"id": 1,
|
||
"first_name": "John",
|
||
"last_name": "Doe",
|
||
"date_of_birth": "2010-01-01"
|
||
},
|
||
"status": "current_year",
|
||
"last_update": "10-02-2025 10:00"
|
||
},
|
||
{
|
||
"id": 2,
|
||
"student": {
|
||
"id": 2,
|
||
"first_name": "Jane",
|
||
"last_name": "Doe",
|
||
"date_of_birth": "2011-02-02"
|
||
},
|
||
"status": "historical",
|
||
"last_update": "09-02-2025 09:00"
|
||
}
|
||
]
|
||
}
|
||
)
|
||
def get(self, request):
|
||
"""
|
||
Récupère les fiches d'inscriptions en fonction du filtre passé.
|
||
"""
|
||
# Récupération des paramètres
|
||
filter = request.GET.get('filter', '').strip()
|
||
page_size = request.GET.get('page_size', None)
|
||
establishment_id = request.GET.get('establishment_id', None)
|
||
search = request.GET.get('search', '').strip() # <-- Ajout du paramètre search
|
||
|
||
# Gestion du page_size
|
||
if page_size is not None:
|
||
try:
|
||
page_size = int(page_size)
|
||
except ValueError:
|
||
page_size = settings.NB_RESULT_SUBSCRIPTIONS_PER_PAGE
|
||
|
||
# Récupérer les années scolaires
|
||
current_year = util.getCurrentSchoolYear()
|
||
next_year = util.getNextSchoolYear()
|
||
historical_years = util.getHistoricalYears()
|
||
|
||
# Récupérer les dossiers d'inscriptions en fonction du filtre
|
||
registerForms_List = None
|
||
if filter == 'current_year':
|
||
registerForms_List = RegistrationForm.objects.filter(school_year=current_year)
|
||
elif filter == 'next_year':
|
||
registerForms_List = RegistrationForm.objects.filter(school_year=next_year)
|
||
elif filter == 'historical':
|
||
registerForms_List = RegistrationForm.objects.filter(school_year__in=historical_years)
|
||
else:
|
||
registerForms_List = None
|
||
|
||
if registerForms_List:
|
||
registerForms_List = registerForms_List.filter(establishment=establishment_id)
|
||
# Ajout du filtre search sur le nom et prénom de l'élève
|
||
if search:
|
||
registerForms_List = registerForms_List.filter(
|
||
Q(student__first_name__icontains=search) |
|
||
Q(student__last_name__icontains=search)
|
||
)
|
||
registerForms_List = registerForms_List.order_by('-last_update')
|
||
|
||
if not registerForms_List:
|
||
return JsonResponse({'error': 'aucune donnée trouvée', 'count': 0}, safe=False)
|
||
|
||
# Pagination
|
||
paginator = self.pagination_class()
|
||
page = paginator.paginate_queryset(registerForms_List, request)
|
||
if page is not None:
|
||
registerForms_serializer = RegistrationFormSerializer(page, many=True)
|
||
response_data = paginator.get_paginated_response(registerForms_serializer.data)
|
||
return JsonResponse(response_data, safe=False)
|
||
|
||
return JsonResponse({'error': 'aucune donnée trouvée', 'count': 0}, safe=False)
|
||
|
||
@swagger_auto_schema(
|
||
request_body=RegistrationFormSerializer,
|
||
responses={200: RegistrationFormSerializer()},
|
||
operation_description="Crée un dossier d'inscription.",
|
||
operation_summary="Créer un dossier d'inscription",
|
||
examples={
|
||
"application/json": {
|
||
"student": {
|
||
"id": 1,
|
||
"first_name": "John",
|
||
"last_name": "Doe",
|
||
"date_of_birth": "2010-01-01"
|
||
},
|
||
"status": "current_year",
|
||
"last_update": "10-02-2025 10:00",
|
||
"codeLienInscription": "ABC123XYZ456"
|
||
}
|
||
}
|
||
)
|
||
@method_decorator(csrf_protect, name='dispatch')
|
||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||
def post(self, request):
|
||
"""
|
||
Crée un dossier d'inscription.
|
||
"""
|
||
regiterFormData = request.data.copy()
|
||
logger.info(f"Création d'un dossier d'inscription {request}")
|
||
# Ajout de la date de mise à jour
|
||
regiterFormData["last_update"] = util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||
# Ajout du code d'inscription
|
||
code = util.genereRandomCode(12)
|
||
regiterFormData["codeLienInscription"] = code
|
||
|
||
guardiansId = regiterFormData.pop('idGuardians', [])
|
||
registerForm_serializer = RegistrationFormSerializer(data=regiterFormData)
|
||
fileGroupId = regiterFormData.pop('fileGroup', None)
|
||
|
||
if registerForm_serializer.is_valid():
|
||
di = registerForm_serializer.save()
|
||
|
||
# Mise à jour de l'automate
|
||
updateStateMachine(di, 'EVENT_INIT')
|
||
|
||
# Récupération du reponsable associé
|
||
for guardianId in guardiansId:
|
||
guardian = Guardian.objects.get(id=guardianId)
|
||
di.student.guardians.add(guardian)
|
||
di.save()
|
||
if fileGroupId:
|
||
di.fileGroup = RegistrationFileGroup.objects.get(id=fileGroupId)
|
||
di.save()
|
||
|
||
return JsonResponse(registerForm_serializer.data, safe=False)
|
||
else:
|
||
logger.error(f"Erreur lors de la validation des données {regiterFormData}")
|
||
|
||
return JsonResponse(registerForm_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)
|
||
|
||
# /Subscriptions/registerForms/{id}
|
||
class RegisterFormWithIdView(APIView):
|
||
"""
|
||
Gère la lecture, création, modification et suppression d’un dossier d’inscription.
|
||
"""
|
||
pagination_class = CustomSubscriptionPagination
|
||
|
||
@swagger_auto_schema(
|
||
responses={200: RegistrationFormSerializer()},
|
||
operation_description="Récupère un dossier d'inscription donné.",
|
||
operation_summary="Récupérer un dossier d'inscription",
|
||
examples={
|
||
"application/json": {
|
||
"id": 1,
|
||
"student": {
|
||
"id": 1,
|
||
"first_name": "John",
|
||
"last_name": "Doe",
|
||
"date_of_birth": "2010-01-01"
|
||
},
|
||
}
|
||
}
|
||
)
|
||
def get(self, request, id):
|
||
"""
|
||
Récupère un dossier d'inscription donné.
|
||
"""
|
||
registerForm = bdd.getObject(RegistrationForm, "student__id", id)
|
||
if registerForm is None:
|
||
return JsonResponse({"errorMessage":'Le dossier d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
|
||
registerForm_serializer = RegistrationFormSerializer(registerForm)
|
||
return JsonResponse(registerForm_serializer.data, safe=False)
|
||
|
||
@swagger_auto_schema(
|
||
request_body=RegistrationFormSerializer,
|
||
responses={200: RegistrationFormSerializer()},
|
||
operation_description="Modifie un dossier d'inscription donné.",
|
||
operation_summary="Modifier un dossier d'inscription",
|
||
examples={
|
||
"application/json": {
|
||
"id": 1,
|
||
"student": {
|
||
"id": 1,
|
||
"first_name": "John",
|
||
"last_name": "Doe",
|
||
"date_of_birth": "2010-01-01"
|
||
},
|
||
"status": "under_review",
|
||
"last_update": "10-02-2025 10:00"
|
||
}
|
||
}
|
||
)
|
||
@method_decorator(csrf_protect, name='dispatch')
|
||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||
def put(self, request, id):
|
||
"""
|
||
Modifie un dossier d'inscription donné.
|
||
"""
|
||
|
||
studentForm_data = request.data.get('data', '{}')
|
||
|
||
try:
|
||
data = json.loads(studentForm_data)
|
||
except json.JSONDecodeError:
|
||
return JsonResponse({"error": "Invalid JSON format in 'data'"}, status=status.HTTP_400_BAD_REQUEST)
|
||
|
||
# Extraire le fichier photo
|
||
photo_file = request.FILES.get('photo')
|
||
|
||
# Extraire le fichier photo
|
||
sepa_file = request.FILES.get('sepa_file')
|
||
|
||
# Ajouter la photo aux données de l'étudiant
|
||
if photo_file:
|
||
data['student']['photo'] = photo_file
|
||
|
||
if sepa_file:
|
||
data['sepa_file'] = sepa_file
|
||
|
||
# Gérer le champ `_status`
|
||
_status = data.pop('status', 0)
|
||
_status = int(_status)
|
||
|
||
# Récupérer le dossier d'inscription
|
||
registerForm = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
|
||
if not registerForm:
|
||
return JsonResponse({"error": "Dossier d'inscription introuvable"}, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
studentForm_serializer = RegistrationFormSerializer(registerForm, data=data, partial=True)
|
||
if studentForm_serializer.is_valid():
|
||
studentForm_serializer.save()
|
||
|
||
# Sauvegarder la photo si elle est présente dans la requête
|
||
if photo_file:
|
||
student = registerForm.student
|
||
|
||
# Vérifier si une photo existante est déjà associée à l'étudiant
|
||
if student.photo and student.photo.name:
|
||
# Construire le chemin complet du fichier existant
|
||
if os.path.isabs(student.photo.name):
|
||
existing_file_path = student.photo.name
|
||
else:
|
||
existing_file_path = os.path.join(settings.MEDIA_ROOT, student.photo.name.lstrip('/'))
|
||
|
||
# Vérifier si le fichier existe et le supprimer
|
||
if os.path.exists(existing_file_path):
|
||
os.remove(existing_file_path)
|
||
student.photo.delete(save=False)
|
||
else:
|
||
print(f'File does not exist: {existing_file_path}')
|
||
|
||
# Sauvegarder la nouvelle photo
|
||
student.photo.save(photo_file.name, photo_file, save=True)
|
||
else:
|
||
return JsonResponse(studentForm_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)
|
||
|
||
if _status == RegistrationForm.RegistrationFormStatus.RF_UNDER_REVIEW:
|
||
# Le parent a rempli le dossier d'inscription sans sélectionner "Prélèvement par Mandat SEPA"
|
||
# L'école doit désormais valider le dossier d'inscription
|
||
try:
|
||
# Génération de la fiche d'inscription au format PDF
|
||
base_dir = os.path.join(settings.MEDIA_ROOT, f"registration_files/dossier_rf_{registerForm.pk}")
|
||
os.makedirs(base_dir, exist_ok=True)
|
||
|
||
# Fichier PDF initial
|
||
initial_pdf = f"{base_dir}/Inscription_{registerForm.student.last_name}_{registerForm.student.first_name}.pdf"
|
||
registerForm.registration_file = util.rfToPDF(registerForm, initial_pdf)
|
||
registerForm.save()
|
||
|
||
# Mise à jour de l'automate
|
||
# Vérification de la présence du fichier SEPA
|
||
if registerForm.sepa_file:
|
||
# Mise à jour de l'automate pour SEPA
|
||
updateStateMachine(registerForm, 'EVENT_SIGNATURE_SEPA')
|
||
else:
|
||
# Mise à jour de l'automate pour une signature classique
|
||
updateStateMachine(registerForm, 'EVENT_SIGNATURE')
|
||
except Exception as e:
|
||
return JsonResponse({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||
elif _status == RegistrationForm.RegistrationFormStatus.RF_SENT:
|
||
if registerForm.status == RegistrationForm.RegistrationFormStatus.RF_UNDER_REVIEW:
|
||
updateStateMachine(registerForm, 'EVENT_REFUSE')
|
||
util.delete_registration_files(registerForm)
|
||
elif _status == RegistrationForm.RegistrationFormStatus.RF_SEPA_SENT:
|
||
# Sauvegarde du mandat SEPA
|
||
student = registerForm.student
|
||
guardian = student.getMainGuardian()
|
||
email = guardian.profile_role.profile.email
|
||
errorMessage = mailer.sendMandatSEPA(email, registerForm.establishment.pk)
|
||
if errorMessage != '':
|
||
return JsonResponse({"errorMessage": errorMessage}, safe=False, status=status.HTTP_400_BAD_REQUEST)
|
||
registerForm.last_update = util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||
updateStateMachine(registerForm, 'EVENT_SEND_SEPA')
|
||
elif _status == RegistrationForm.RegistrationFormStatus.RF_SEPA_TO_SEND:
|
||
# Le parent a rempli le dossier d'inscription en sélectionnant "Prélèvement par Mandat SEPA"
|
||
# L'école doit désormais envoyer le mandat SEPA pour poursuivre l'inscription
|
||
updateStateMachine(registerForm, 'EVENT_WAITING_FOR_SEPA')
|
||
|
||
elif _status == RegistrationForm.RegistrationFormStatus.RF_VALIDATED:
|
||
# Vérifier si le paramètre fusion est activé via l'URL
|
||
fusion = data.get('fusionParam', False)
|
||
if fusion:
|
||
# Fusion des documents
|
||
# Récupération des fichiers schoolFileTemplates
|
||
school_file_paths = RegistrationSchoolFileTemplate.get_files_from_rf(registerForm.pk)
|
||
|
||
# Récupération des fichiers parentFileTemplates
|
||
parent_file_templates = RegistrationParentFileTemplate.get_files_from_rf(registerForm.pk)
|
||
|
||
# Initialisation de la liste des fichiers à fusionner
|
||
fileNames = []
|
||
|
||
# Ajout du fichier registration_file en première position
|
||
if registerForm.registration_file:
|
||
fileNames.append(registerForm.registration_file.path)
|
||
|
||
# Ajout des fichiers schoolFileTemplates
|
||
fileNames.extend(school_file_paths)
|
||
|
||
# Ajout des fichiers parentFileTemplates
|
||
fileNames.extend(parent_file_templates)
|
||
|
||
# Création du fichier PDF fusionné
|
||
merged_pdf_content = util.merge_files_pdf(fileNames)
|
||
|
||
# Mise à jour du champ registration_file avec le fichier fusionné
|
||
registerForm.fusion_file.save(
|
||
f"dossier_complet.pdf",
|
||
File(merged_pdf_content),
|
||
save=True
|
||
)
|
||
# Valorisation des StudentCompetency pour l'élève
|
||
try:
|
||
student = registerForm.student
|
||
cycle = None
|
||
if student.level:
|
||
cycle = student.level.cycle.number
|
||
if cycle:
|
||
# Récupérer les EstablishmentCompetency de l'établissement et du cycle de l'élève
|
||
establishment_competencies = EstablishmentCompetency.objects.filter(
|
||
establishment=registerForm.establishment,
|
||
custom_category__domain__cycle=cycle
|
||
) | EstablishmentCompetency.objects.filter(
|
||
establishment=registerForm.establishment,
|
||
competency__category__domain__cycle=cycle
|
||
)
|
||
establishment_competencies = establishment_competencies.distinct()
|
||
|
||
establishment = registerForm.establishment
|
||
evaluation_frequency = establishment.evaluation_frequency # 1=Trimestre, 2=Semestre, 3=Année
|
||
school_year = registerForm.school_year # ex: "2024_2025"
|
||
|
||
establishment_competencies = establishment_competencies.distinct()
|
||
|
||
periods = []
|
||
if evaluation_frequency == 1: # Trimestre
|
||
periods = [f"T{i+1}_{school_year}" for i in range(3)]
|
||
elif evaluation_frequency == 2: # Semestre
|
||
periods = [f"S{i+1}_{school_year}" for i in range(2)]
|
||
elif evaluation_frequency == 3: # Année
|
||
periods = [f"A_{school_year}"]
|
||
|
||
for ec in establishment_competencies:
|
||
for period in periods:
|
||
StudentCompetency.objects.get_or_create(
|
||
student=student,
|
||
establishment_competency=ec,
|
||
period=period
|
||
)
|
||
except Exception as e:
|
||
logger.error(f"Erreur lors de la valorisation des StudentCompetency: {e}")
|
||
|
||
updateStateMachine(registerForm, 'EVENT_VALIDATE')
|
||
|
||
# Retourner les données mises à jour
|
||
return JsonResponse(studentForm_serializer.data, safe=False)
|
||
|
||
@swagger_auto_schema(
|
||
request_body=openapi.Schema(
|
||
type=openapi.TYPE_OBJECT,
|
||
properties={
|
||
'student_data': openapi.Schema(type=openapi.TYPE_STRING, description='JSON string des données étudiant'),
|
||
'guardians_data': openapi.Schema(type=openapi.TYPE_STRING, description='JSON string des données responsables'),
|
||
'siblings_data': openapi.Schema(type=openapi.TYPE_STRING, description='JSON string des données fratrie'),
|
||
'payment_data': openapi.Schema(type=openapi.TYPE_STRING, description='JSON string des données de paiement'),
|
||
'current_page': openapi.Schema(type=openapi.TYPE_INTEGER, description='Page actuelle du formulaire'),
|
||
'auto_save': openapi.Schema(type=openapi.TYPE_BOOLEAN, description='Indicateur auto-save'),
|
||
}
|
||
),
|
||
responses={200: RegistrationFormSerializer()},
|
||
operation_description="Auto-sauvegarde partielle d'un dossier d'inscription.",
|
||
operation_summary="Auto-sauvegarder un dossier d'inscription"
|
||
)
|
||
@method_decorator(csrf_protect, name='dispatch')
|
||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||
def patch(self, request, id):
|
||
"""
|
||
Auto-sauvegarde partielle d'un dossier d'inscription.
|
||
Cette méthode est optimisée pour les sauvegardes automatiques périodiques.
|
||
"""
|
||
try:
|
||
# Récupérer le dossier d'inscription
|
||
registerForm = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
|
||
if not registerForm:
|
||
return JsonResponse({"error": "Dossier d'inscription introuvable"}, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
# Préparer les données à mettre à jour
|
||
update_data = {}
|
||
|
||
# Traiter les données étudiant si présentes
|
||
if 'student_data' in request.data:
|
||
try:
|
||
student_data = json.loads(request.data['student_data'])
|
||
|
||
# Extraire les données de paiement des données étudiant
|
||
payment_fields = ['registration_payment', 'tuition_payment', 'registration_payment_plan', 'tuition_payment_plan']
|
||
payment_data = {}
|
||
|
||
for field in payment_fields:
|
||
if field in student_data:
|
||
payment_data[field] = student_data.pop(field)
|
||
|
||
# Si nous avons des données de paiement, les traiter
|
||
if payment_data:
|
||
logger.debug(f"Auto-save: extracted payment_data from student_data = {payment_data}")
|
||
|
||
# Traiter les données de paiement
|
||
payment_updates = {}
|
||
|
||
# Gestion du mode de paiement d'inscription
|
||
if 'registration_payment' in payment_data and payment_data['registration_payment']:
|
||
try:
|
||
from School.models import PaymentMode
|
||
payment_mode = PaymentMode.objects.get(id=payment_data['registration_payment'])
|
||
registerForm.registration_payment = payment_mode
|
||
payment_updates['registration_payment'] = payment_mode.id
|
||
except PaymentMode.DoesNotExist:
|
||
logger.warning(f"Auto-save: PaymentMode with id {payment_data['registration_payment']} not found")
|
||
|
||
# Gestion du mode de paiement de scolarité
|
||
if 'tuition_payment' in payment_data and payment_data['tuition_payment']:
|
||
try:
|
||
from School.models import PaymentMode
|
||
payment_mode = PaymentMode.objects.get(id=payment_data['tuition_payment'])
|
||
registerForm.tuition_payment = payment_mode
|
||
payment_updates['tuition_payment'] = payment_mode.id
|
||
except PaymentMode.DoesNotExist:
|
||
logger.warning(f"Auto-save: PaymentMode with id {payment_data['tuition_payment']} not found")
|
||
|
||
# Gestion du plan de paiement d'inscription
|
||
if 'registration_payment_plan' in payment_data and payment_data['registration_payment_plan']:
|
||
try:
|
||
from School.models import PaymentPlan
|
||
payment_plan = PaymentPlan.objects.get(id=payment_data['registration_payment_plan'])
|
||
registerForm.registration_payment_plan = payment_plan
|
||
payment_updates['registration_payment_plan'] = payment_plan.id
|
||
except PaymentPlan.DoesNotExist:
|
||
logger.warning(f"Auto-save: PaymentPlan with id {payment_data['registration_payment_plan']} not found")
|
||
|
||
# Gestion du plan de paiement de scolarité
|
||
if 'tuition_payment_plan' in payment_data and payment_data['tuition_payment_plan']:
|
||
try:
|
||
from School.models import PaymentPlan
|
||
payment_plan = PaymentPlan.objects.get(id=payment_data['tuition_payment_plan'])
|
||
registerForm.tuition_payment_plan = payment_plan
|
||
payment_updates['tuition_payment_plan'] = payment_plan.id
|
||
except PaymentPlan.DoesNotExist:
|
||
logger.warning(f"Auto-save: PaymentPlan with id {payment_data['tuition_payment_plan']} not found")
|
||
|
||
# Sauvegarder les modifications de paiement
|
||
if payment_updates:
|
||
registerForm.save()
|
||
logger.debug(f"Auto-save: Payment data updated - {payment_updates}")
|
||
|
||
update_data['student'] = student_data
|
||
except json.JSONDecodeError:
|
||
logger.warning("Auto-save: Invalid JSON in student_data")
|
||
|
||
# Traiter les données des responsables si présentes
|
||
if 'guardians_data' in request.data:
|
||
try:
|
||
guardians_data = json.loads(request.data['guardians_data'])
|
||
logger.debug(f"Auto-save: guardians_data = {guardians_data}")
|
||
|
||
# Enregistrer directement chaque guardian avec le modèle
|
||
for i, guardian_data in enumerate(guardians_data):
|
||
guardian_id = guardian_data.get('id')
|
||
if guardian_id:
|
||
try:
|
||
# Récupérer le guardian existant et mettre à jour ses champs
|
||
guardian = Guardian.objects.get(id=guardian_id)
|
||
|
||
# Mettre à jour les champs si ils sont présents
|
||
if 'birth_date' in guardian_data and guardian_data['birth_date']:
|
||
guardian.birth_date = guardian_data['birth_date']
|
||
if 'profession' in guardian_data:
|
||
guardian.profession = guardian_data['profession']
|
||
if 'address' in guardian_data:
|
||
guardian.address = guardian_data['address']
|
||
if 'phone' in guardian_data:
|
||
guardian.phone = guardian_data['phone']
|
||
if 'first_name' in guardian_data:
|
||
guardian.first_name = guardian_data['first_name']
|
||
if 'last_name' in guardian_data:
|
||
guardian.last_name = guardian_data['last_name']
|
||
|
||
guardian.save()
|
||
logger.debug(f"Guardian {i}: Updated birth_date={guardian.birth_date}, profession={guardian.profession}, address={guardian.address}")
|
||
|
||
except Guardian.DoesNotExist:
|
||
logger.warning(f"Auto-save: Guardian with id {guardian_id} not found")
|
||
|
||
except json.JSONDecodeError:
|
||
logger.warning("Auto-save: Invalid JSON in guardians_data")
|
||
|
||
# Traiter les données de la fratrie si présentes
|
||
if 'siblings_data' in request.data:
|
||
try:
|
||
siblings_data = json.loads(request.data['siblings_data'])
|
||
logger.debug(f"Auto-save: siblings_data = {siblings_data}")
|
||
|
||
# Enregistrer directement chaque sibling avec le modèle
|
||
for i, sibling_data in enumerate(siblings_data):
|
||
sibling_id = sibling_data.get('id')
|
||
if sibling_id:
|
||
try:
|
||
# Récupérer le sibling existant et mettre à jour ses champs
|
||
from Subscriptions.models import Sibling
|
||
sibling = Sibling.objects.get(id=sibling_id)
|
||
|
||
# Mettre à jour les champs si ils sont présents
|
||
if 'first_name' in sibling_data:
|
||
sibling.first_name = sibling_data['first_name']
|
||
if 'last_name' in sibling_data:
|
||
sibling.last_name = sibling_data['last_name']
|
||
if 'birth_date' in sibling_data and sibling_data['birth_date']:
|
||
sibling.birth_date = sibling_data['birth_date']
|
||
|
||
sibling.save()
|
||
logger.debug(f"Sibling {i}: Updated first_name={sibling.first_name}, last_name={sibling.last_name}, birth_date={sibling.birth_date}")
|
||
|
||
except Sibling.DoesNotExist:
|
||
logger.warning(f"Auto-save: Sibling with id {sibling_id} not found")
|
||
|
||
except json.JSONDecodeError:
|
||
logger.warning("Auto-save: Invalid JSON in siblings_data")
|
||
|
||
# Traiter les données de paiement si présentes
|
||
if 'payment_data' in request.data:
|
||
try:
|
||
payment_data = json.loads(request.data['payment_data'])
|
||
logger.debug(f"Auto-save: payment_data = {payment_data}")
|
||
|
||
# Mettre à jour directement les champs de paiement du formulaire
|
||
payment_updates = {}
|
||
|
||
# Gestion du mode de paiement d'inscription
|
||
if 'registration_payment' in payment_data and payment_data['registration_payment']:
|
||
try:
|
||
from School.models import PaymentMode
|
||
payment_mode = PaymentMode.objects.get(id=payment_data['registration_payment'])
|
||
registerForm.registration_payment = payment_mode
|
||
payment_updates['registration_payment'] = payment_mode.id
|
||
except PaymentMode.DoesNotExist:
|
||
logger.warning(f"Auto-save: PaymentMode with id {payment_data['registration_payment']} not found")
|
||
|
||
# Gestion du mode de paiement de scolarité
|
||
if 'tuition_payment' in payment_data and payment_data['tuition_payment']:
|
||
try:
|
||
from School.models import PaymentMode
|
||
payment_mode = PaymentMode.objects.get(id=payment_data['tuition_payment'])
|
||
registerForm.tuition_payment = payment_mode
|
||
payment_updates['tuition_payment'] = payment_mode.id
|
||
except PaymentMode.DoesNotExist:
|
||
logger.warning(f"Auto-save: PaymentMode with id {payment_data['tuition_payment']} not found")
|
||
|
||
# Gestion du plan de paiement d'inscription
|
||
if 'registration_payment_plan' in payment_data and payment_data['registration_payment_plan']:
|
||
try:
|
||
from School.models import PaymentPlan
|
||
payment_plan = PaymentPlan.objects.get(id=payment_data['registration_payment_plan'])
|
||
registerForm.registration_payment_plan = payment_plan
|
||
payment_updates['registration_payment_plan'] = payment_plan.id
|
||
except PaymentPlan.DoesNotExist:
|
||
logger.warning(f"Auto-save: PaymentPlan with id {payment_data['registration_payment_plan']} not found")
|
||
|
||
# Gestion du plan de paiement de scolarité
|
||
if 'tuition_payment_plan' in payment_data and payment_data['tuition_payment_plan']:
|
||
try:
|
||
from School.models import PaymentPlan
|
||
payment_plan = PaymentPlan.objects.get(id=payment_data['tuition_payment_plan'])
|
||
registerForm.tuition_payment_plan = payment_plan
|
||
payment_updates['tuition_payment_plan'] = payment_plan.id
|
||
except PaymentPlan.DoesNotExist:
|
||
logger.warning(f"Auto-save: PaymentPlan with id {payment_data['tuition_payment_plan']} not found")
|
||
|
||
# Sauvegarder les modifications de paiement
|
||
if payment_updates:
|
||
registerForm.save()
|
||
logger.debug(f"Auto-save: Payment data updated - {payment_updates}")
|
||
|
||
except json.JSONDecodeError:
|
||
logger.warning("Auto-save: Invalid JSON in payment_data")
|
||
|
||
# Mettre à jour la page actuelle si présente
|
||
if 'current_page' in request.data:
|
||
try:
|
||
current_page = int(request.data['current_page'])
|
||
# Vous pouvez sauvegarder cette info dans un champ du modèle si nécessaire
|
||
logger.debug(f"Auto-save: current_page = {current_page}")
|
||
except (ValueError, TypeError):
|
||
logger.warning("Auto-save: Invalid current_page value")
|
||
|
||
# Effectuer la mise à jour partielle seulement si nous avons des données
|
||
if update_data:
|
||
serializer = RegistrationFormSerializer(registerForm, data=update_data, partial=True)
|
||
if serializer.is_valid():
|
||
serializer.save()
|
||
logger.debug(f"Auto-save successful for student {id}")
|
||
return JsonResponse({"status": "auto_save_success", "timestamp": util._now().isoformat()}, safe=False)
|
||
else:
|
||
logger.warning(f"Auto-save validation errors: {serializer.errors}")
|
||
# Pour l'auto-save, on retourne un succès même en cas d'erreur de validation
|
||
return JsonResponse({"status": "auto_save_partial", "errors": serializer.errors}, safe=False)
|
||
else:
|
||
# Pas de données à sauvegarder, mais on retourne un succès
|
||
return JsonResponse({"status": "auto_save_no_data"}, safe=False)
|
||
|
||
except Exception as e:
|
||
logger.error(f"Auto-save error for student {id}: {str(e)}")
|
||
# Pour l'auto-save, on ne retourne pas d'erreur HTTP pour éviter d'interrompre l'UX
|
||
return JsonResponse({"status": "auto_save_failed", "error": str(e)}, safe=False)
|
||
|
||
@swagger_auto_schema(
|
||
responses={204: 'No Content'},
|
||
operation_description="Supprime un dossier d'inscription donné.",
|
||
operation_summary="Supprimer un dossier d'inscription"
|
||
)
|
||
@method_decorator(csrf_protect, name='dispatch')
|
||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||
def delete(self, request, id):
|
||
"""
|
||
Supprime un dossier d'inscription donné.
|
||
"""
|
||
register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
|
||
if register_form != None:
|
||
student = register_form.student
|
||
student.guardians.clear()
|
||
student.profiles.clear()
|
||
student.registration_files.clear()
|
||
student.delete()
|
||
|
||
return JsonResponse("La suppression du dossier a été effectuée avec succès", safe=False)
|
||
|
||
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
@swagger_auto_schema(
|
||
method='get',
|
||
responses={200: openapi.Response('Success', schema=openapi.Schema(
|
||
type=openapi.TYPE_OBJECT,
|
||
properties={
|
||
'message': openapi.Schema(type=openapi.TYPE_STRING)
|
||
}
|
||
))},
|
||
operation_description="Envoie le dossier d'inscription par e-mail",
|
||
operation_summary="Envoyer un dossier d'inscription"
|
||
)
|
||
@api_view(['GET'])
|
||
def send(request,id):
|
||
"""Envoie le dossier d'inscription par e-mail."""
|
||
register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
|
||
if register_form != None:
|
||
student = register_form.student
|
||
guardian = student.getMainGuardian()
|
||
email = guardian.profile_role.profile.email
|
||
errorMessage = mailer.sendRegisterForm(email, register_form.establishment.pk)
|
||
if errorMessage == '':
|
||
register_form.last_update=util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||
updateStateMachine(register_form, 'EVENT_SEND')
|
||
return JsonResponse({"message": f"Le dossier d'inscription a bien été envoyé à l'addresse {email}"}, safe=False)
|
||
return JsonResponse({"errorMessage":errorMessage}, safe=False, status=status.HTTP_400_BAD_REQUEST)
|
||
return JsonResponse({"errorMessage":'Dossier d\'inscription non trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
@swagger_auto_schema(
|
||
method='get',
|
||
responses={200: openapi.Response('Success', schema=openapi.Schema(
|
||
type=openapi.TYPE_OBJECT,
|
||
properties={
|
||
'message': openapi.Schema(type=openapi.TYPE_STRING)
|
||
}
|
||
))},
|
||
operation_description="Archive le dossier d'inscription",
|
||
operation_summary="Archiver un dossier d'inscription"
|
||
)
|
||
@api_view(['GET'])
|
||
def archive(request,id):
|
||
"""Archive le dossier d'inscription."""
|
||
register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
|
||
if register_form != None:
|
||
register_form.last_update=util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||
updateStateMachine(register_form, 'EVENT_ARCHIVE')
|
||
return JsonResponse({"message": "Le dossier a été archivé avec succès"}, safe=False)
|
||
return JsonResponse({"errorMessage":'Dossier d\'inscription non trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
@swagger_auto_schema(
|
||
method='get',
|
||
responses={200: openapi.Response('Success', schema=openapi.Schema(
|
||
type=openapi.TYPE_OBJECT,
|
||
properties={
|
||
'message': openapi.Schema(type=openapi.TYPE_STRING)
|
||
}
|
||
))},
|
||
operation_description="Relance un dossier d'inscription par e-mail",
|
||
operation_summary="Relancer un dossier d'inscription"
|
||
)
|
||
@api_view(['GET'])
|
||
def resend(request,id):
|
||
"""Relance un dossier d'inscription par e-mail."""
|
||
register_form = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=id)
|
||
if register_form != None:
|
||
student = register_form.student
|
||
guardian = student.getMainGuardian()
|
||
email = guardian.email
|
||
errorMessage = mailer.envoieRelanceDossierInscription(email, register_form.codeLienInscription)
|
||
if errorMessage == '':
|
||
register_form.status=RegistrationForm.RegistrationFormStatus.RF_SENT
|
||
register_form.last_update=util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
|
||
register_form.save()
|
||
return JsonResponse({"message": f"Le dossier a été renvoyé à l'adresse {email}"}, safe=False)
|
||
return JsonResponse({"errorMessage":errorMessage}, safe=False, status=status.HTTP_400_BAD_REQUEST)
|
||
return JsonResponse({"errorMessage":'Dossier d\'inscription non trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
@swagger_auto_schema(
|
||
method='get',
|
||
responses={200: openapi.Response('Success', schema=openapi.Schema(
|
||
type=openapi.TYPE_OBJECT,
|
||
properties={
|
||
'message': openapi.Schema(type=openapi.TYPE_STRING)
|
||
}
|
||
))},
|
||
operation_description="Récupère les fichiers à signer d'un dossier d'inscription donné",
|
||
operation_summary="Récupérer les fichiers à signer d'un dossier d'inscription donné"
|
||
)
|
||
@api_view(['GET'])
|
||
def get_school_file_templates_by_rf(request, id):
|
||
try:
|
||
# Récupérer les templates associés au RegistrationForm donné
|
||
templates = RegistrationSchoolFileTemplate.objects.filter(registration_form=id)
|
||
|
||
# Sérialiser les données
|
||
serializer = RegistrationSchoolFileTemplateSerializer(templates, many=True)
|
||
|
||
# Retourner les données sérialisées
|
||
return JsonResponse(serializer.data, safe=False)
|
||
except RegistrationSchoolFileTemplate.DoesNotExist:
|
||
return JsonResponse({'error': 'Aucun template trouvé pour ce dossier d\'inscription'}, status=status.HTTP_404_NOT_FOUND)
|
||
|
||
@swagger_auto_schema(
|
||
method='get',
|
||
responses={200: openapi.Response('Success', schema=openapi.Schema(
|
||
type=openapi.TYPE_OBJECT,
|
||
properties={
|
||
'message': openapi.Schema(type=openapi.TYPE_STRING)
|
||
}
|
||
))},
|
||
operation_description="Récupère les pièces à fournir d'un dossier d'inscription donné",
|
||
operation_summary="Récupérer les pièces à fournir d'un dossier d'inscription donné"
|
||
)
|
||
@api_view(['GET'])
|
||
def get_parent_file_templates_by_rf(request, id):
|
||
try:
|
||
# Récupérer les pièces à fournir associés au RegistrationForm donné
|
||
parent_files = RegistrationParentFileTemplate.objects.filter(registration_form=id)
|
||
|
||
# Sérialiser les données
|
||
serializer = RegistrationParentFileTemplateSerializer(parent_files, many=True)
|
||
|
||
# Retourner les données sérialisées
|
||
return JsonResponse(serializer.data, safe=False)
|
||
except RegistrationParentFileTemplate.DoesNotExist:
|
||
return JsonResponse({'error': 'Aucune pièce à fournir trouvée pour ce dossier d\'inscription'}, status=status.HTTP_404_NOT_FOUND)
|