refactor: extract duplicated patterns into shared helpers
Backend: create api/helpers.py with eligible_enrollment_filter, count_eligible_students, get_active_enrollment, ensure_unique_name, upsert_app_configs, and build_heatmap. Add full_name properties to Student model. Apply across all route files (-481/+184 lines). Frontend: create stores/helpers.js with withLoading composable, apply to assessments and classes Pinia stores. 96/96 tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ from sqlalchemy import select, func
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
from api.dependencies import AsyncSessionDep
|
||||
from api.helpers import get_active_enrollment
|
||||
from infrastructure.database.models import (
|
||||
Student,
|
||||
StudentEnrollment,
|
||||
@@ -62,12 +63,8 @@ async def get_students(
|
||||
students_list = []
|
||||
for student in students:
|
||||
# Trouver l'inscription active
|
||||
current_enrollment = None
|
||||
for enrollment in student.enrollments:
|
||||
if enrollment.departure_date is None:
|
||||
current_enrollment = enrollment
|
||||
break
|
||||
|
||||
current_enrollment = get_active_enrollment(student)
|
||||
|
||||
# Filtrer par classe si demandé
|
||||
if class_id and (not current_enrollment or current_enrollment.class_group_id != class_id):
|
||||
continue
|
||||
@@ -78,7 +75,7 @@ async def get_students(
|
||||
last_name=student.last_name,
|
||||
first_name=student.first_name,
|
||||
email=student.email,
|
||||
full_name=f"{student.first_name} {student.last_name}",
|
||||
full_name=student.full_name,
|
||||
current_class_id=current_enrollment.class_group_id if current_enrollment else None,
|
||||
current_class_name=current_enrollment.class_group.name if current_enrollment else None
|
||||
)
|
||||
@@ -113,13 +110,10 @@ async def get_student(
|
||||
raise HTTPException(status_code=404, detail="Étudiant non trouvé")
|
||||
|
||||
# Trouver l'inscription active
|
||||
current_enrollment = None
|
||||
current_enrollment = get_active_enrollment(student)
|
||||
enrollments_list = []
|
||||
|
||||
|
||||
for enrollment in student.enrollments:
|
||||
if enrollment.departure_date is None:
|
||||
current_enrollment = enrollment
|
||||
|
||||
enrollments_list.append(
|
||||
EnrollmentRead(
|
||||
id=enrollment.id,
|
||||
@@ -144,7 +138,7 @@ async def get_student(
|
||||
last_name=student.last_name,
|
||||
first_name=student.first_name,
|
||||
email=student.email,
|
||||
full_name=f"{student.first_name} {student.last_name}",
|
||||
full_name=student.full_name,
|
||||
current_class_id=current_enrollment.class_group_id if current_enrollment else None,
|
||||
current_class_name=current_enrollment.class_group.name if current_enrollment else None,
|
||||
enrollments=enrollments_list
|
||||
@@ -210,7 +204,7 @@ async def create_student(
|
||||
last_name=new_student.last_name,
|
||||
first_name=new_student.first_name,
|
||||
email=new_student.email,
|
||||
full_name=f"{new_student.first_name} {new_student.last_name}",
|
||||
full_name=new_student.full_name,
|
||||
current_class_id=current_class_id,
|
||||
current_class_name=current_class_name
|
||||
)
|
||||
@@ -264,18 +258,14 @@ async def update_student(
|
||||
await session.refresh(student)
|
||||
|
||||
# Trouver la classe actuelle
|
||||
current_enrollment = None
|
||||
for enrollment in student.enrollments:
|
||||
if enrollment.departure_date is None:
|
||||
current_enrollment = enrollment
|
||||
break
|
||||
|
||||
current_enrollment = get_active_enrollment(student)
|
||||
|
||||
return StudentWithClass(
|
||||
id=student.id,
|
||||
last_name=student.last_name,
|
||||
first_name=student.first_name,
|
||||
email=student.email,
|
||||
full_name=f"{student.first_name} {student.last_name}",
|
||||
full_name=student.full_name,
|
||||
current_class_id=current_enrollment.class_group_id if current_enrollment else None,
|
||||
current_class_name=current_enrollment.class_group.name if current_enrollment else None
|
||||
)
|
||||
@@ -325,18 +315,14 @@ async def update_student_email(
|
||||
await session.refresh(student)
|
||||
|
||||
# Trouver la classe actuelle
|
||||
current_enrollment = None
|
||||
for enrollment in student.enrollments:
|
||||
if enrollment.departure_date is None:
|
||||
current_enrollment = enrollment
|
||||
break
|
||||
|
||||
current_enrollment = get_active_enrollment(student)
|
||||
|
||||
return StudentWithClass(
|
||||
id=student.id,
|
||||
last_name=student.last_name,
|
||||
first_name=student.first_name,
|
||||
email=student.email,
|
||||
full_name=f"{student.first_name} {student.last_name}",
|
||||
full_name=student.full_name,
|
||||
current_class_id=current_enrollment.class_group_id if current_enrollment else None,
|
||||
current_class_name=current_enrollment.class_group.name if current_enrollment else None
|
||||
)
|
||||
@@ -403,7 +389,7 @@ async def enroll_student(
|
||||
if active_result.scalar_one_or_none():
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"L'élève {student.first_name} {student.last_name} est déjà inscrit dans une classe"
|
||||
detail=f"L'élève {student.full_name} est déjà inscrit dans une classe"
|
||||
)
|
||||
else:
|
||||
# Nouvel élève
|
||||
@@ -447,9 +433,9 @@ async def enroll_student(
|
||||
return EnrollmentResponse(
|
||||
enrollment_id=enrollment.id,
|
||||
student_id=student.id,
|
||||
student_name=f"{student.first_name} {student.last_name}",
|
||||
student_name=student.full_name,
|
||||
class_name=class_group.name,
|
||||
message=f"Élève {student.first_name} {student.last_name} inscrit en {class_group.name}",
|
||||
message=f"Élève {student.full_name} inscrit en {class_group.name}",
|
||||
is_new_student=is_new_student
|
||||
)
|
||||
|
||||
@@ -493,9 +479,9 @@ async def transfer_student(
|
||||
if not old_enrollment:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Aucune inscription active trouvée pour l'élève {student.first_name} {student.last_name}"
|
||||
detail=f"Aucune inscription active trouvée pour l'élève {student.full_name}"
|
||||
)
|
||||
|
||||
|
||||
old_class_name = old_enrollment.class_group.name
|
||||
|
||||
# Terminer l'ancienne inscription
|
||||
@@ -516,10 +502,10 @@ async def transfer_student(
|
||||
return TransferResponse(
|
||||
old_enrollment_id=old_enrollment.id,
|
||||
new_enrollment_id=new_enrollment.id,
|
||||
student_name=f"{student.first_name} {student.last_name}",
|
||||
student_name=student.full_name,
|
||||
old_class_name=old_class_name,
|
||||
new_class_name=new_class.name,
|
||||
message=f"Élève {student.first_name} {student.last_name} transféré de {old_class_name} vers {new_class.name}"
|
||||
message=f"Élève {student.full_name} transféré de {old_class_name} vers {new_class.name}"
|
||||
)
|
||||
|
||||
|
||||
@@ -554,9 +540,9 @@ async def record_departure(
|
||||
if not enrollment:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Aucune inscription active trouvée pour l'élève {student.first_name} {student.last_name}"
|
||||
detail=f"Aucune inscription active trouvée pour l'élève {student.full_name}"
|
||||
)
|
||||
|
||||
|
||||
class_name = enrollment.class_group.name
|
||||
|
||||
# Enregistrer le départ
|
||||
@@ -567,7 +553,7 @@ async def record_departure(
|
||||
|
||||
return DepartureResponse(
|
||||
enrollment_id=enrollment.id,
|
||||
student_name=f"{student.first_name} {student.last_name}",
|
||||
student_name=student.full_name,
|
||||
class_name=class_name,
|
||||
message=f"Départ de {student.first_name} {student.last_name} de {class_name} enregistré"
|
||||
message=f"Départ de {student.full_name} de {class_name} enregistré"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user