feat: improve assessment creation and edition
This commit is contained in:
		| @@ -1,55 +1,153 @@ | ||||
| from flask import Blueprint, render_template, redirect, url_for, flash, request | ||||
| from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify, current_app | ||||
| from models import db, Assessment, ClassGroup | ||||
| from forms import AssessmentForm | ||||
| from services import AssessmentService | ||||
| from utils import handle_db_errors, ValidationError | ||||
| from datetime import datetime | ||||
|  | ||||
| bp = Blueprint('assessments', __name__, url_prefix='/assessments') | ||||
|  | ||||
| @bp.route('/') | ||||
| @handle_db_errors | ||||
| def list(): | ||||
|     assessments = Assessment.query.join(ClassGroup).order_by(Assessment.date.desc()).all() | ||||
|     from sqlalchemy.orm import joinedload | ||||
|     assessments = Assessment.query.options(joinedload(Assessment.class_group)).order_by(Assessment.date.desc()).all() | ||||
|     return render_template('assessments.html', assessments=assessments) | ||||
|  | ||||
| @bp.route('/new', methods=['GET', 'POST']) | ||||
| def new(): | ||||
|     form = AssessmentForm() | ||||
|     if form.validate_on_submit(): | ||||
|         assessment = Assessment( | ||||
|             title=form.title.data, | ||||
|             description=form.description.data, | ||||
|             date=form.date.data, | ||||
|             class_group_id=form.class_group_id.data, | ||||
|             coefficient=form.coefficient.data | ||||
|         ) | ||||
|         db.session.add(assessment) | ||||
|         db.session.commit() | ||||
|         flash('Évaluation créée avec succès !', 'success') | ||||
|         return redirect(url_for('assessments.detail', id=assessment.id)) | ||||
|     return render_template('assessment_form.html', form=form, title='Nouvelle évaluation') | ||||
| # Route obsolète supprimée - utiliser new_unified à la place | ||||
|  | ||||
| @bp.route('/<int:id>') | ||||
| @handle_db_errors | ||||
| def detail(id): | ||||
|     assessment = Assessment.query.get_or_404(id) | ||||
|     from sqlalchemy.orm import joinedload | ||||
|     from models import Exercise, GradingElement | ||||
|     assessment = Assessment.query.options( | ||||
|         joinedload(Assessment.class_group), | ||||
|         joinedload(Assessment.exercises).joinedload(Exercise.grading_elements) | ||||
|     ).get_or_404(id) | ||||
|     return render_template('assessment_detail.html', assessment=assessment) | ||||
|  | ||||
| def _handle_unified_assessment_request(form, assessment=None, is_edit=False): | ||||
|     """Fonction helper pour traiter les requêtes JSON d'évaluation unifiée""" | ||||
|     # Ne traiter que les requêtes POST | ||||
|     if request.method != 'POST': | ||||
|         return None | ||||
|          | ||||
|     if request.is_json: | ||||
|         try: | ||||
|             data = request.get_json() | ||||
|             if not data: | ||||
|                 return jsonify({'success': False, 'error': 'Aucune donnée fournie'}), 400 | ||||
|              | ||||
|             # Peupler le formulaire pour validation CSRF | ||||
|             form.csrf_token.data = data.get('csrf_token') | ||||
|              | ||||
|             # Traitement via le service | ||||
|             if is_edit and assessment: | ||||
|                 processed_assessment = AssessmentService.process_assessment_with_exercises( | ||||
|                     data, is_edit=True, existing_assessment=assessment | ||||
|                 ) | ||||
|             else: | ||||
|                 processed_assessment = AssessmentService.process_assessment_with_exercises(data) | ||||
|              | ||||
|             db.session.commit() | ||||
|             flash('Évaluation ' + ('modifiée' if is_edit else 'créée') + ' avec succès !', 'success') | ||||
|             return jsonify({'success': True, 'assessment_id': processed_assessment.id}) | ||||
|              | ||||
|         except ValidationError as e: | ||||
|             current_app.logger.warning(f'Erreur de validation: {e}') | ||||
|             return jsonify({'success': False, 'error': str(e)}), 400 | ||||
|         except ValueError as e: | ||||
|             current_app.logger.warning(f'Erreur de données: {e}') | ||||
|             return jsonify({'success': False, 'error': str(e)}), 400 | ||||
|              | ||||
|     else:  # request.method == 'POST' and not request.is_json | ||||
|         # Traitement classique du formulaire (fallback) | ||||
|         if form.validate_on_submit(): | ||||
|             if is_edit and assessment: | ||||
|                 AssessmentService.update_assessment_basic_info(assessment, { | ||||
|                     'title': form.title.data, | ||||
|                     'description': form.description.data, | ||||
|                     'date': form.date.data, | ||||
|                     'class_group_id': form.class_group_id.data, | ||||
|                     'coefficient': form.coefficient.data | ||||
|                 }) | ||||
|             else: | ||||
|                 assessment = AssessmentService.create_assessment({ | ||||
|                     'title': form.title.data, | ||||
|                     'description': form.description.data, | ||||
|                     'date': form.date.data, | ||||
|                     'class_group_id': form.class_group_id.data, | ||||
|                     'coefficient': form.coefficient.data | ||||
|                 }) | ||||
|             db.session.commit() | ||||
|             flash('Évaluation ' + ('modifiée' if is_edit else 'créée') + ' avec succès !', 'success') | ||||
|             return redirect(url_for('assessments.detail', id=assessment.id)) | ||||
|      | ||||
|     return None | ||||
|  | ||||
| @bp.route('/<int:id>/edit', methods=['GET', 'POST']) | ||||
| @handle_db_errors | ||||
| def edit(id): | ||||
|     assessment = Assessment.query.get_or_404(id) | ||||
|     from sqlalchemy.orm import joinedload | ||||
|     from models import Exercise, GradingElement | ||||
|     assessment = Assessment.query.options( | ||||
|         joinedload(Assessment.class_group), | ||||
|         joinedload(Assessment.exercises).joinedload(Exercise.grading_elements) | ||||
|     ).get_or_404(id) | ||||
|     form = AssessmentForm(obj=assessment) | ||||
|     if form.validate_on_submit(): | ||||
|         assessment.title = form.title.data | ||||
|         assessment.description = form.description.data | ||||
|         assessment.date = form.date.data | ||||
|         assessment.class_group_id = form.class_group_id.data | ||||
|         assessment.coefficient = form.coefficient.data | ||||
|         db.session.commit() | ||||
|         flash('Évaluation modifiée avec succès !', 'success') | ||||
|         return redirect(url_for('assessments.detail', id=assessment.id)) | ||||
|     return render_template('assessment_form.html', form=form, title='Modifier l\'évaluation', assessment=assessment) | ||||
|      | ||||
|     result = _handle_unified_assessment_request(form, assessment, is_edit=True) | ||||
|     if result: | ||||
|         return result | ||||
|      | ||||
|     # Préparer les exercices pour la sérialisation JSON | ||||
|     exercises_data = [] | ||||
|     for exercise in assessment.exercises: | ||||
|         exercise_data = { | ||||
|             'id': exercise.id, | ||||
|             'title': exercise.title, | ||||
|             'description': exercise.description or '', | ||||
|             'order': exercise.order, | ||||
|             'grading_elements': [] | ||||
|         } | ||||
|         for element in exercise.grading_elements: | ||||
|             element_data = { | ||||
|                 'id': element.id, | ||||
|                 'label': element.label, | ||||
|                 'description': element.description or '', | ||||
|                 'skill': element.skill or '', | ||||
|                 'max_points': float(element.max_points), | ||||
|                 'grading_type': element.grading_type | ||||
|             } | ||||
|             exercise_data['grading_elements'].append(element_data) | ||||
|         exercises_data.append(exercise_data) | ||||
|      | ||||
|     return render_template('assessment_form_unified.html',  | ||||
|                          form=form,  | ||||
|                          title='Modifier l\'évaluation complète',  | ||||
|                          assessment=assessment,  | ||||
|                          exercises_json=exercises_data, | ||||
|                          is_edit=True) | ||||
|  | ||||
| @bp.route('/new', methods=['GET', 'POST']) | ||||
| @handle_db_errors | ||||
| def new(): | ||||
|     form = AssessmentForm() | ||||
|      | ||||
|     result = _handle_unified_assessment_request(form, is_edit=False) | ||||
|     if result: | ||||
|         return result | ||||
|      | ||||
|     return render_template('assessment_form_unified.html', form=form, title='Nouvelle évaluation complète') | ||||
|  | ||||
| @bp.route('/<int:id>/delete', methods=['POST']) | ||||
| @handle_db_errors | ||||
| def delete(id): | ||||
|     assessment = Assessment.query.get_or_404(id) | ||||
|     title = assessment.title  # Conserver pour le log | ||||
|     db.session.delete(assessment) | ||||
|     db.session.commit() | ||||
|     current_app.logger.info(f'Évaluation supprimée: {title} (ID: {id})') | ||||
|     flash('Évaluation supprimée avec succès !', 'success') | ||||
|     return redirect(url_for('assessments.list')) | ||||
		Reference in New Issue
	
	Block a user