Files
notytex/backend/schemas/council.py
Bertrand Benjamin 2b08eb534a Migration v1 (Flask) -> v2 (FastAPI + Vue.js) complétée
 Changements majeurs:
- Suppression complète du code Flask legacy
- Migration backend FastAPI vers racine /backend
- Migration frontend Vue.js vers racine /frontend
- Suppression de notytex-v2/ (code monté à la racine)

 Validations:
- Backend démarre correctement (port 8000)
- API /api/v2/health répond healthy
- 99/99 tests unitaires passent
- Frontend configuré avec proxy Vite

📝 Documentation:
- README.md réécrit pour v2
- Instructions de démarrage mises à jour
- .gitignore adapté pour backend/frontend/

🎯 Architecture finale:
notytex/
├── backend/     # FastAPI + SQLAlchemy + Pydantic
├── frontend/    # Vue 3 + Vite + TailwindCSS
├── docs/        # Documentation
└── school_management.db  # Base de données (inchangée)

Jalon 6 complété: Application v2 prête pour utilisation!
2025-11-25 21:09:47 +01:00

115 lines
2.9 KiB
Python

"""
Schemas Pydantic pour le conseil de classe.
"""
from datetime import date, datetime
from typing import Optional, List, Dict, Any
from pydantic import Field
from schemas.common import BaseSchema
class AssessmentGradeInfo(BaseSchema):
"""Information sur les notes d'un élève pour une évaluation."""
id: int
title: str
date: Optional[date]
score: float
max_score: float = 20.0
coefficient: float = 1.0
class StudentTrimesterSummaryRead(BaseSchema):
"""Résumé d'un élève pour un trimestre."""
student_id: int
first_name: str
last_name: str
full_name: str
overall_average: Optional[float]
assessment_count: int
grades_by_assessment: Dict[int, AssessmentGradeInfo]
performance_status: str # 'excellent', 'good', 'average', 'struggling', 'no_data'
has_appreciation: bool
appreciation_status: Optional[str] = None # 'draft', 'finalized'
class PerformanceDistribution(BaseSchema):
"""Distribution des performances de la classe."""
excellent: int = 0
good: int = 0
average: int = 0
struggling: int = 0
no_data: int = 0
class ClassStatisticsRead(BaseSchema):
"""Statistiques de la classe pour un trimestre."""
mean: Optional[float]
median: Optional[float]
min: Optional[float]
max: Optional[float]
std_dev: Optional[float]
performance_distribution: PerformanceDistribution
student_count_with_data: int = 0
total_students: int = 0
class AppreciationStatsRead(BaseSchema):
"""Statistiques de completion des appréciations."""
total_students: int
completed_appreciations: int
draft_appreciations: int
finalized_appreciations: int
completion_percentage: float
class CouncilPreparationRead(BaseSchema):
"""Données complètes pour la préparation du conseil de classe."""
class_group_id: int
class_name: str
trimester: int
student_summaries: List[StudentTrimesterSummaryRead]
class_statistics: ClassStatisticsRead
appreciation_stats: AppreciationStatsRead
total_students: int
completed_appreciations: int
class AppreciationCreate(BaseSchema):
"""Données pour créer/mettre à jour une appréciation."""
general_appreciation: Optional[str] = None
strengths: Optional[str] = None
areas_for_improvement: Optional[str] = None
status: str = Field(default="draft", pattern="^(draft|finalized)$")
class AppreciationRead(BaseSchema):
"""Lecture d'une appréciation."""
id: int
student_id: int
class_group_id: int
trimester: int
general_appreciation: Optional[str]
strengths: Optional[str]
areas_for_improvement: Optional[str]
status: str
last_modified: datetime
created_at: datetime
class AppreciationResponse(BaseSchema):
"""Réponse après sauvegarde d'une appréciation."""
success: bool
message: str
appreciation: AppreciationRead