""" Repository pour la gestion des appréciations du conseil de classe. """ from typing import List, Optional from sqlalchemy.orm import joinedload from models import CouncilAppreciation, db from repositories.base_repository import BaseRepository class AppreciationRepository(BaseRepository[CouncilAppreciation]): """Repository pour les appréciations du conseil de classe.""" def __init__(self): super().__init__(CouncilAppreciation) def find_by_class_trimester(self, class_group_id: int, trimester: int) -> List[CouncilAppreciation]: """Trouve toutes les appréciations d'une classe pour un trimestre.""" return CouncilAppreciation.query.filter_by( class_group_id=class_group_id, trimester=trimester ).options( joinedload(CouncilAppreciation.student), joinedload(CouncilAppreciation.class_group) ).all() def find_by_student_trimester( self, student_id: int, class_group_id: int, trimester: int ) -> Optional[CouncilAppreciation]: """Trouve l'appréciation d'un élève pour un trimestre.""" return CouncilAppreciation.query.filter_by( student_id=student_id, class_group_id=class_group_id, trimester=trimester ).options( joinedload(CouncilAppreciation.student), joinedload(CouncilAppreciation.class_group) ).first() def find_by_student_all_trimesters( self, student_id: int, class_group_id: int ) -> List[CouncilAppreciation]: """Trouve toutes les appréciations d'un élève pour tous les trimestres.""" return CouncilAppreciation.query.filter_by( student_id=student_id, class_group_id=class_group_id ).options( joinedload(CouncilAppreciation.student), joinedload(CouncilAppreciation.class_group) ).order_by(CouncilAppreciation.trimester).all() def count_with_content_by_class_trimester( self, class_group_id: int, trimester: int ) -> int: """Compte le nombre d'appréciations avec contenu pour une classe/trimestre.""" return CouncilAppreciation.query.filter( CouncilAppreciation.class_group_id == class_group_id, CouncilAppreciation.trimester == trimester, db.or_( CouncilAppreciation.general_appreciation.isnot(None), CouncilAppreciation.strengths.isnot(None), CouncilAppreciation.areas_for_improvement.isnot(None) ) ).count() def get_completion_stats(self, class_group_id: int, trimester: int) -> dict: """Statistiques de completion des appréciations pour une classe/trimestre.""" from repositories.temporal_student_repository import TemporalStudentRepository # Nombre total d'élèves actuellement dans la classe temporal_repo = TemporalStudentRepository() current_students = temporal_repo.find_current_students_in_class(class_group_id) total_students = len(current_students) # Nombre d'appréciations existantes total_appreciations = CouncilAppreciation.query.filter_by( class_group_id=class_group_id, trimester=trimester ).count() # Nombre d'appréciations avec contenu completed_appreciations = self.count_with_content_by_class_trimester( class_group_id, trimester ) # Nombre d'appréciations finalisées finalized_appreciations = CouncilAppreciation.query.filter_by( class_group_id=class_group_id, trimester=trimester, status='finalized' ).count() return { 'total_students': total_students, 'total_appreciations': total_appreciations, 'completed_appreciations': completed_appreciations, 'finalized_appreciations': finalized_appreciations, 'completion_percentage': (completed_appreciations / total_students * 100) if total_students > 0 else 0, 'finalization_percentage': (finalized_appreciations / total_students * 100) if total_students > 0 else 0 } def create_or_update( self, student_id: int, class_group_id: int, trimester: int, data: dict ) -> CouncilAppreciation: """Crée ou met à jour une appréciation.""" existing = self.find_by_student_trimester(student_id, class_group_id, trimester) if existing: # Mise à jour for key, value in data.items(): if hasattr(existing, key): setattr(existing, key, value) self.commit() return existing else: # Création appreciation_data = { 'student_id': student_id, 'class_group_id': class_group_id, 'trimester': trimester, **data } appreciation = CouncilAppreciation(**appreciation_data) self.save(appreciation) self.commit() return appreciation def delete_by_student_trimester( self, student_id: int, class_group_id: int, trimester: int ) -> bool: """Supprime une appréciation spécifique.""" appreciation = self.find_by_student_trimester(student_id, class_group_id, trimester) if appreciation: self.delete(appreciation) return True return False def get_students_without_appreciation( self, class_group_id: int, trimester: int ) -> List: """Retourne la liste des élèves sans appréciation pour un trimestre.""" from models import Student # Sous-requête pour les élèves qui ont déjà une appréciation students_with_appreciation = db.session.query(CouncilAppreciation.student_id).filter_by( class_group_id=class_group_id, trimester=trimester ).subquery() # Élèves sans appréciation students_without = Student.query.filter_by( class_group_id=class_group_id ).filter( ~Student.id.in_(students_with_appreciation) ).order_by(Student.last_name, Student.first_name).all() return students_without