feat: add commentary in concil prep

This commit is contained in:
2025-08-15 07:59:23 +02:00
parent c3ef5287b3
commit f438082c4c
4 changed files with 656 additions and 5 deletions

View File

@@ -1,7 +1,9 @@
from typing import List, Optional, Dict, Any
from sqlalchemy.orm import joinedload
from sqlalchemy import func
from models import Grade, GradingElement, Exercise, Assessment, Student
from .base_repository import BaseRepository
from app_config import config_manager
class GradeRepository(BaseRepository[Grade]):
@@ -127,4 +129,261 @@ class GradeRepository(BaseRepository[Grade]):
Exercise.assessment_id == assessment_id
).options(
joinedload(Grade.grading_element).joinedload(GradingElement.exercise)
).all()
).all()
def get_special_values_counts_by_student_trimester(self, student_id: int, trimester: int) -> Dict[str, int]:
"""
Compte les valeurs spéciales pour un élève dans un trimestre donné.
Args:
student_id: ID de l'élève
trimester: Numéro du trimestre (1, 2, ou 3)
Returns:
Dictionnaire avec les comptes par valeur spéciale (ex: {'.': 3, 'd': 1, 'a': 0})
"""
# Récupération dynamique des valeurs spéciales configurées
special_values = config_manager.get_special_values()
# Requête pour compter les valeurs spéciales avec jointures optimisées
grade_values = Grade.query.join(
GradingElement
).join(
Exercise
).join(
Assessment
).filter(
Grade.student_id == student_id,
Assessment.trimester == trimester,
Grade.value.in_(list(special_values.keys()))
).with_entities(
Grade.value,
func.count(Grade.value).label('count')
).group_by(
Grade.value
).all()
# Initialiser le dictionnaire avec toutes les valeurs spéciales à 0
result = {value: 0 for value in special_values.keys()}
# Mettre à jour avec les comptes réels
for value, count in grade_values:
if value in result:
result[value] = count
return result
def get_special_values_counts_by_student_assessment(self, student_id: int, assessment_id: int) -> Dict[str, int]:
"""
Compte les valeurs spéciales pour un élève dans une évaluation donnée.
Args:
student_id: ID de l'élève
assessment_id: ID de l'évaluation
Returns:
Dictionnaire avec les comptes par valeur spéciale (ex: {'.': 2, 'd': 0, 'a': 1})
"""
# Récupération dynamique des valeurs spéciales configurées
special_values = config_manager.get_special_values()
# Requête pour compter les valeurs spéciales avec jointures optimisées
grade_values = Grade.query.join(
GradingElement
).join(
Exercise
).filter(
Grade.student_id == student_id,
Exercise.assessment_id == assessment_id,
Grade.value.in_(list(special_values.keys()))
).with_entities(
Grade.value,
func.count(Grade.value).label('count')
).group_by(
Grade.value
).all()
# Initialiser le dictionnaire avec toutes les valeurs spéciales à 0
result = {value: 0 for value in special_values.keys()}
# Mettre à jour avec les comptes réels
for value, count in grade_values:
if value in result:
result[value] = count
return result
def get_special_values_details_by_student_trimester(self, student_id: int, trimester: int) -> Dict[str, List[Dict[str, Any]]]:
"""
Récupère les détails des valeurs spéciales pour un élève dans un trimestre donné.
Args:
student_id: ID de l'élève
trimester: Numéro du trimestre (1, 2, ou 3)
Returns:
Dictionnaire avec les détails par valeur spéciale incluant les commentaires
Format: {'.': [{'element_name': str, 'comment': str, 'assessment_title': str}, ...]}
"""
# Récupération dynamique des valeurs spéciales configurées
special_values = config_manager.get_special_values()
# Requête pour récupérer les détails des valeurs spéciales
grade_details = Grade.query.join(
GradingElement
).join(
Exercise
).join(
Assessment
).filter(
Grade.student_id == student_id,
Assessment.trimester == trimester,
Grade.value.in_(list(special_values.keys()))
).with_entities(
Grade.value,
Grade.comment,
GradingElement.label.label('element_name'),
Assessment.title.label('assessment_title'),
Assessment.id.label('assessment_id')
).all()
# Organiser par valeur spéciale
result_details = {}
# Initialiser avec toutes les valeurs spéciales
for special_value in special_values.keys():
result_details[special_value] = []
# Ajouter les détails trouvés
for detail in grade_details:
result_details[detail.value].append({
'element_name': detail.element_name,
'comment': detail.comment,
'assessment_title': detail.assessment_title,
'assessment_id': detail.assessment_id
})
return result_details
def get_special_values_details_by_student_assessment(self, student_id: int, assessment_id: int) -> Dict[str, List[Dict[str, Any]]]:
"""
Récupère les détails des valeurs spéciales pour un élève dans une évaluation donnée.
Args:
student_id: ID de l'élève
assessment_id: ID de l'évaluation
Returns:
Dictionnaire avec les détails par valeur spéciale incluant les commentaires
Format: {'.': [{'element_name': str, 'comment': str}, ...]}
"""
# Récupération dynamique des valeurs spéciales configurées
special_values = config_manager.get_special_values()
# Requête pour récupérer les détails des valeurs spéciales
grade_details = Grade.query.join(
GradingElement
).join(
Exercise
).filter(
Grade.student_id == student_id,
Exercise.assessment_id == assessment_id,
Grade.value.in_(list(special_values.keys()))
).with_entities(
Grade.value,
Grade.comment,
GradingElement.label.label('element_name')
).all()
# Organiser par valeur spéciale
result_details = {}
# Initialiser avec toutes les valeurs spéciales
for special_value in special_values.keys():
result_details[special_value] = []
# Ajouter les détails trouvés
for detail in grade_details:
result_details[detail.value].append({
'element_name': detail.element_name,
'comment': detail.comment
})
return result_details
def get_all_comments_by_student_trimester(self, student_id: int, trimester: int) -> Dict[str, Any]:
"""
Récupère tous les commentaires regroupés par évaluations pour un élève dans un trimestre.
Args:
student_id: ID de l'élève
trimester: Numéro du trimestre (1, 2, ou 3)
Returns:
Dict avec commentaires organisés par évaluation avec métadonnées complètes
"""
# Requête pour récupérer tous les commentaires non vides avec toutes les informations
grade_comments = Grade.query.join(
GradingElement
).join(
Exercise
).join(
Assessment
).filter(
Grade.student_id == student_id,
Assessment.trimester == trimester,
Grade.comment.isnot(None),
Grade.comment != ''
).with_entities(
Grade.value,
Grade.comment,
GradingElement.label.label('element_label'),
GradingElement.description.label('element_description'),
Assessment.title.label('assessment_title'),
Assessment.id.label('assessment_id'),
Assessment.date.label('assessment_date'),
Exercise.title.label('exercise_title'),
Exercise.order.label('exercise_order')
).order_by(
Assessment.date.desc(),
Exercise.order,
GradingElement.id
).all()
# Organiser par évaluation
comments_by_assessment = {}
for comment_data in grade_comments:
assessment_id = comment_data.assessment_id
# Initialiser l'évaluation si pas encore présente
if assessment_id not in comments_by_assessment:
comments_by_assessment[assessment_id] = {
'id': assessment_id,
'title': comment_data.assessment_title,
'date': comment_data.assessment_date,
'comments': []
}
# Ajouter le commentaire
comments_by_assessment[assessment_id]['comments'].append({
'value': comment_data.value,
'comment': comment_data.comment,
'element_label': comment_data.element_label,
'element_description': comment_data.element_description,
'exercise_title': comment_data.exercise_title,
'exercise_order': comment_data.exercise_order
})
# Convertir en liste triée par date (plus récent en premier)
assessments_with_comments = list(comments_by_assessment.values())
assessments_with_comments.sort(key=lambda x: x['date'] if x['date'] else '', reverse=True)
# Calculer le total de commentaires
total_comments = sum(len(assessment['comments']) for assessment in assessments_with_comments)
return {
'assessments': assessments_with_comments,
'total_comments': total_comments,
'has_comments': total_comments > 0
}