Files
n3wt-school/Back-End/Subscriptions/views/register_form_views.py
2025-11-30 17:24:25 +01:00

838 lines
41 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 dinscription, 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 dun dossier dinscription.
"""
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)