Files
notytex/services.py

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)