mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
261 lines
9.5 KiB
Python
261 lines
9.5 KiB
Python
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
|
||
|
||
from datetime import datetime
|
||
|
||
class RegistrationFee(models.Model):
|
||
"""
|
||
Représente un tarif ou frais d’inscription avec différentes options de paiement.
|
||
"""
|
||
class PaymentOptions(models.IntegerChoices):
|
||
SINGLE_PAYMENT = 0, _('Paiement en une seule fois')
|
||
MONTHLY_PAYMENT = 1, _('Paiement mensuel')
|
||
QUARTERLY_PAYMENT = 2, _('Paiement trimestriel')
|
||
|
||
name = models.CharField(max_length=255, unique=True)
|
||
description = models.TextField(blank=True)
|
||
base_amount = models.DecimalField(max_digits=10, decimal_places=2)
|
||
discounts = models.JSONField(blank=True, null=True)
|
||
supplements = models.JSONField(blank=True, null=True)
|
||
validity_start_date = models.DateField()
|
||
validity_end_date = models.DateField()
|
||
payment_option = models.IntegerField(choices=PaymentOptions, default=PaymentOptions.SINGLE_PAYMENT)
|
||
|
||
def __str__(self):
|
||
return self.name
|
||
|
||
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 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=settings.DOCUMENT_DIR, default="", blank=True)
|
||
associated_rf = models.CharField(max_length=200, default="", blank=True)
|
||
|
||
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)
|
||
|
||
@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
|