Files
n3wt-school/Back-End/Subscriptions/views.py

461 lines
21 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.contrib.auth import login, authenticate, get_user_model
from django.views.decorators.csrf import ensure_csrf_cookie, csrf_protect
from django.utils.decorators import method_decorator
from django.core.cache import cache
from django.core.paginator import Paginator
from django.core.files import File
from django.db.models import Q # Ajout de cet import
from rest_framework.parsers import JSONParser,MultiPartParser, FormParser
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
import json
from pathlib import Path
import os
from io import BytesIO
import Subscriptions.mailManager as mailer
import Subscriptions.util as util
from Subscriptions.automate import Automate_RF_Register, load_config, getStateMachineObjectState, updateStateMachine
from .serializers import RegistrationFormSerializer, StudentSerializer, RegistrationFormByParentSerializer, StudentByRFCreationSerializer, RegistrationFileSerializer, RegistrationFileTemplateSerializer, RegistrationFormByParentSerializer, StudentByRFCreationSerializer, RegistrationFeeSerializer
from .pagination import CustomPagination
from .signals import clear_cache
from .models import Student, Guardian, RegistrationForm, RegistrationFee, RegistrationFileTemplate, RegistrationFile
from .automate import Automate_RF_Register, load_config, getStateMachineObjectState, updateStateMachine
from Auth.models import Profile
from N3wtSchool import settings, renderers, bdd
class RegisterFormListView(APIView):
"""
Gère la liste des dossiers dinscription, lecture et création.
"""
pagination_class = CustomPagination
def get_register_form(self, _filter, search=None):
"""
Récupère les fiches d'inscriptions en fonction du filtre passé.
_filter: Filtre pour déterminer l'état des fiches ('pending', 'archived', 'subscribed')
search: Terme de recherche (optionnel)
"""
if _filter == 'pending':
exclude_states = [RegistrationForm.RegistrationFormStatus.RF_VALIDATED, RegistrationForm.RegistrationFormStatus.RF_ARCHIVED]
return bdd.searchObjects(RegistrationForm, search, _excludeStates=exclude_states)
elif _filter == 'archived':
return bdd.getObjects(RegistrationForm, 'status', RegistrationForm.RegistrationFormStatus.RF_ARCHIVED)
elif _filter == 'subscribed':
return bdd.getObjects(RegistrationForm, 'status', RegistrationForm.RegistrationFormStatus.RF_VALIDATED)
return None
@swagger_auto_schema(
manual_parameters=[
openapi.Parameter('_filter', openapi.IN_PATH, description="filtre", type=openapi.TYPE_STRING, enum=['pending', 'archived', 'subscribed'], 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),
],
responses={200: RegistrationFormSerializer(many=True)}
)
def get(self, request, _filter):
"""
Récupère les fiches d'inscriptions en fonction du filtre passé.
"""
# Récupération des paramètres
search = request.GET.get('search', '').strip()
page_size = request.GET.get('page_size', None)
# Gestion du page_size
if page_size is not None:
try:
page_size = int(page_size)
except ValueError:
page_size = settings.NB_RESULT_PER_PAGE
# Définir le cache_key en fonction du filtre
page_number = request.GET.get('page', 1)
cache_key = f'N3WT_ficheInscriptions_{_filter}_page_{page_number}_search_{search if _filter == "pending" else ""}'
cached_page = cache.get(cache_key)
if cached_page:
return JsonResponse(cached_page, safe=False)
# Récupérer les fiches d'inscriptions en fonction du filtre
registerForms_List = self.get_register_form(_filter, search)
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)
cache.set(cache_key, response_data, timeout=60*15)
return JsonResponse(response_data, safe=False)
return JsonResponse({'error' : 'aucune donnée trouvée', 'count' :0}, safe=False)
@swagger_auto_schema(
manual_parameters=[
],
responses={200: RegistrationFormSerializer(many=True)}
)
def post(self, request):
studentFormList_serializer=JSONParser().parse(request)
for studentForm_data in studentFormList_serializer:
# Ajout de la date de mise à jour
studentForm_data["last_update"] = util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
json.dumps(studentForm_data)
# Ajout du code d'inscription
code = util.genereRandomCode(12)
studentForm_data["codeLienInscription"] = code
studentForm_serializer = RegistrationFormSerializer(data=studentForm_data)
if studentForm_serializer.is_valid():
studentForm_serializer.save()
return JsonResponse(studentForm_serializer.errors, safe=False)
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class RegisterFormView(APIView):
"""
Gère la lecture, création, modification et suppression dun dossier dinscription.
"""
pagination_class = CustomPagination
def get(self, request, _id):
"""
Récupère un dossier d'inscription donné.
"""
registerForm=bdd.getObject(RegistrationForm, "student__id", _id)
registerForm_serializer=RegistrationFormSerializer(registerForm)
return JsonResponse(registerForm_serializer.data, safe=False)
def post(self, request):
"""
Crée un dossier d'inscription.
"""
studentForm_data=JSONParser().parse(request)
# Ajout de la date de mise à jour
studentForm_data["last_update"] = util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
json.dumps(studentForm_data)
# Ajout du code d'inscription
code = util.genereRandomCode(12)
studentForm_data["codeLienInscription"] = code
guardiansId = studentForm_data.pop('idGuardians', [])
studentForm_serializer = RegistrationFormSerializer(data=studentForm_data)
if studentForm_serializer.is_valid():
di = studentForm_serializer.save()
# Mise à jour de l'automate
updateStateMachine(di, 'creationDI')
# Récupération du reponsable associé
for guardianId in guardiansId:
guardian = Guardian.objects.get(id=guardianId)
di.student.guardians.add(guardian)
di.save()
return JsonResponse(studentForm_serializer.data, safe=False)
return JsonResponse(studentForm_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)
def put(self, request, _id):
"""
Modifie un dossier d'inscription donné.
"""
studentForm_data=JSONParser().parse(request)
_status = studentForm_data.pop('status', 0)
studentForm_data["last_update"] = str(util.convertToStr(util._now(), '%d-%m-%Y %H:%M'))
registerForm = bdd.getObject(_objectName=RegistrationForm, _columnName='student__id', _value=_id)
if _status == RegistrationForm.RegistrationFormStatus.RF_UNDER_REVIEW:
try:
# Génération de la fiche d'inscription au format PDF
base_dir = f"registration_files/dossier_rf_{registerForm.pk}"
os.makedirs(base_dir, exist_ok=True)
# Fichier PDF initial
initial_pdf = f"{base_dir}/rf_{registerForm.student.last_name}_{registerForm.student.first_name}.pdf"
registerForm.registration_file = util.rfToPDF(registerForm, initial_pdf)
registerForm.save()
# Récupération des fichiers d'inscription
fileNames = RegistrationFile.get_files_from_rf(registerForm.pk)
if registerForm.registration_file:
fileNames.insert(0, registerForm.registration_file.path)
# Création du fichier PDF Fusionné
merged_pdf = f"{base_dir}/dossier_complet_{registerForm.pk}.pdf"
util.merge_files_pdf(fileNames, merged_pdf)
# Mise à jour du champ registration_file avec le fichier fusionné
with open(merged_pdf, 'rb') as f:
registerForm.registration_file.save(
os.path.basename(merged_pdf),
File(f),
save=True
)
# Mise à jour de l'automate
updateStateMachine(registerForm, 'saisiDI')
except Exception as e:
return JsonResponse({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
elif _status == RegistrationForm.RegistrationFormStatus.RF_VALIDATED:
# L'école a validé le dossier d'inscription
# Mise à jour de l'automate
updateStateMachine(registerForm, 'valideDI')
studentForm_serializer = RegistrationFormSerializer(registerForm, data=studentForm_data)
if studentForm_serializer.is_valid():
studentForm_serializer.save()
return JsonResponse(studentForm_serializer.data, safe=False)
return JsonResponse(studentForm_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)
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()
clear_cache()
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)
class StudentView(APIView):
"""
Gère la lecture dun élève donné.
"""
def get(self, request, _id):
student = bdd.getObject(_objectName=Student, _columnName='id', _value=_id)
if student is None:
return JsonResponse({"errorMessage":'Aucun élève trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
student_serializer = StudentSerializer(student)
return JsonResponse(student_serializer.data, safe=False)
class GuardianView(APIView):
"""
Récupère le dernier ID de responsable légal créé.
"""
def get(self, request):
lastGuardian = bdd.getLastId(Guardian)
return JsonResponse({"lastid":lastGuardian}, safe=False)
def send(request, _id):
"""
Envoie le dossier dinscription 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.sendRegisterForm(email)
if errorMessage == '':
register_form.last_update=util.convertToStr(util._now(), '%d-%m-%Y %H:%M')
# Mise à jour de l'automate
updateStateMachine(register_form, 'envoiDI')
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":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False, status=status.HTTP_404_NOT_FOUND)
def archive(request, _id):
"""
Archive le dossier dinscription visé.
"""
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')
# Mise à jour de l'automate
updateStateMachine(register_form, 'archiveDI')
return JsonResponse({"errorMessage":''}, safe=False, status=status.HTTP_400_BAD_REQUEST)
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False, status=status.HTTP_404_NOT_FOUND)
def relance(request, _id):
"""
Relance un dossier dinscription 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({"errorMessage":errorMessage}, safe=False, status=status.HTTP_400_BAD_REQUEST)
return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False, status=status.HTTP_404_NOT_FOUND)
# API utilisée pour la vue parent
class ChildrenListView(APIView):
"""
Pour la vue parent : liste les élèves rattachés à un profil donné.
"""
# Récupération des élèves d'un parent
# idProfile : identifiant du profil connecté rattaché aux fiches d'élèves
def get(self, request, _id):
students = bdd.getObjects(_objectName=RegistrationForm, _columnName='student__guardians__associated_profile__id', _value=_id)
students_serializer = RegistrationFormByParentSerializer(students, many=True)
return JsonResponse(students_serializer.data, safe=False)
# API utilisée pour la vue de création d'un DI
class StudentListView(APIView):
"""
Pour la vue de création dun dossier dinscription : liste les élèves disponibles.
"""
# Récupération de la liste des élèves inscrits ou en cours d'inscriptions
def get(self, request):
students = bdd.getAllObjects(_objectName=Student)
students_serializer = StudentByRFCreationSerializer(students, many=True)
return JsonResponse(students_serializer.data, safe=False)
# API utilisée pour la vue de personnalisation des frais d'inscription pour la structure
class RegistrationFeeView(APIView):
"""
Liste les frais dinscription.
"""
def get(self, request):
tarifs = bdd.getAllObjects(RegistrationFee)
tarifs_serializer = RegistrationFeeSerializer(tarifs, many=True)
return JsonResponse(tarifs_serializer.data, safe=False)
class RegistrationFileTemplateView(APIView):
"""
Gère les fichiers templates pour les dossiers dinscription.
"""
parser_classes = (MultiPartParser, FormParser)
def get(self, request, _id=None):
"""
Récupère les fichiers templates pour les dossiers dinscription.
"""
if _id is None:
files = RegistrationFileTemplate.objects.all()
serializer = RegistrationFileTemplateSerializer(files, many=True)
return Response(serializer.data)
else :
registationFileTemplate = bdd.getObject(_objectName=RegistrationFileTemplate, _columnName='id', _value=_id)
if registationFileTemplate is None:
return JsonResponse({"errorMessage":'Le fichier d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
serializer = RegistrationFileTemplateSerializer(registationFileTemplate)
return JsonResponse(serializer.data, safe=False)
def put(self, request, _id):
"""
Met à jour un fichier template existant.
"""
registationFileTemplate = bdd.getObject(_objectName=RegistrationFileTemplate, _columnName='id', _value=_id)
if registationFileTemplate is None:
return JsonResponse({'erreur': 'Le fichier d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
serializer = RegistrationFileTemplateSerializer(registationFileTemplate,data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def post(self, request):
"""
Crée un fichier template pour les dossiers dinscription.
"""
serializer = RegistrationFileTemplateSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, _id):
"""
Supprime un fichier template existant.
"""
registrationFileTemplate = bdd.getObject(_objectName=RegistrationFileTemplate, _columnName='id', _value=_id)
if registrationFileTemplate is not None:
registrationFileTemplate.file.delete() # Supprimer le fichier uploadé
registrationFileTemplate.delete()
return JsonResponse({'message': 'La suppression du fichier d\'inscription a été effectuée avec succès'}, safe=False, status=status.HTTP_204_NO_CONTENT)
else:
return JsonResponse({'erreur': 'Le fichier d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
class RegistrationFileView(APIView):
"""
Gère la création, mise à jour et suppression de fichiers liés à un dossier dinscription.
"""
parser_classes = (MultiPartParser, FormParser)
def get(self, request, _id=None):
"""
Récupère les fichiers liés à un dossier dinscription donné.
"""
if (_id is None):
files = RegistrationFile.objects.all()
serializer = RegistrationFileSerializer(files, many=True)
return Response(serializer.data)
else:
registationFile = bdd.getObject(_objectName=RegistrationFile, _columnName='id', _value=_id)
if registationFile is None:
return JsonResponse({"errorMessage":'Le fichier d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
serializer = RegistrationFileSerializer(registationFile)
return JsonResponse(serializer.data, safe=False)
def post(self, request):
"""
Crée un RegistrationFile pour le RegistrationForm associé.
"""
serializer = RegistrationFileSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def put(self, request, fileId):
"""
Met à jour un RegistrationFile existant.
"""
registrationFile = bdd.getObject(_objectName=RegistrationFile, _columnName='id', _value=fileId)
if registrationFile is None:
return JsonResponse({'erreur': 'Le fichier d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
serializer = RegistrationFileSerializer(registrationFile, data=request.data)
if serializer.is_valid():
serializer.save()
return Response({'message': 'Fichier mis à jour avec succès', 'data': serializer.data}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, _id):
"""
Supprime un RegistrationFile existant.
"""
registrationFile = bdd.getObject(_objectName=RegistrationFile, _columnName='id', _value=_id)
if registrationFile is not None:
registrationFile.file.delete() # Supprimer le fichier uploadé
registrationFile.delete()
return JsonResponse({'message': 'La suppression du fichier a été effectuée avec succès'}, safe=False)
else:
return JsonResponse({'erreur': 'Le fichier n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)