refact: use repositories patterns for classes
This commit is contained in:
210
repositories/class_repository.py
Normal file
210
repositories/class_repository.py
Normal file
@@ -0,0 +1,210 @@
|
||||
from typing import List, Optional, Dict, Tuple
|
||||
from sqlalchemy.orm import joinedload
|
||||
from sqlalchemy import and_
|
||||
from models import ClassGroup, Student, Assessment
|
||||
from .base_repository import BaseRepository
|
||||
|
||||
|
||||
class ClassRepository(BaseRepository[ClassGroup]):
|
||||
"""Repository pour les classes (ClassGroup)."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(ClassGroup)
|
||||
|
||||
def get_or_404(self, id: int) -> ClassGroup:
|
||||
"""
|
||||
Récupère une classe ou lève une erreur 404.
|
||||
|
||||
Args:
|
||||
id: Identifiant de la classe
|
||||
|
||||
Returns:
|
||||
ClassGroup: La classe trouvée
|
||||
|
||||
Raises:
|
||||
404: Si la classe n'existe pas
|
||||
"""
|
||||
return ClassGroup.query.get_or_404(id)
|
||||
|
||||
def find_by_name(self, name: str) -> Optional[ClassGroup]:
|
||||
"""
|
||||
Trouve une classe par son nom.
|
||||
|
||||
Args:
|
||||
name: Nom de la classe à rechercher
|
||||
|
||||
Returns:
|
||||
Optional[ClassGroup]: La classe trouvée ou None
|
||||
"""
|
||||
return ClassGroup.query.filter_by(name=name).first()
|
||||
|
||||
def exists_by_name(self, name: str, exclude_id: Optional[int] = None) -> bool:
|
||||
"""
|
||||
Vérifie si une classe avec ce nom existe déjà.
|
||||
|
||||
Args:
|
||||
name: Nom à vérifier
|
||||
exclude_id: ID de classe à exclure de la recherche (pour la modification)
|
||||
|
||||
Returns:
|
||||
bool: True si une classe avec ce nom existe
|
||||
"""
|
||||
query = ClassGroup.query.filter_by(name=name)
|
||||
|
||||
if exclude_id is not None:
|
||||
query = query.filter(ClassGroup.id != exclude_id)
|
||||
|
||||
return query.first() is not None
|
||||
|
||||
def find_all_ordered(self, order_by: str = 'year_name') -> List[ClassGroup]:
|
||||
"""
|
||||
Trouve toutes les classes triées selon le critère spécifié.
|
||||
|
||||
Args:
|
||||
order_by: Critère de tri ('year_name', 'name', 'year')
|
||||
|
||||
Returns:
|
||||
List[ClassGroup]: Liste des classes triées
|
||||
"""
|
||||
query = ClassGroup.query
|
||||
|
||||
if order_by == 'year_name':
|
||||
query = query.order_by(ClassGroup.year, ClassGroup.name)
|
||||
elif order_by == 'name':
|
||||
query = query.order_by(ClassGroup.name)
|
||||
elif order_by == 'year':
|
||||
query = query.order_by(ClassGroup.year)
|
||||
else:
|
||||
# Défaut : tri par nom
|
||||
query = query.order_by(ClassGroup.name)
|
||||
|
||||
return query.all()
|
||||
|
||||
def count_all(self) -> int:
|
||||
"""
|
||||
Compte le nombre total de classes.
|
||||
|
||||
Returns:
|
||||
int: Nombre de classes
|
||||
"""
|
||||
return ClassGroup.query.count()
|
||||
|
||||
def can_be_deleted(self, id: int) -> Tuple[bool, Dict[str, int]]:
|
||||
"""
|
||||
Vérifie si une classe peut être supprimée et retourne les dépendances.
|
||||
|
||||
Args:
|
||||
id: Identifiant de la classe
|
||||
|
||||
Returns:
|
||||
Tuple[bool, Dict[str, int]]: (peut_être_supprimée, statistiques_dépendances)
|
||||
"""
|
||||
students_count = Student.query.filter_by(class_group_id=id).count()
|
||||
assessments_count = Assessment.query.filter_by(class_group_id=id).count()
|
||||
|
||||
dependencies = {
|
||||
'students': students_count,
|
||||
'assessments': assessments_count
|
||||
}
|
||||
|
||||
can_delete = students_count == 0 and assessments_count == 0
|
||||
|
||||
return can_delete, dependencies
|
||||
|
||||
def find_with_students_ordered(self, id: int) -> Optional[ClassGroup]:
|
||||
"""
|
||||
Trouve une classe avec ses étudiants triés par nom.
|
||||
|
||||
Args:
|
||||
id: Identifiant de la classe
|
||||
|
||||
Returns:
|
||||
Optional[ClassGroup]: La classe avec étudiants triés ou None
|
||||
"""
|
||||
class_group = ClassGroup.query.get(id)
|
||||
if not class_group:
|
||||
return None
|
||||
|
||||
# Charger les étudiants triés
|
||||
students = Student.query.filter_by(class_group_id=id).order_by(
|
||||
Student.last_name, Student.first_name
|
||||
).all()
|
||||
|
||||
# Assigner les étudiants triés à la classe
|
||||
class_group._students_ordered = students
|
||||
|
||||
return class_group
|
||||
|
||||
def find_with_recent_assessments(self, id: int, limit: int = 5) -> Optional[ClassGroup]:
|
||||
"""
|
||||
Trouve une classe avec ses évaluations récentes.
|
||||
|
||||
Args:
|
||||
id: Identifiant de la classe
|
||||
limit: Nombre maximum d'évaluations à récupérer
|
||||
|
||||
Returns:
|
||||
Optional[ClassGroup]: La classe avec évaluations récentes ou None
|
||||
"""
|
||||
class_group = ClassGroup.query.get(id)
|
||||
if not class_group:
|
||||
return None
|
||||
|
||||
# Charger les évaluations récentes
|
||||
recent_assessments = Assessment.query.filter_by(class_group_id=id).order_by(
|
||||
Assessment.date.desc()
|
||||
).limit(limit).all()
|
||||
|
||||
# Assigner les évaluations récentes à la classe
|
||||
class_group._recent_assessments = recent_assessments
|
||||
|
||||
return class_group
|
||||
|
||||
def find_with_full_details(self, id: int) -> Optional[ClassGroup]:
|
||||
"""
|
||||
Trouve une classe avec tous ses détails (étudiants et évaluations).
|
||||
|
||||
Args:
|
||||
id: Identifiant de la classe
|
||||
|
||||
Returns:
|
||||
Optional[ClassGroup]: La classe avec tous ses détails ou None
|
||||
"""
|
||||
return ClassGroup.query.options(
|
||||
joinedload(ClassGroup.students),
|
||||
joinedload(ClassGroup.assessments)
|
||||
).filter_by(id=id).first()
|
||||
|
||||
def get_students_count(self, id: int) -> int:
|
||||
"""
|
||||
Compte le nombre d'étudiants dans une classe.
|
||||
|
||||
Args:
|
||||
id: Identifiant de la classe
|
||||
|
||||
Returns:
|
||||
int: Nombre d'étudiants
|
||||
"""
|
||||
return Student.query.filter_by(class_group_id=id).count()
|
||||
|
||||
def get_assessments_count(self, id: int) -> int:
|
||||
"""
|
||||
Compte le nombre d'évaluations dans une classe.
|
||||
|
||||
Args:
|
||||
id: Identifiant de la classe
|
||||
|
||||
Returns:
|
||||
int: Nombre d'évaluations
|
||||
"""
|
||||
return Assessment.query.filter_by(class_group_id=id).count()
|
||||
|
||||
def find_for_form_choices(self) -> List[ClassGroup]:
|
||||
"""
|
||||
Trouve toutes les classes pour les choix de formulaires.
|
||||
Optimisé pour n'inclure que les champs nécessaires.
|
||||
|
||||
Returns:
|
||||
List[ClassGroup]: Liste des classes triées par nom
|
||||
"""
|
||||
return ClassGroup.query.order_by(ClassGroup.name).all()
|
||||
Reference in New Issue
Block a user