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 import json from pathlib import Path import os from io import BytesIO import GestionInscriptions.mailManager as mailer import GestionInscriptions.util as util from GestionInscriptions.serializers import FichierInscriptionSerializer, FicheInscriptionSerializer, EleveSerializer, FicheInscriptionByParentSerializer, EleveByDICreationSerializer, FraisInscriptionSerializer from GestionInscriptions.pagination import CustomPagination from GestionInscriptions.signals import clear_cache from .models import Eleve, Responsable, FicheInscription, FraisInscription, FichierInscription from GestionInscriptions.automate import Automate_DI_Inscription, load_config, getStateMachineObjectState, updateStateMachine from GestionLogin.models import Profil from N3wtSchool import settings, renderers, bdd class ListFichesInscriptionView(APIView): pagination_class = CustomPagination def get_fiche_inscriptions(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 = [FicheInscription.EtatDossierInscription.DI_VALIDE, FicheInscription.EtatDossierInscription.DI_ARCHIVE] return bdd.searchObjects(FicheInscription, search, _excludeStates=exclude_states) elif _filter == 'archived': return bdd.getObjects(FicheInscription, 'etat', FicheInscription.EtatDossierInscription.DI_ARCHIVE) elif _filter == 'subscribed': return bdd.getObjects(FicheInscription, 'etat', FicheInscription.EtatDossierInscription.DI_VALIDE) return None def get(self, request, _filter): # 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 ficheInscriptions_List = self.get_fiche_inscriptions(_filter, search) if not ficheInscriptions_List: return JsonResponse({'error' : 'aucune donnée trouvée', 'count' :0}, safe=False) # Pagination paginator = self.pagination_class() page = paginator.paginate_queryset(ficheInscriptions_List, request) if page is not None: ficheInscriptions_serializer = FicheInscriptionSerializer(page, many=True) response_data = paginator.get_paginated_response(ficheInscriptions_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) def post(self, request): fichesEleve_data=JSONParser().parse(request) for ficheEleve_data in fichesEleve_data: # Ajout de la date de mise à jour ficheEleve_data["dateMAJ"] = util.convertToStr(util._now(), '%d-%m-%Y %H:%M') json.dumps(ficheEleve_data) # Ajout du code d'inscription code = util.genereRandomCode(12) ficheEleve_data["codeLienInscription"] = code ficheEleve_serializer = FicheInscriptionSerializer(data=ficheEleve_data) if ficheEleve_serializer.is_valid(): ficheEleve_serializer.save() return JsonResponse(ficheEleve_serializer.errors, safe=False) @method_decorator(csrf_protect, name='dispatch') @method_decorator(ensure_csrf_cookie, name='dispatch') class FicheInscriptionView(APIView): pagination_class = CustomPagination def get(self, request, _id): ficheInscription=bdd.getObject(FicheInscription, "eleve__id", _id) fiche_serializer=FicheInscriptionSerializer(ficheInscription) return JsonResponse(fiche_serializer.data, safe=False) def post(self, request): ficheEleve_data=JSONParser().parse(request) # Ajout de la date de mise à jour ficheEleve_data["dateMAJ"] = util.convertToStr(util._now(), '%d-%m-%Y %H:%M') json.dumps(ficheEleve_data) # Ajout du code d'inscription code = util.genereRandomCode(12) ficheEleve_data["codeLienInscription"] = code responsablesId = ficheEleve_data.pop('idResponsables', []) ficheEleve_serializer = FicheInscriptionSerializer(data=ficheEleve_data) if ficheEleve_serializer.is_valid(): di = ficheEleve_serializer.save() # Mise à jour de l'automate updateStateMachine(di, 'creationDI') # Récupération du reponsable associé for responsableId in responsablesId: responsable = Responsable.objects.get(id=responsableId) di.eleve.responsables.add(responsable) di.save() return JsonResponse(ficheEleve_serializer.data, safe=False) return JsonResponse(ficheEleve_serializer.errors, safe=False) def put(self, request, id): ficheEleve_data=JSONParser().parse(request) etat = ficheEleve_data.pop('etat', 0) ficheEleve_data["dateMAJ"] = str(util.convertToStr(util._now(), '%d-%m-%Y %H:%M')) ficheEleve = bdd.getObject(_objectName=FicheInscription, _columnName='eleve__id', _value=id) if etat == FicheInscription.EtatDossierInscription.DI_EN_VALIDATION: # Le parent a complété le dossier d'inscription, il est soumis à validation par l'école print('EN VALIDATION') json.dumps(ficheEleve_data) util.diToPDF(ficheEleve) # Mise à jour de l'automate updateStateMachine(ficheEleve, 'saisiDI') elif etat == FicheInscription.EtatDossierInscription.DI_VALIDE: # L'école a validé le dossier d'inscription # Mise à jour de l'automate print('VALIDATION') updateStateMachine(ficheEleve, 'valideDI') ficheEleve_serializer = FicheInscriptionSerializer(ficheEleve, data=ficheEleve_data) if ficheEleve_serializer.is_valid(): ficheEleve_serializer.save() return JsonResponse(ficheEleve_serializer.data, safe=False) return JsonResponse(ficheEleve_serializer.errors, safe=False) def delete(self, request, id): fiche_inscription = bdd.getObject(_objectName=FicheInscription, _columnName='eleve__id', _value=id) if fiche_inscription != None: eleve = fiche_inscription.eleve eleve.responsables.clear() eleve.profils.clear() eleve.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) class EleveView(APIView): def get(self, request, _id): eleve = bdd.getObject(_objectName=Eleve, _columnName='id', _value=_id) eleve_serializer = EleveSerializer(eleve) return JsonResponse(eleve_serializer.data, safe=False) class ResponsableView(APIView): def get(self, request): lastResponsable = bdd.getLastId(Responsable) return JsonResponse({"lastid":lastResponsable}, safe=False) def send(request, id): fiche_inscription = bdd.getObject(_objectName=FicheInscription, _columnName='eleve__id', _value=id) if fiche_inscription != None: eleve = fiche_inscription.eleve responsable = eleve.getResponsablePrincipal() mail = responsable.mail errorMessage = mailer.envoieDossierInscription(mail) if errorMessage == '': fiche_inscription.dateMAJ=util.convertToStr(util._now(), '%d-%m-%Y %H:%M') # Mise à jour de l'automate updateStateMachine(fiche_inscription, 'envoiDI') return JsonResponse({"errorMessage":errorMessage}, safe=False) return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False) def archive(request, id): fiche_inscription = bdd.getObject(_objectName=FicheInscription, _columnName='eleve__id', _value=id) if fiche_inscription != None: fiche_inscription.dateMAJ=util.convertToStr(util._now(), '%d-%m-%Y %H:%M') # Mise à jour de l'automate updateStateMachine(fiche_inscription, 'archiveDI') return JsonResponse({"errorMessage":''}, safe=False) return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False) def relance(request, id): fiche_inscription = bdd.getObject(_objectName=FicheInscription, _columnName='eleve__id', _value=id) if fiche_inscription != None: eleve = fiche_inscription.eleve responsable = eleve.getResponsablePrincipal() mail = responsable.mail errorMessage = mailer.envoieRelanceDossierInscription(mail, fiche_inscription.codeLienInscription) if errorMessage == '': fiche_inscription.etat=FicheInscription.EtatDossierInscription.DI_ENVOYE fiche_inscription.dateMAJ=util.convertToStr(util._now(), '%d-%m-%Y %H:%M') fiche_inscription.save() return JsonResponse({"errorMessage":errorMessage}, safe=False) return JsonResponse({"errorMessage":'Aucun dossier d\'inscription rattaché à l\'élève'}, safe=False) # API utilisée pour la vue parent class ListeEnfantsView(APIView): # Récupération des élèves d'un parent # idProfile : identifiant du profil connecté rattaché aux fiches d'élèves def get(self, request, _idProfile): students = bdd.getObjects(_objectName=FicheInscription, _columnName='eleve__responsables__profilAssocie__id', _value=_idProfile) students_serializer = FicheInscriptionByParentSerializer(students, many=True) return JsonResponse(students_serializer.data, safe=False) # API utilisée pour la vue de création d'un DI class ListeElevesView(APIView): # Récupération de la liste des élèves inscrits ou en cours d'inscriptions def get(self, request): students = bdd.getAllObjects(_objectName=Eleve) students_serializer = EleveByDICreationSerializer(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 FraisInscriptionView(APIView): def get(self, request): tarifs = bdd.getAllObjects(FraisInscription) tarifs_serializer = FraisInscriptionSerializer(tarifs, many=True) return JsonResponse(tarifs_serializer.data, safe=False) class FichierInscriptionView(APIView): parser_classes = (MultiPartParser, FormParser) def get(self, request): fichiers = FichierInscription.objects.all() serializer = FichierInscriptionSerializer(fichiers, many=True) return Response(serializer.data) def post(self, request): serializer = FichierInscriptionSerializer(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): fichierInscription = bdd.getObject(_objectName=FichierInscription, _columnName='id', _value=_id) if fichierInscription is not None: fichierInscription.file.delete() # Supprimer le fichier uploadé fichierInscription.delete() return JsonResponse({'message': 'La suppression du fichier d\'inscription a été effectuée avec succès'}, safe=False) else: return JsonResponse({'erreur': 'Le fichier d\'inscription n\'a pas été trouvé'}, safe=False)