refact: use repositories patterns for classes

This commit is contained in:
2025-08-08 06:04:55 +02:00
parent 35bf575125
commit 5c25723e4f
13 changed files with 2325 additions and 54 deletions

View File

@@ -1,8 +1,8 @@
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify, current_app
from models import db, ClassGroup
from models import db
from forms import AssessmentForm
from services import AssessmentService
from repositories import AssessmentRepository
from repositories import AssessmentRepository, ClassRepository
from utils import handle_db_errors, ValidationError
bp = Blueprint('assessments', __name__, url_prefix='/assessments')
@@ -11,6 +11,7 @@ bp = Blueprint('assessments', __name__, url_prefix='/assessments')
@handle_db_errors
def list():
assessment_repo = AssessmentRepository()
class_repo = ClassRepository()
# Récupérer les paramètres de filtrage
trimester_filter = request.args.get('trimester', '')
@@ -30,7 +31,7 @@ def list():
total_assessments = assessment_repo.find_by_filters()
# Récupérer toutes les classes pour le filtre
classes = ClassGroup.query.order_by(ClassGroup.name.asc()).all()
classes = class_repo.find_for_form_choices()
return render_template('assessments.html',
assessments=assessments,
@@ -115,8 +116,10 @@ def _handle_unified_assessment_request(form, assessment=None, is_edit=False):
@handle_db_errors
def edit(id):
assessment_repo = AssessmentRepository()
class_repo = ClassRepository()
assessment = assessment_repo.get_with_full_details_or_404(id)
form = AssessmentForm(obj=assessment)
form.populate_class_choices(class_repo)
result = _handle_unified_assessment_request(form, assessment, is_edit=True)
if result:
@@ -163,7 +166,9 @@ def edit(id):
@handle_db_errors
def new():
from app_config import config_manager
class_repo = ClassRepository()
form = AssessmentForm()
form.populate_class_choices(class_repo)
result = _handle_unified_assessment_request(form, is_edit=False)
if result:

View File

@@ -2,6 +2,7 @@ from flask import Blueprint, render_template, redirect, url_for, flash, request,
from models import db, ClassGroup, Student, Assessment
from forms import ClassGroupForm
from utils import handle_db_errors, ValidationError
from repositories.class_repository import ClassRepository
bp = Blueprint('classes', __name__, url_prefix='/classes')
@@ -20,12 +21,12 @@ def new():
def create():
"""Traitement de la création d'une classe."""
form = ClassGroupForm()
class_repo = ClassRepository()
if form.validate_on_submit():
try:
# Vérification d'unicité du nom de classe
existing_class = ClassGroup.query.filter_by(name=form.name.data).first()
if existing_class:
if class_repo.exists_by_name(form.name.data):
flash('Une classe avec ce nom existe déjà.', 'error')
return render_template('class_form.html',
form=form,
@@ -60,7 +61,8 @@ def create():
@handle_db_errors
def edit(id):
"""Formulaire de modification d'une classe."""
class_group = ClassGroup.query.get_or_404(id)
class_repo = ClassRepository()
class_group = class_repo.get_or_404(id)
form = ClassGroupForm(obj=class_group)
return render_template('class_form.html',
@@ -73,18 +75,14 @@ def edit(id):
@handle_db_errors
def update(id):
"""Traitement de la modification d'une classe."""
class_group = ClassGroup.query.get_or_404(id)
class_repo = ClassRepository()
class_group = class_repo.get_or_404(id)
form = ClassGroupForm()
if form.validate_on_submit():
try:
# Vérification d'unicité du nom (sauf si c'est le même nom)
existing_class = ClassGroup.query.filter(
ClassGroup.name == form.name.data,
ClassGroup.id != id
).first()
if existing_class:
if class_repo.exists_by_name(form.name.data, exclude_id=id):
flash('Une autre classe avec ce nom existe déjà.', 'error')
return render_template('class_form.html',
form=form,
@@ -118,14 +116,16 @@ def update(id):
@handle_db_errors
def delete(id):
"""Suppression d'une classe avec vérifications."""
class_group = ClassGroup.query.get_or_404(id)
class_repo = ClassRepository()
class_group = class_repo.get_or_404(id)
try:
# Vérifier s'il y a des étudiants ou des évaluations liés
students_count = Student.query.filter_by(class_group_id=id).count()
assessments_count = Assessment.query.filter_by(class_group_id=id).count()
can_delete, dependencies = class_repo.can_be_deleted(id)
if students_count > 0 or assessments_count > 0:
if not can_delete:
students_count = dependencies['students']
assessments_count = dependencies['assessments']
flash(
f'Impossible de supprimer la classe "{class_group.name}". '
f'Elle contient {students_count} élève(s) et {assessments_count} évaluation(s). '
@@ -152,17 +152,19 @@ def delete(id):
@handle_db_errors
def details(id):
"""Page de détail d'une classe avec ses étudiants et évaluations."""
class_group = ClassGroup.query.get_or_404(id)
class_repo = ClassRepository()
class_group = class_repo.find_with_full_details(id)
# Récupérer les étudiants triés par nom
students = Student.query.filter_by(class_group_id=id).order_by(
Student.last_name, Student.first_name
).all()
if not class_group:
# Gestion manuelle du 404 car find_with_full_details retourne None
from flask import abort
abort(404)
# Récupérer les évaluations récentes
recent_assessments = Assessment.query.filter_by(class_group_id=id).order_by(
Assessment.date.desc()
).limit(5).all()
# Trier les étudiants par nom (optimisé en Python car déjà chargés)
students = sorted(class_group.students, key=lambda s: (s.last_name, s.first_name))
# Prendre les 5 évaluations les plus récentes (optimisé en Python car déjà chargées)
recent_assessments = sorted(class_group.assessments, key=lambda a: a.date, reverse=True)[:5]
return render_template('class_details.html',
class_group=class_group,