from django.db import models from django.utils.timezone import now from django.conf import settings from django.utils.translation import gettext_lazy as _ from Auth.models import Profile from School.models import SchoolClass, Fee, Discount, Establishment from datetime import datetime class Language(models.Model): """ Représente une langue parlée par l’élève. """ id = models.AutoField(primary_key=True) label = models.CharField(max_length=200, default="") def __str__(self): return "LANGUAGE" class Guardian(models.Model): """ Représente un responsable légal (parent/tuteur) d’un élève. """ last_name = models.CharField(max_length=200, default="") first_name = models.CharField(max_length=200, default="") birth_date = models.CharField(max_length=200, default="", blank=True) address = models.CharField(max_length=200, default="", blank=True) email = models.CharField(max_length=200, default="", blank=True) phone = models.CharField(max_length=200, default="", blank=True) profession = models.CharField(max_length=200, default="", blank=True) associated_profile = models.ForeignKey(Profile, on_delete=models.CASCADE) def __str__(self): return self.last_name + "_" + self.first_name class Sibling(models.Model): """ Représente un frère ou une sœur d’un élève. """ id = models.AutoField(primary_key=True) last_name = models.CharField(max_length=200, default="") first_name = models.CharField(max_length=200, default="") birth_date = models.CharField(max_length=200, default="", blank=True) def __str__(self): return "SIBLING" class Student(models.Model): """ Représente l’élève inscrit ou en cours d’inscription. """ class StudentGender(models.IntegerChoices): NONE = 0, _('Sélection du genre') MALE = 1, _('Garçon') FEMALE = 2, _('Fille') class StudentLevel(models.IntegerChoices): NONE = 0, _('Sélection du niveau') TPS = 1, _('TPS - Très Petite Section') PS = 2, _('PS - Petite Section') MS = 3, _('MS - Moyenne Section') GS = 4, _('GS - Grande Section') class PaymentMethod(models.IntegerChoices): NONE = 0, _('Sélection du mode de paiement') SEPA_DIRECT_DEBIT = 1, _('Prélèvement SEPA') CHECK = 2, _('Chèques') last_name = models.CharField(max_length=200, default="") first_name = models.CharField(max_length=200, default="") gender = models.IntegerField(choices=StudentGender, default=StudentGender.NONE, blank=True) level = models.IntegerField(choices=StudentLevel, default=StudentLevel.NONE, blank=True) nationality = models.CharField(max_length=200, default="", blank=True) address = models.CharField(max_length=200, default="", blank=True) birth_date = models.DateField(null=True, blank=True) birth_place = models.CharField(max_length=200, default="", blank=True) birth_postal_code = models.IntegerField(default=0, blank=True) attending_physician = models.CharField(max_length=200, default="", blank=True) payment_method = models.IntegerField(choices=PaymentMethod, default=PaymentMethod.NONE, blank=True) # Many-to-Many Relationship profiles = models.ManyToManyField(Profile, blank=True) # Many-to-Many Relationship guardians = models.ManyToManyField(Guardian, blank=True) # Many-to-Many Relationship siblings = models.ManyToManyField(Sibling, blank=True) # Many-to-Many Relationship registration_files = models.ManyToManyField('RegistrationFile', blank=True, related_name='students') # Many-to-Many Relationship spoken_languages = models.ManyToManyField(Language, blank=True) # One-to-Many Relationship associated_class = models.ForeignKey(SchoolClass, on_delete=models.SET_NULL, null=True, blank=True, related_name='students') def __str__(self): return self.last_name + "_" + self.first_name def getSpokenLanguages(self): """ Retourne la liste des langues parlées par l’élève. """ return self.spoken_languages.all() def getMainGuardian(self): """ Retourne le responsable légal principal de l’élève. """ return self.guardians.all()[0] def getGuardians(self): """ Retourne tous les responsables légaux de l’élève. """ return self.guardians.all() def getProfiles(self): """ Retourne les profils utilisateurs liés à l’élève. """ return self.profiles.all() def getSiblings(self): """ Retourne les frères et sœurs de l’élève. """ return self.siblings.all() def getNumberOfSiblings(self): """ Retourne le nombre de frères et sœurs. """ return self.siblings.count() @property def age(self): if self.birth_date: today = datetime.today() years = today.year - self.birth_date.year months = today.month - self.birth_date.month if today.day < self.birth_date.day: months -= 1 if months < 0: years -= 1 months += 12 # Determine the age format if 6 <= months <= 12: return f"{years} years 1/2" else: return f"{years} years" return None @property def formatted_birth_date(self): if self.birth_date: return self.birth_date.strftime('%d-%m-%Y') return None class RegistrationFileGroup(models.Model): name = models.CharField(max_length=255) description = models.TextField(blank=True, null=True) def __str__(self): return self.name def registration_file_path(instance, filename): # Génère le chemin : registration_files/dossier_rf_{student_id}/filename return f'registration_files/dossier_rf_{instance.student_id}/{filename}' class RegistrationForm(models.Model): """ Gère le dossier d’inscription lié à un élève donné. """ class RegistrationFormStatus(models.IntegerChoices): RF_ABSENT = 0, _('Pas de dossier d\'inscription') RF_CREATED = 1, _('Dossier d\'inscription créé') RF_SENT = 2, _('Dossier d\'inscription envoyé') RF_UNDER_REVIEW = 3, _('Dossier d\'inscription en cours de validation') RF_TO_BE_FOLLOWED_UP = 4, _('Dossier d\'inscription à relancer') RF_VALIDATED = 5, _('Dossier d\'inscription validé') RF_ARCHIVED = 6, _('Dossier d\'inscription archivé') # One-to-One Relationship student = models.OneToOneField(Student, on_delete=models.CASCADE, primary_key=True) status = models.IntegerField(choices=RegistrationFormStatus, default=RegistrationFormStatus.RF_ABSENT) last_update = models.DateTimeField(auto_now=True) notes = models.CharField(max_length=200, blank=True) registration_link_code = models.CharField(max_length=200, default="", blank=True) registration_file = models.FileField( upload_to=registration_file_path, null=True, blank=True ) associated_rf = models.CharField(max_length=200, default="", blank=True) # Many-to-Many Relationship fees = models.ManyToManyField(Fee, blank=True, related_name='register_forms') # Many-to-Many Relationship discounts = models.ManyToManyField(Discount, blank=True, related_name='register_forms') fileGroup = models.ForeignKey(RegistrationFileGroup, on_delete=models.CASCADE, related_name='file_group', null=True, blank=True) establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='register_forms') def __str__(self): return "RF_" + self.student.last_name + "_" + self.student.first_name class RegistrationFileTemplate(models.Model): """ Modèle pour stocker les fichiers "templates" d’inscription. """ name = models.CharField(max_length=255) file = models.FileField(upload_to='templates_files/', blank=True, null=True) order = models.PositiveIntegerField(default=0) # Ajout du champ order date_added = models.DateTimeField(auto_now_add=True) is_required = models.BooleanField(default=False) group = models.ForeignKey(RegistrationFileGroup, on_delete=models.CASCADE, related_name='file_templates', null=True, blank=True) @property def formatted_date_added(self): if self.date_added: return self.date_added.strftime('%d-%m-%Y') return None def __str__(self): return self.name def registration_file_upload_to(instance, filename): return f"registration_files/dossier_rf_{instance.register_form.pk}/{filename}" class RegistrationFile(models.Model): """ Fichier lié à un dossier d’inscription particulier. """ name = models.CharField(max_length=255) file = models.FileField(upload_to=registration_file_upload_to) date_added = models.DateTimeField(auto_now_add=True) template = models.OneToOneField(RegistrationFileTemplate, on_delete=models.CASCADE) register_form = models.ForeignKey('RegistrationForm', on_delete=models.CASCADE, related_name='registration_files') @property def formatted_date_added(self): if self.date_added: return self.date_added.strftime('%d-%m-%Y') return None def __str__(self): return self.name @staticmethod def get_files_from_rf(register_form_id): """ Récupère tous les fichiers liés à un dossier d’inscription donné. """ registration_files = RegistrationFile.objects.filter(register_form_id=register_form_id).order_by('template__order') filenames = [] for reg_file in registration_files: filenames.append(reg_file.file.path) return filenames