Files
n3wt-school/Back-End/School/models.py
2025-05-11 20:29:53 +02:00

197 lines
7.8 KiB
Python

from django.db import models
from Auth.models import ProfileRole
from Establishment.models import Establishment
from django.db.models import JSONField
from django.dispatch import receiver
from django.contrib.postgres.fields import ArrayField
from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ValidationError
LEVEL_CHOICES = [
(1, 'Très Petite Section (TPS)'),
(2, 'Petite Section (PS)'),
(3, 'Moyenne Section (MS)'),
(4, 'Grande Section (GS)'),
(5, 'Cours Préparatoire (CP)'),
(6, 'Cours Élémentaire 1 (CE1)'),
(7, 'Cours Élémentaire 2 (CE2)'),
(8, 'Cours Moyen 1 (CM1)'),
(9, 'Cours Moyen 2 (CM2)')
]
class Speciality(models.Model):
name = models.CharField(max_length=100)
updated_date = models.DateTimeField(auto_now=True)
color_code = models.CharField(max_length=7, default='#FFFFFF')
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='specialities')
def __str__(self):
return self.name
class Teacher(models.Model):
last_name = models.CharField(max_length=100)
first_name = models.CharField(max_length=100)
specialities = models.ManyToManyField(Speciality, blank=True)
profile_role = models.OneToOneField(ProfileRole, on_delete=models.CASCADE, related_name='teacher_profile', null=True, blank=True)
updated_date = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.last_name} {self.first_name}"
class SchoolClass(models.Model):
PLANNING_TYPE_CHOICES = [
(1, 'Annuel'),
(2, 'Semestriel'),
(3, 'Trimestriel')
]
atmosphere_name = models.CharField(max_length=255, null=True, blank=True)
age_range = models.JSONField(blank=True)
number_of_students = models.PositiveIntegerField(blank=True)
teaching_language = models.CharField(max_length=255, blank=True)
school_year = models.CharField(max_length=9, blank=True)
updated_date = models.DateTimeField(auto_now=True)
teachers = models.ManyToManyField(Teacher, blank=True)
levels = ArrayField(models.IntegerField(choices=LEVEL_CHOICES), default=list)
type = models.IntegerField(choices=PLANNING_TYPE_CHOICES, default=1)
time_range = models.JSONField(default=list)
opening_days = ArrayField(models.IntegerField(), default=list)
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='school_classes')
def __str__(self):
return self.atmosphere_name
class Planning(models.Model):
level = models.IntegerField(choices=LEVEL_CHOICES, null=True, blank=True)
school_class = models.ForeignKey(SchoolClass, null=True, blank=True, related_name='plannings', on_delete=models.CASCADE)
schedule = JSONField(default=dict)
def __str__(self):
return f'Planning for {self.level} of {self.school_class.atmosphere_name}'
class PaymentPlanType(models.IntegerChoices):
ONE_TIME = 1, '1 fois'
THREE_TIMES = 3, '3 fois'
TEN_TIMES = 10, '10 fois'
TWELVE_TIMES = 12, '12 fois'
class DiscountType(models.IntegerChoices):
CURRENCY = 0, 'Currency'
PERCENT = 1, 'Percent'
class FeeType(models.IntegerChoices):
REGISTRATION_FEE = 0, 'Registration Fee'
TUITION_FEE = 1, 'Tuition Fee'
class PaymentModeType(models.IntegerChoices):
SEPA = 1, 'Prélèvement SEPA'
TRANSFER = 2, 'Virement'
CHECK = 3, 'Chèque'
CASH = 4, 'Espèce'
class Discount(models.Model):
name = models.CharField(max_length=255, null=True, blank=True)
amount = models.DecimalField(max_digits=10, decimal_places=2, default=0)
description = models.TextField(blank=True)
discount_type = models.IntegerField(choices=DiscountType.choices, default=DiscountType.CURRENCY)
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
updated_at = models.DateTimeField(auto_now=True)
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='discounts')
def __str__(self):
return self.name
class Fee(models.Model):
name = models.CharField(max_length=255, null=True, blank=True)
base_amount = models.DecimalField(max_digits=10, decimal_places=2, default=0)
description = models.TextField(blank=True)
is_active = models.BooleanField(default=True)
updated_at = models.DateTimeField(auto_now=True)
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='fees')
def __str__(self):
return self.name
class PaymentPlan(models.Model):
frequency = models.IntegerField(choices=PaymentPlanType.choices, default=PaymentPlanType.ONE_TIME)
due_dates = ArrayField(models.DateField(), blank=True)
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
is_active = models.BooleanField(default=False)
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='payment_plans')
def __str__(self):
return f"{self.get_frequency_display()} - {self.get_type_display()}"
class PaymentMode(models.Model):
mode = models.IntegerField(choices=PaymentModeType.choices, default=PaymentModeType.SEPA)
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
is_active = models.BooleanField(default=False)
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='payment_modes')
def __str__(self):
return f"{self.get_mode_display()} - {self.get_type_display()}"
class Domain(models.Model):
name = models.CharField(max_length=255)
cycle = models.IntegerField(choices=[(1, 'Cycle 1'), (2, 'Cycle 2'), (3, 'Cycle 3'), (4, 'Cycle 4')])
def __str__(self):
return f"{self.name} (Cycle {self.cycle})"
class Category(models.Model):
name = models.CharField(max_length=255)
domain = models.ForeignKey(Domain, on_delete=models.CASCADE, related_name='categories')
def __str__(self):
return self.name
class Competency(models.Model):
name = models.TextField()
end_of_cycle = models.BooleanField(default=False, null=True, blank=True)
level = models.CharField(max_length=50, null=True, blank=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='competencies')
establishments = models.ManyToManyField(
Establishment,
through='EstablishmentCompetency',
related_name='competencies',
blank=True
)
def __str__(self):
return self.name
class EstablishmentCompetency(models.Model):
"""
Relation entre un établissement et une compétence.
Permet de définir quelles compétences sont sélectionnées par un établissement.
"""
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE)
competency = models.ForeignKey(Competency, on_delete=models.CASCADE)
is_selected = models.BooleanField(default=False)
class Meta:
unique_together = ('establishment', 'competency')
def __str__(self):
return f"{self.establishment.name} - {self.competency.name}"
class StudentCompetency(models.Model):
"""
Relation entre un élève et une compétence.
Permet d'attribuer une note à un élève pour une compétence.
"""
student = models.ForeignKey('Subscriptions.Student', on_delete=models.CASCADE, related_name='competency_scores')
competency = models.ForeignKey(Competency, on_delete=models.CASCADE, related_name='student_scores')
score = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) # Note attribuée
comment = models.TextField(blank=True, null=True) # Commentaire facultatif
class Meta:
unique_together = ('student', 'competency')
def __str__(self):
return f"{self.student} - {self.competency.name} - Score: {self.score}"