161 lines
7.0 KiB
Python
161 lines
7.0 KiB
Python
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
|
|
|
|
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', 'notes')
|
|
if grading_type not in ['notes', '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))
|
|
|
|
# Gestion du domaine
|
|
domain_id = None
|
|
if 'domain_name' in elem_data and elem_data['domain_name']:
|
|
# Récupérer ou créer le domaine
|
|
from app_config import config_manager
|
|
domain = config_manager.get_or_create_domain(
|
|
elem_data['domain_name'],
|
|
elem_data.get('domain_color', '#6B7280')
|
|
)
|
|
domain_id = domain.id
|
|
elif 'domain_id' in elem_data:
|
|
domain_id = elem_data['domain_id']
|
|
|
|
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,
|
|
domain_id=domain_id,
|
|
exercise_id=exercise.id
|
|
)
|
|
db.session.add(grading_element) |