from models import db, Assessment, Exercise, GradingElement from utils import safe_int_conversion, safe_decimal_conversion, validate_json_data, ValidationError, log_user_action from datetime import datetime from decimal import Decimal class AssessmentService: """Service pour gérer les opérations sur les évaluations""" @staticmethod def create_assessment(form_data): """Crée une nouvelle évaluation""" assessment = Assessment( title=form_data['title'], description=form_data.get('description', ''), date=form_data['date'], trimester=form_data['trimester'], class_group_id=form_data['class_group_id'], coefficient=form_data['coefficient'] ) db.session.add(assessment) db.session.flush() # Pour obtenir l'ID log_user_action("Création évaluation", f"ID: {assessment.id}, Titre: {assessment.title}") return assessment @staticmethod def update_assessment_basic_info(assessment, form_data): """Met à jour les informations de base d'une évaluation""" assessment.title = form_data['title'] assessment.description = form_data.get('description', '') assessment.date = form_data['date'] assessment.trimester = form_data['trimester'] assessment.class_group_id = form_data['class_group_id'] assessment.coefficient = form_data['coefficient'] log_user_action("Modification évaluation", f"ID: {assessment.id}") @staticmethod def delete_assessment_exercises(assessment): """Supprime tous les exercices d'une évaluation (pour remplacement)""" for exercise in assessment.exercises: db.session.delete(exercise) @staticmethod def process_assessment_with_exercises(assessment_data, is_edit=False, existing_assessment=None): """Traite une évaluation complète avec exercices et éléments""" # Validation des données de base required_fields = ['title', 'date', 'trimester', 'class_group_id', 'coefficient'] validate_json_data(assessment_data, required_fields) # Validation et conversion des types try: class_group_id = safe_int_conversion(assessment_data['class_group_id'], "ID de classe") coefficient = safe_decimal_conversion(assessment_data['coefficient'], "coefficient") trimester = safe_int_conversion(assessment_data['trimester'], "trimestre") # Validation du trimestre if trimester not in [1, 2, 3]: raise ValidationError("Le trimestre doit être 1, 2 ou 3") # Validation de la date date_str = assessment_data.get('date') if date_str: date_obj = datetime.strptime(date_str, '%Y-%m-%d').date() else: raise ValidationError("Date requise") except ValueError as e: raise ValidationError(str(e)) # Préparation des données validées validated_data = { 'title': assessment_data['title'].strip(), 'description': assessment_data.get('description', '').strip(), 'date': date_obj, 'trimester': trimester, 'class_group_id': class_group_id, 'coefficient': coefficient } # Création ou mise à jour de l'évaluation if is_edit and existing_assessment: AssessmentService.update_assessment_basic_info(existing_assessment, validated_data) AssessmentService.delete_assessment_exercises(existing_assessment) assessment = existing_assessment else: assessment = AssessmentService.create_assessment(validated_data) # Traitement des exercices exercises_data = assessment_data.get('exercises', []) AssessmentService.process_exercises(assessment, exercises_data) return assessment @staticmethod def process_exercises(assessment, exercises_data): """Traite les exercices d'une évaluation""" for ex_data in exercises_data: # Validation des données d'exercice if not ex_data.get('title'): raise ValidationError("Titre d'exercice requis") try: order = safe_int_conversion(ex_data.get('order', 1), "ordre de l'exercice") if order < 1: raise ValidationError("L'ordre de l'exercice doit être positif") except ValueError as e: raise ValidationError(str(e)) exercise = Exercise( title=ex_data['title'].strip(), description=ex_data.get('description', '').strip(), order=order, assessment_id=assessment.id ) db.session.add(exercise) db.session.flush() # Traitement des éléments de notation grading_elements_data = ex_data.get('grading_elements', []) AssessmentService.process_grading_elements(exercise, grading_elements_data) @staticmethod def process_grading_elements(exercise, grading_elements_data): """Traite les éléments de notation d'un exercice""" for elem_data in grading_elements_data: # Validation des données d'élément if not elem_data.get('label'): raise ValidationError("Libellé d'élément de notation requis") grading_type = elem_data.get('grading_type', 'points') if grading_type not in ['points', 'score']: raise ValidationError("Type de notation invalide") try: max_points = safe_decimal_conversion(elem_data.get('max_points'), "points maximum") if max_points <= 0: raise ValidationError("Les points maximum doivent être positifs") except ValueError as e: raise ValidationError(str(e)) grading_element = GradingElement( label=elem_data['label'].strip(), description=elem_data.get('description', '').strip(), skill=elem_data.get('skill', '').strip(), max_points=max_points, grading_type=grading_type, exercise_id=exercise.id ) db.session.add(grading_element)