from django.http.response import JsonResponse from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi from rest_framework.parsers import MultiPartParser, FormParser from rest_framework.response import Response from rest_framework.views import APIView from rest_framework import status import os from Subscriptions.serializers import RegistrationSchoolFileMasterSerializer, RegistrationSchoolFileTemplateSerializer, RegistrationParentFileMasterSerializer, RegistrationParentFileTemplateSerializer from Subscriptions.models import RegistrationSchoolFileMaster, RegistrationSchoolFileTemplate, RegistrationParentFileMaster, RegistrationParentFileTemplate from N3wtSchool import bdd import logging import Subscriptions.util as util logger = logging.getLogger(__name__) class RegistrationSchoolFileMasterView(APIView): parser_classes = [MultiPartParser, FormParser] @swagger_auto_schema( operation_description="Récupère tous les masters de templates d'inscription pour un établissement donné", manual_parameters=[ openapi.Parameter( 'establishment_id', openapi.IN_QUERY, description="ID de l'établissement", type=openapi.TYPE_INTEGER, required=True ) ], responses={200: RegistrationSchoolFileMasterSerializer(many=True)} ) def get(self, request): establishment_id = request.GET.get('establishment_id') if not establishment_id: return Response({'error': "Paramètre 'establishment_id' requis"}, status=status.HTTP_400_BAD_REQUEST) # Filtrer les masters liés à l'établissement via groups.establishment masters = RegistrationSchoolFileMaster.objects.filter( groups__establishment__id=establishment_id ).distinct() serializer = RegistrationSchoolFileMasterSerializer(masters, many=True) return Response(serializer.data) @swagger_auto_schema( operation_description="Crée un nouveau master de template d'inscription", request_body=RegistrationSchoolFileMasterSerializer, responses={ 201: RegistrationSchoolFileMasterSerializer, 400: "Données invalides" } ) def post(self, request): logger.info(f"raw request.data: {request.data}") payload, resp = util.build_payload_from_request(request) if resp: return resp logger.info(f"payload for serializer: {payload}") serializer = RegistrationSchoolFileMasterSerializer(data=payload, partial=True) if serializer.is_valid(): obj = serializer.save() return Response(RegistrationSchoolFileMasterSerializer(obj).data, status=status.HTTP_201_CREATED) logger.error(f"serializer errors: {serializer.errors}") return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class RegistrationSchoolFileMasterSimpleView(APIView): @swagger_auto_schema( operation_description="Récupère un master de template d'inscription spécifique", responses={ 200: RegistrationSchoolFileMasterSerializer, 404: "Master non trouvé" } ) def get(self, request, id): master = bdd.getObject(_objectName=RegistrationSchoolFileMaster, _columnName='id', _value=id) if master is None: return JsonResponse({"errorMessage":'Le master de template n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND) serializer = RegistrationSchoolFileMasterSerializer(master) return JsonResponse(serializer.data, safe=False) @swagger_auto_schema( operation_description="Met à jour un master de template d'inscription existant", request_body=RegistrationSchoolFileMasterSerializer, responses={ 200: RegistrationSchoolFileMasterSerializer, 400: "Données invalides", 404: "Master non trouvé" } ) def put(self, request, id): master = bdd.getObject(_objectName=RegistrationSchoolFileMaster, _columnName='id', _value=id) if master is None: return JsonResponse({'erreur': "Le master de template n'a pas été trouvé"}, safe=False, status=status.HTTP_404_NOT_FOUND) # Normaliser payload (supporte form-data avec champ 'data' JSON ou fichier JSON) payload, resp = util.build_payload_from_request(request) if resp: return resp logger.info(f"payload for update serializer: {payload}") serializer = RegistrationSchoolFileMasterSerializer(master, data=payload, partial=True) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_200_OK) logger.error(f"serializer errors on put: {serializer.errors}") return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( operation_description="Supprime un master de template d'inscription", responses={ 204: "Suppression réussie", 404: "Master non trouvé" } ) def delete(self, request, id): master = bdd.getObject(_objectName=RegistrationSchoolFileMaster, _columnName='id', _value=id) if master is not None: master.delete() return JsonResponse({'message': 'La suppression du master de template a été effectuée avec succès'}, safe=False, status=status.HTTP_200_OK) else: return JsonResponse({'erreur': 'Le master de template n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND) class RegistrationSchoolFileTemplateView(APIView): @swagger_auto_schema( operation_description="Récupère tous les templates d'inscription pour un établissement donné", manual_parameters=[ openapi.Parameter( 'establishment_id', openapi.IN_QUERY, description="ID de l'établissement", type=openapi.TYPE_INTEGER, required=True ) ], responses={200: RegistrationSchoolFileTemplateSerializer(many=True)} ) def get(self, request): establishment_id = request.GET.get('establishment_id') if not establishment_id: return Response({'error': "Paramètre 'establishment_id' requis"}, status=status.HTTP_400_BAD_REQUEST) # Filtrer les templates liés à l'établissement via master.groups.establishment templates = RegistrationSchoolFileTemplate.objects.filter( master__groups__establishment__id=establishment_id ).distinct() serializer = RegistrationSchoolFileTemplateSerializer(templates, many=True) return Response(serializer.data) @swagger_auto_schema( operation_description="Crée un nouveau template d'inscription", request_body=RegistrationSchoolFileTemplateSerializer, responses={ 201: RegistrationSchoolFileTemplateSerializer, 400: "Données invalides" } ) def post(self, request): serializer = RegistrationSchoolFileTemplateSerializer(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) class RegistrationSchoolFileTemplateSimpleView(APIView): @swagger_auto_schema( operation_description="Récupère un template d'inscription spécifique", responses={ 200: RegistrationSchoolFileTemplateSerializer, 404: "Template non trouvé" } ) def get(self, request, id): template = bdd.getObject(_objectName=RegistrationSchoolFileTemplate, _columnName='id', _value=id) if template is None: return JsonResponse({"errorMessage":'Le template d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND) serializer = RegistrationSchoolFileTemplateSerializer(template) return JsonResponse(serializer.data, safe=False) @swagger_auto_schema( operation_description="Met à jour un template d'inscription existant", request_body=RegistrationSchoolFileTemplateSerializer, responses={ 200: RegistrationSchoolFileTemplateSerializer, 400: "Données invalides", 404: "Template non trouvé" } ) def put(self, request, id): template = bdd.getObject(_objectName=RegistrationSchoolFileTemplate, _columnName='id', _value=id) if template is None: return JsonResponse({'erreur': 'Le template d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND) serializer = RegistrationSchoolFileTemplateSerializer(template, data=request.data) if serializer.is_valid(): serializer.save() return Response({'message': 'Template mis à jour avec succès', 'data': serializer.data}, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( operation_description="Supprime un template d'inscription", responses={ 204: "Suppression réussie", 404: "Template non trouvé" } ) def delete(self, request, id): template = bdd.getObject(_objectName=RegistrationSchoolFileTemplate, _columnName='id', _value=id) if template is not None: # Suppression du fichier PDF associé if template.file and template.file.name: file_path = template.file.path template.file.delete(save=False) # Vérification post-suppression if os.path.exists(file_path): try: os.remove(file_path) logger.info(f"Fichier supprimé manuellement: {file_path}") except Exception as e: logger.error(f"Erreur lors de la suppression manuelle du fichier: {e}") template.delete() return JsonResponse({'message': 'La suppression du template a été effectuée avec succès'}, safe=False, status=status.HTTP_204_NO_CONTENT) else: return JsonResponse({'erreur': 'Le template n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND) class RegistrationParentFileMasterView(APIView): @swagger_auto_schema( operation_description="Récupère tous les fichiers parents pour un établissement donné", manual_parameters=[ openapi.Parameter( 'establishment_id', openapi.IN_QUERY, description="ID de l'établissement", type=openapi.TYPE_INTEGER, required=True ) ], responses={200: RegistrationParentFileMasterSerializer(many=True)} ) def get(self, request): establishment_id = request.GET.get('establishment_id') if not establishment_id: return Response({'error': "Paramètre 'establishment_id' requis"}, status=status.HTTP_400_BAD_REQUEST) # Filtrer les fichiers parents liés à l'établissement templates = RegistrationParentFileMaster.objects.filter( groups__establishment__id=establishment_id ).distinct() serializer = RegistrationParentFileMasterSerializer(templates, many=True) return Response(serializer.data) @swagger_auto_schema( operation_description="Crée un nouveau fichier parent", request_body=RegistrationParentFileMasterSerializer, responses={ 201: RegistrationParentFileMasterSerializer, 400: "Données invalides" } ) def post(self, request): serializer = RegistrationParentFileMasterSerializer(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) class RegistrationParentFileMasterSimpleView(APIView): @swagger_auto_schema( operation_description="Récupère un fichier parent spécifique", responses={ 200: RegistrationParentFileMasterSerializer, 404: "Fichier parent non trouvé" } ) def get(self, request, id): template = bdd.getObject(_objectName=RegistrationParentFileMaster, _columnName='id', _value=id) if template is None: return JsonResponse({"errorMessage":'Le fichier parent n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND) serializer = RegistrationParentFileMasterSerializer(template) return JsonResponse(serializer.data, safe=False) @swagger_auto_schema( operation_description="Met à jour un fichier parent existant", request_body=RegistrationParentFileMasterSerializer, responses={ 200: RegistrationParentFileMasterSerializer, 400: "Données invalides", 404: "Fichier parent non trouvé" } ) def put(self, request, id): template = bdd.getObject(_objectName=RegistrationParentFileMaster, _columnName='id', _value=id) if template is None: return JsonResponse({'erreur': 'Le fichier parent n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND) serializer = RegistrationParentFileMasterSerializer(template, data=request.data) if serializer.is_valid(): serializer.save() return Response({'message': 'Fichier parent mis à jour avec succès', 'data': serializer.data}, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( operation_description="Supprime un fichier parent", responses={ 204: "Suppression réussie", 404: "Fichier parent non trouvé" } ) def delete(self, request, id): template = bdd.getObject(_objectName=RegistrationParentFileMaster, _columnName='id', _value=id) if template is not None: template.delete() return JsonResponse({'message': 'La suppression du fichier parent a été effectuée avec succès'}, safe=False, status=status.HTTP_204_NO_CONTENT) else: return JsonResponse({'erreur': 'Le fichier parent n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND) class RegistrationParentFileTemplateView(APIView): @swagger_auto_schema( operation_description="Récupère tous les templates parents pour un établissement donné", manual_parameters=[ openapi.Parameter( 'establishment_id', openapi.IN_QUERY, description="ID de l'établissement", type=openapi.TYPE_INTEGER, required=True ) ], responses={200: RegistrationParentFileTemplateSerializer(many=True)} ) def get(self, request): establishment_id = request.GET.get('establishment_id') if not establishment_id: return Response({'error': "Paramètre 'establishment_id' requis"}, status=status.HTTP_400_BAD_REQUEST) # Filtrer les templates parents liés à l'établissement via master.groups.establishment templates = RegistrationParentFileTemplate.objects.filter( master__groups__establishment__id=establishment_id ).distinct() serializer = RegistrationParentFileTemplateSerializer(templates, many=True) return Response(serializer.data) @swagger_auto_schema( operation_description="Crée un nouveau template d'inscription", request_body=RegistrationParentFileTemplateSerializer, responses={ 201: RegistrationParentFileTemplateSerializer, 400: "Données invalides" } ) def post(self, request): serializer = RegistrationParentFileTemplateSerializer(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) class RegistrationParentFileTemplateSimpleView(APIView): @swagger_auto_schema( operation_description="Récupère un template d'inscription spécifique", responses={ 200: RegistrationParentFileTemplateSerializer, 404: "Template non trouvé" } ) def get(self, request, id): template = bdd.getObject(_objectName=RegistrationParentFileTemplate, _columnName='id', _value=id) if template is None: return JsonResponse({"errorMessage":'Le template d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND) serializer = RegistrationParentFileTemplateSerializer(template) return JsonResponse(serializer.data, safe=False) @swagger_auto_schema( operation_description="Met à jour un template d'inscription existant", request_body=RegistrationParentFileTemplateSerializer, responses={ 200: RegistrationParentFileTemplateSerializer, 400: "Données invalides", 404: "Template non trouvé" } ) def put(self, request, id): template = bdd.getObject(_objectName=RegistrationParentFileTemplate, _columnName='id', _value=id) if template is None: return JsonResponse({'erreur': 'Le template d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND) serializer = RegistrationParentFileTemplateSerializer(template, data=request.data, partial=True) if serializer.is_valid(): serializer.save() return Response({'message': 'Template mis à jour avec succès', 'data': serializer.data}, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( operation_description="Supprime un template d'inscription", responses={ 204: "Suppression réussie", 404: "Template non trouvé" } ) def delete(self, request, id): template = bdd.getObject(_objectName=RegistrationParentFileTemplate, _columnName='id', _value=id) if template is not None: # Suppression du fichier PDF associé if template.file and template.file.name: file_path = template.file.path template.file.delete(save=False) # Vérification post-suppression if os.path.exists(file_path): try: os.remove(file_path) logger.info(f"Fichier supprimé manuellement: {file_path}") except Exception as e: logger.error(f"Erreur lors de la suppression manuelle du fichier: {e}") template.delete() return JsonResponse({'message': 'La suppression du template a été effectuée avec succès'}, safe=False, status=status.HTTP_204_NO_CONTENT) else: return JsonResponse({'erreur': 'Le template n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)