172 lines
6.8 KiB
Python
172 lines
6.8 KiB
Python
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify, current_app
|
|
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')
|
|
|
|
@bp.route('/new')
|
|
@handle_db_errors
|
|
def new():
|
|
"""Formulaire de création d'une nouvelle classe."""
|
|
form = ClassGroupForm()
|
|
return render_template('class_form.html',
|
|
form=form,
|
|
title="Créer une nouvelle classe",
|
|
is_edit=False)
|
|
|
|
@bp.route('/', methods=['POST'])
|
|
@handle_db_errors
|
|
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
|
|
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,
|
|
title="Créer une nouvelle classe",
|
|
is_edit=False)
|
|
|
|
# Création de la nouvelle classe
|
|
class_group = ClassGroup(
|
|
name=form.name.data,
|
|
description=form.description.data,
|
|
year=form.year.data
|
|
)
|
|
|
|
db.session.add(class_group)
|
|
db.session.commit()
|
|
|
|
current_app.logger.info(f'Nouvelle classe créée: {class_group.name}')
|
|
flash(f'Classe "{class_group.name}" créée avec succès !', 'success')
|
|
return redirect(url_for('classes'))
|
|
|
|
except Exception as e:
|
|
db.session.rollback()
|
|
current_app.logger.error(f'Erreur lors de la création de la classe: {e}')
|
|
flash('Erreur lors de la création de la classe.', 'error')
|
|
|
|
return render_template('class_form.html',
|
|
form=form,
|
|
title="Créer une nouvelle classe",
|
|
is_edit=False)
|
|
|
|
@bp.route('/<int:id>/edit')
|
|
@handle_db_errors
|
|
def edit(id):
|
|
"""Formulaire de modification d'une classe."""
|
|
class_repo = ClassRepository()
|
|
class_group = class_repo.get_or_404(id)
|
|
|
|
form = ClassGroupForm(obj=class_group)
|
|
return render_template('class_form.html',
|
|
form=form,
|
|
class_group=class_group,
|
|
title=f"Modifier la classe {class_group.name}",
|
|
is_edit=True)
|
|
|
|
@bp.route('/<int:id>', methods=['POST'])
|
|
@handle_db_errors
|
|
def update(id):
|
|
"""Traitement de la modification d'une classe."""
|
|
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)
|
|
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,
|
|
class_group=class_group,
|
|
title=f"Modifier la classe {class_group.name}",
|
|
is_edit=True)
|
|
|
|
# Mise à jour des données
|
|
class_group.name = form.name.data
|
|
class_group.description = form.description.data
|
|
class_group.year = form.year.data
|
|
|
|
db.session.commit()
|
|
|
|
current_app.logger.info(f'Classe modifiée: {class_group.name}')
|
|
flash(f'Classe "{class_group.name}" modifiée avec succès !', 'success')
|
|
return redirect(url_for('classes'))
|
|
|
|
except Exception as e:
|
|
db.session.rollback()
|
|
current_app.logger.error(f'Erreur lors de la modification de la classe: {e}')
|
|
flash('Erreur lors de la modification de la classe.', 'error')
|
|
|
|
return render_template('class_form.html',
|
|
form=form,
|
|
class_group=class_group,
|
|
title=f"Modifier la classe {class_group.name}",
|
|
is_edit=True)
|
|
|
|
@bp.route('/<int:id>/delete', methods=['POST'])
|
|
@handle_db_errors
|
|
def delete(id):
|
|
"""Suppression d'une classe avec vérifications."""
|
|
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
|
|
can_delete, dependencies = class_repo.can_be_deleted(id)
|
|
|
|
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). '
|
|
f'Supprimez d\'abord ces éléments.',
|
|
'error'
|
|
)
|
|
return redirect(url_for('classes'))
|
|
|
|
# Suppression de la classe
|
|
db.session.delete(class_group)
|
|
db.session.commit()
|
|
|
|
current_app.logger.info(f'Classe supprimée: {class_group.name}')
|
|
flash(f'Classe "{class_group.name}" supprimée avec succès.', 'success')
|
|
|
|
except Exception as e:
|
|
db.session.rollback()
|
|
current_app.logger.error(f'Erreur lors de la suppression de la classe: {e}')
|
|
flash('Erreur lors de la suppression de la classe.', 'error')
|
|
|
|
return redirect(url_for('classes'))
|
|
|
|
@bp.route('/<int:id>/details')
|
|
@handle_db_errors
|
|
def details(id):
|
|
"""Page de détail d'une classe avec ses étudiants et évaluations."""
|
|
class_repo = ClassRepository()
|
|
class_group = class_repo.find_with_full_details(id)
|
|
|
|
if not class_group:
|
|
# Gestion manuelle du 404 car find_with_full_details retourne None
|
|
from flask import abort
|
|
abort(404)
|
|
|
|
# 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,
|
|
students=students,
|
|
recent_assessments=recent_assessments) |