Files
notytex/repositories/appreciation_repository.py

172 lines
6.4 KiB
Python

"""
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