feat: Génération du bilan de compétence en PDF [#16]

This commit is contained in:
N3WT DE COMPET
2025-05-21 20:44:37 +02:00
parent eb7805e54e
commit 0fe6c76189
14 changed files with 357 additions and 67 deletions

View File

@ -2,13 +2,19 @@ from django.http.response import JsonResponse
from rest_framework.views import APIView
from rest_framework import status
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from django.views.decorators.csrf import ensure_csrf_cookie, csrf_protect
from django.utils.decorators import method_decorator
from Subscriptions.models import StudentCompetency, Student
from Common.models import Domain
from School.models import Competency
from N3wtSchool.bdd import delete_object
from django.conf import settings
from datetime import date
from N3wtSchool.renderers import render_to_pdf
from django.core.files import File
from io import BytesIO
import os
import logging
logger = logging.getLogger(__name__)
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
@ -107,6 +113,91 @@ class StudentCompetencyListCreateView(APIView):
updated.append(comp_id)
except StudentCompetency.DoesNotExist:
errors.append({"competenceId": comp_id, "error": "not found"})
# Génération du PDF si au moins une compétence a été mise à jour
if updated:
student = Student.objects.get(id=student_id)
# Reconstituer la structure "domaines" comme dans le GET
student_competencies = StudentCompetency.objects.filter(student=student).select_related(
'establishment_competency',
'establishment_competency__competency',
'establishment_competency__competency__category',
'establishment_competency__competency__category__domain',
'establishment_competency__custom_category',
'establishment_competency__custom_category__domain',
)
result = []
domaines = Domain.objects.all()
for domaine in domaines:
domaine_dict = {
"nom": domaine.name,
"categories": []
}
categories = domaine.categories.all()
for categorie in categories:
categorie_dict = {
"nom": categorie.name,
"competences": []
}
for sc in student_competencies:
ec = sc.establishment_competency
if ec.competency and ec.competency.category_id == categorie.id:
comp = ec.competency
categorie_dict["competences"].append({
"nom": comp.name,
"score": sc.score,
"comment": sc.comment or "",
})
elif ec.competency is None and ec.custom_category_id == categorie.id:
categorie_dict["competences"].append({
"nom": ec.custom_name,
"score": sc.score,
"comment": sc.comment or "",
})
if categorie_dict["competences"]:
domaine_dict["categories"].append(categorie_dict)
if domaine_dict["categories"]:
result.append(domaine_dict)
context = {
"student": {
"first_name": student.first_name,
"last_name": student.last_name,
"level": student.level,
"class_name": student.associated_class.atmosphere_name,
},
"date": date.today().strftime("%d/%m/%Y"),
"domaines": result,
}
print('génération du PDF...')
pdf_result = render_to_pdf('pdfs/bilan_competences.html', context)
# Vérifier si un fichier bilan_form existe déjà et le supprimer
if student.bilan_form and student.bilan_form.name:
if os.path.isabs(student.bilan_form.path):
existing_file_path = student.bilan_form.path
else:
existing_file_path = os.path.join(settings.MEDIA_ROOT, student.bilan_form.name.lstrip('/'))
if os.path.exists(existing_file_path):
os.remove(existing_file_path)
student.bilan_form.delete(save=False)
logger.info(f"Ancien PDF supprimé : {existing_file_path}")
else:
logger.info(f"File does not exist: {existing_file_path}")
try:
filename = f"bilan_competences_{student.last_name}_{student.first_name}.pdf"
student.bilan_form.save(
os.path.basename(filename), # Utiliser uniquement le nom de fichier
File(BytesIO(pdf_result.content)),
save=True
)
except Exception as e:
logger.error(f"Erreur lors de la sauvegarde du fichier PDF : {e}")
raise
# Exemple : retour du PDF dans la réponse HTTP (pour test)
return JsonResponse({"updated": updated, "errors": errors}, status=200)
@method_decorator(csrf_protect, name='dispatch')