feat(mail): restauration de l'envoie de mail
All checks were successful
Build and Publish Docker Images / Build Frontend Image (push) Successful in 2m56s
Build and Publish Docker Images / Build Backend Image (push) Successful in 3m5s
Build and Publish Docker Images / Build Summary (push) Successful in 3s

This commit is contained in:
2025-12-04 06:04:13 +01:00
parent 08c8ee4931
commit f76b033d55
11 changed files with 1189 additions and 184 deletions

View File

@@ -6,6 +6,7 @@ from typing import Optional, List
from datetime import date
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import HTMLResponse
from sqlalchemy import select, func
from sqlalchemy.orm import selectinload
@@ -392,6 +393,7 @@ async def get_assessment_results(
student_scores[student_id] = StudentScore(
student_id=student_id,
student_name=f"{student.last_name} {student.first_name}",
email=student.email, # Ajouter l'email de l'élève
total_score=round(total_score, 2),
total_max_points=counted_max,
percentage=percentage,
@@ -1215,3 +1217,127 @@ async def send_reports(
results=results,
message=message
)
@router.get("/{assessment_id}/preview-report/{student_id}", response_class=HTMLResponse)
async def preview_report(
assessment_id: int,
student_id: int,
session: AsyncSessionDep,
):
"""
Génère un aperçu HTML du bilan d'un élève sans l'envoyer.
Utile pour vérifier le rendu du bilan avant l'envoi groupé.
Retourne le HTML brut qui serait envoyé par email, directement affichable dans le navigateur.
"""
# Récupérer l'évaluation avec toutes les relations nécessaires
assessment_query = (
select(Assessment)
.options(
selectinload(Assessment.class_group),
selectinload(Assessment.exercises).selectinload(Exercise.grading_elements).selectinload(GradingElement.grades),
selectinload(Assessment.exercises).selectinload(Exercise.grading_elements).selectinload(GradingElement.domain)
)
.where(Assessment.id == assessment_id)
)
assessment_result = await session.execute(assessment_query)
assessment = assessment_result.scalar_one_or_none()
if not assessment:
raise HTTPException(status_code=404, detail="Évaluation non trouvée")
# Récupérer l'élève
student_query = select(Student).where(Student.id == student_id)
student_result = await session.execute(student_query)
student = student_result.scalar_one_or_none()
if not student:
raise HTTPException(status_code=404, detail="Élève non trouvé")
# Préparer les données pour le service de rapport (même logique que send_reports)
assessment_data = {
'title': assessment.title,
'description': assessment.description,
'date': assessment.date.isoformat() if assessment.date else '',
'trimester': assessment.trimester,
'class_name': assessment.class_group.name,
'coefficient': assessment.coefficient
}
# Préparer les données des exercices et éléments
exercises_data = []
all_students_grades = {} # {student_id: [grades]}
for exercise in sorted(assessment.exercises, key=lambda x: x.order):
elements_data = []
for element in exercise.grading_elements:
element_data = {
'id': element.id,
'exercise_id': exercise.id,
'label': element.label,
'description': element.description,
'skill': element.skill,
'domain_name': element.domain.name if element.domain else None,
'domain_color': element.domain.color if element.domain else None,
'grading_type': element.grading_type,
'max_points': element.max_points
}
elements_data.append(element_data)
# Collecter les notes
for grade in element.grades:
if grade.student_id not in all_students_grades:
all_students_grades[grade.student_id] = []
all_students_grades[grade.student_id].append({
'element_id': element.id,
'value': grade.value,
'comment': grade.comment
})
exercises_data.append({
'id': exercise.id,
'title': exercise.title,
'description': exercise.description,
'order': exercise.order,
'elements': elements_data
})
# Vérifier que l'élève a des notes pour cette évaluation
if student_id not in all_students_grades:
raise HTTPException(
status_code=400,
detail=f"L'élève {student.first_name} {student.last_name} n'a pas de notes pour cette évaluation"
)
# Créer le service de rapport
report_service = StudentReportService()
# Préparer les données de l'élève
student_data = {
'id': student.id,
'first_name': student.first_name,
'last_name': student.last_name,
'email': student.email
}
try:
# Générer le rapport
report_data = report_service.generate_student_report(
assessment_data,
student_data,
all_students_grades,
exercises_data
)
# Générer le HTML (sans message personnalisé pour la prévisualisation)
html_body = generate_report_html(report_data, "")
# Retourner directement le HTML pour affichage dans le navigateur
return HTMLResponse(content=html_body)
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"Erreur lors de la génération du rapport: {str(e)}"
)