feat: Utilisation de l'établissement en variable de session / gestion de

la page des inscriptions en fonction de l'établissement / mise à jour du
mock_data à l'init
This commit is contained in:
N3WT DE COMPET
2025-03-06 20:08:16 +01:00
parent c03fa0ba42
commit f2ad1de5a4
20 changed files with 464 additions and 372 deletions

View File

@ -20,6 +20,7 @@ class Profile(AbstractUser):
datePeremption = models.CharField(max_length=200, default="", blank=True) datePeremption = models.CharField(max_length=200, default="", blank=True)
droit = models.IntegerField(choices=Droits, default=Droits.PROFIL_UNDEFINED) droit = models.IntegerField(choices=Droits, default=Droits.PROFIL_UNDEFINED)
estConnecte = models.BooleanField(default=False, blank=True) estConnecte = models.BooleanField(default=False, blank=True)
establishment = models.ForeignKey('School.Establishment', on_delete=models.PROTECT, related_name='profile', null=True, blank=True)
def __str__(self): def __str__(self):
return self.email + " - " + str(self.droit) return self.email + " - " + str(self.droit)

View File

@ -8,7 +8,7 @@ class ProfileSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Profile model = Profile
fields = ['id', 'password', 'email', 'code', 'datePeremption', 'estConnecte', 'droit', 'username', 'is_active'] fields = ['id', 'password', 'email', 'code', 'datePeremption', 'estConnecte', 'droit', 'username', 'is_active', 'establishment']
extra_kwargs = {'password': {'write_only': True}} extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data): def create(self, validated_data):
@ -16,7 +16,8 @@ class ProfileSerializer(serializers.ModelSerializer):
username=validated_data['username'], username=validated_data['username'],
email=validated_data['email'], email=validated_data['email'],
is_active=validated_data['is_active'], is_active=validated_data['is_active'],
droit=validated_data['droit'] droit=validated_data['droit'],
establishment=validated_data.get('establishment')
) )
user.set_password(validated_data['password']) user.set_password(validated_data['password'])
user.save() user.save()

View File

@ -204,6 +204,7 @@ class LoginView(APIView):
'user_id': user.id, 'user_id': user.id,
'email': user.email, 'email': user.email,
'droit': user.droit, 'droit': user.droit,
'establishment': user.establishment.id,
'type': 'access', 'type': 'access',
'exp': datetime.utcnow() + settings.SIMPLE_JWT['ACCESS_TOKEN_LIFETIME'], 'exp': datetime.utcnow() + settings.SIMPLE_JWT['ACCESS_TOKEN_LIFETIME'],
'iat': datetime.utcnow(), 'iat': datetime.utcnow(),
@ -300,6 +301,7 @@ class RefreshJWTView(APIView):
'user_id': user.id, 'user_id': user.id,
'email': user.email, 'email': user.email,
'droit': user.droit, 'droit': user.droit,
'establishment': user.establishment.id,
'type': 'access', 'type': 'access',
'exp': datetime.utcnow() + settings.SIMPLE_JWT['ACCESS_TOKEN_LIFETIME'], 'exp': datetime.utcnow() + settings.SIMPLE_JWT['ACCESS_TOKEN_LIFETIME'],
'iat': datetime.utcnow(), 'iat': datetime.utcnow(),

View File

@ -2,7 +2,8 @@ import logging
from django.db.models import Q from django.db.models import Q
from django.http import JsonResponse from django.http import JsonResponse
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from Subscriptions.models import RegistrationForm, Profile, Student from Subscriptions.models import RegistrationForm, Student
from Auth.models import Profile
logger = logging.getLogger('N3wtSchool') logger = logging.getLogger('N3wtSchool')

View File

@ -31,12 +31,17 @@ from django.core.exceptions import SuspiciousFileOperation
import os import os
from django.conf import settings from django.conf import settings
from faker import Faker from faker import Faker
import random
import json
# Définir le chemin vers le dossier mock_datas
MOCK_DATAS_PATH = os.path.join(settings.BASE_DIR, 'School', 'management', 'mock_datas')
class Command(BaseCommand): class Command(BaseCommand):
help = 'Initialise toutes les données mock' help = 'Initialise toutes les données mock'
def handle(self, *args, **kwargs): def handle(self, *args, **kwargs):
self.create_or_update_establishment() self.create_or_update_establishments()
self.create_or_update_fees() self.create_or_update_fees()
self.create_or_update_discounts() self.create_or_update_discounts()
self.create_or_update_payment_modes() self.create_or_update_payment_modes()
@ -47,71 +52,32 @@ class Command(BaseCommand):
self.create_or_update_registration_file_group() self.create_or_update_registration_file_group()
self.create_register_form() self.create_register_form()
def create_or_update_establishment(self): def load_data(self, filename):
establishment_data = { with open(os.path.join(MOCK_DATAS_PATH, filename), 'r') as file:
"name": "N3WT", return json.load(file)
"address": "Société n3wt-innov 69 Chez LANA",
"total_capacity": 69,
"establishment_type": [StructureType.MATERNELLE, StructureType.PRIMAIRE],
"licence_code": ""
}
def create_or_update_establishments(self):
establishments_data = self.load_data('establishments.json')
self.establishments = []
for establishment_data in establishments_data:
establishment, created = Establishment.objects.update_or_create( establishment, created = Establishment.objects.update_or_create(
name=establishment_data["name"], name=establishment_data["name"],
defaults=establishment_data defaults=establishment_data
) )
self.establishments.append(establishment)
if created: if created:
self.stdout.write(self.style.SUCCESS('Establishment created successfully')) self.stdout.write(self.style.SUCCESS(f'Establishment {establishment.name} created successfully'))
else: else:
self.stdout.write(self.style.SUCCESS('Establishment updated successfully')) self.stdout.write(self.style.SUCCESS(f'Establishment {establishment.name} updated successfully'))
def create_or_update_fees(self): def create_or_update_fees(self):
establishment = Establishment.objects.get(name="N3WT") fees_data = self.load_data('fees.json')
fees_data = [
{
"name": "Frais d'inscription",
"base_amount": "150.00",
"description": "Montant de base",
"is_active": True,
"type": FeeType.REGISTRATION_FEE,
"establishment": establishment
},
{
"name": "Matériel",
"base_amount": "85.00",
"description": "Livres / jouets",
"is_active": True,
"type": FeeType.REGISTRATION_FEE,
"establishment": establishment
},
{
"name": "Sorties périscolaires",
"base_amount": "120.00",
"description": "Sorties",
"is_active": True,
"type": FeeType.REGISTRATION_FEE,
"establishment": establishment
},
{
"name": "Les colibris",
"base_amount": "4500.00",
"description": "TPS / PS / MS / GS",
"is_active": True,
"type": FeeType.TUITION_FEE,
"establishment": establishment
},
{
"name": "Les butterflies",
"base_amount": "5000.00",
"description": "CP / CE1 / CE2 / CM1 / CM2",
"is_active": True,
"type": FeeType.TUITION_FEE,
"establishment": establishment
}
]
for fee_data in fees_data: for fee_data in fees_data:
establishment = random.choice(self.establishments)
fee_data["name"] = f"{fee_data['name']} - {establishment.name}"
fee_data["establishment"] = establishment
Fee.objects.update_or_create( Fee.objects.update_or_create(
name=fee_data["name"], name=fee_data["name"],
type=fee_data["type"], type=fee_data["type"],
@ -121,27 +87,12 @@ class Command(BaseCommand):
self.stdout.write(self.style.SUCCESS('Fees initialized or updated successfully')) self.stdout.write(self.style.SUCCESS('Fees initialized or updated successfully'))
def create_or_update_discounts(self): def create_or_update_discounts(self):
establishment = Establishment.objects.get(name="N3WT") discounts_data = self.load_data('discounts.json')
discounts_data = [
{
"name": "Parrainage",
"amount": "10.00",
"description": "Réduction pour parrainage",
"discount_type": DiscountType.PERCENT,
"type": FeeType.TUITION_FEE,
"establishment": establishment
},
{
"name": "Réinscription",
"amount": "100.00",
"description": "Réduction pour Réinscription",
"discount_type": DiscountType.PERCENT,
"type": FeeType.REGISTRATION_FEE,
"establishment": establishment
}
]
for discount_data in discounts_data: for discount_data in discounts_data:
establishment = random.choice(self.establishments)
discount_data["name"] = f"{discount_data['name']} - {establishment.name}"
discount_data["establishment"] = establishment
Discount.objects.update_or_create( Discount.objects.update_or_create(
name=discount_data["name"], name=discount_data["name"],
type=discount_data["type"], type=discount_data["type"],
@ -152,104 +103,44 @@ class Command(BaseCommand):
self.stdout.write(self.style.SUCCESS('Discounts initialized or updated successfully')) self.stdout.write(self.style.SUCCESS('Discounts initialized or updated successfully'))
def create_or_update_payment_modes(self): def create_or_update_payment_modes(self):
establishment = Establishment.objects.get(name="N3WT") payment_modes_data = self.load_data('payment_modes.json')
for fee_type in FeeType.choices:
fee_type_value = fee_type[0]
for mode in PaymentModeType.choices:
mode_value = mode[0]
for payment_mode_data in payment_modes_data:
establishment = random.choice(self.establishments)
payment_mode_data["establishment"] = establishment
PaymentMode.objects.update_or_create( PaymentMode.objects.update_or_create(
mode=mode_value, mode=payment_mode_data["mode"],
type=fee_type_value, type=payment_mode_data["type"],
defaults={ defaults=payment_mode_data
'is_active': False,
'establishment': establishment
}
) )
self.stdout.write(self.style.SUCCESS('Payment Modes initialized or updated successfully')) self.stdout.write(self.style.SUCCESS('Payment Modes initialized or updated successfully'))
def create_or_update_payment_plans(self): def create_or_update_payment_plans(self):
payment_plans_data = self.load_data('payment_plans.json')
current_date = timezone.now().date() current_date = timezone.now().date()
establishment = Establishment.objects.get(name="N3WT")
for fee_type in FeeType.choices: for payment_plan_data in payment_plans_data:
fee_type_value = fee_type[0] establishment = random.choice(self.establishments)
payment_plan_data["establishment"] = establishment
payment_plan_data["due_dates"] = [current_date + relativedelta(months=1)]
if payment_plan_data["frequency"] == PaymentPlanType.THREE_TIMES:
payment_plan_data["due_dates"] = [current_date + relativedelta(months=1+4*i) for i in range(3)]
elif payment_plan_data["frequency"] == PaymentPlanType.TEN_TIMES:
payment_plan_data["due_dates"] = [current_date + relativedelta(months=1+i) for i in range(10)]
elif payment_plan_data["frequency"] == PaymentPlanType.TWELVE_TIMES:
payment_plan_data["due_dates"] = [current_date + relativedelta(months=1+i) for i in range(12)]
# 1 fois - échéance à 1 mois à partir de la date actuelle
PaymentPlan.objects.update_or_create( PaymentPlan.objects.update_or_create(
frequency=PaymentPlanType.ONE_TIME, frequency=payment_plan_data["frequency"],
type=fee_type_value, type=payment_plan_data["type"],
defaults={ defaults=payment_plan_data
'due_dates': [current_date + relativedelta(months=1)],
'is_active': True,
'establishment': establishment
}
)
# 3 fois - échéances espacées de 4 mois
PaymentPlan.objects.update_or_create(
frequency=PaymentPlanType.THREE_TIMES,
type=fee_type_value,
defaults={
'due_dates': [current_date + relativedelta(months=1+4*i) for i in range(3)],
'is_active': False,
'establishment': establishment
}
)
# 10 fois - échéances espacées d'un mois
PaymentPlan.objects.update_or_create(
frequency=PaymentPlanType.TEN_TIMES,
type=fee_type_value,
defaults={
'due_dates': [current_date + relativedelta(months=1+i) for i in range(10)],
'is_active': False,
'establishment': establishment
}
)
# 12 fois - échéances espacées d'un mois
PaymentPlan.objects.update_or_create(
frequency=PaymentPlanType.TWELVE_TIMES,
type=fee_type_value,
defaults={
'due_dates': [current_date + relativedelta(months=1+i) for i in range(12)],
'is_active': False,
'establishment': establishment
}
) )
self.stdout.write(self.style.SUCCESS('Payment Plans initialized or updated successfully')) self.stdout.write(self.style.SUCCESS('Payment Plans initialized or updated successfully'))
def create_or_update_specialities(self): def create_or_update_specialities(self):
specialities_data = [ specialities_data = self.load_data('specialities.json')
{
"name": "GROUPE",
"color_code": "#FF0000"
},
{
"name": "MATHS",
"color_code": "#0a98f0"
},
{
"name": "ANGLAIS",
"color_code": "#f708d7"
},
{
"name": "FRANCAIS",
"color_code": "#04f108"
},
{
"name": "HISTOIRE",
"color_code": "#ffb005"
},
{
"name": "SPORT",
"color_code": "#bbb9b9"
}
]
for speciality_data in specialities_data: for speciality_data in specialities_data:
Speciality.objects.update_or_create( Speciality.objects.update_or_create(
@ -259,42 +150,15 @@ class Command(BaseCommand):
self.stdout.write(self.style.SUCCESS('Specialities initialized or updated successfully')) self.stdout.write(self.style.SUCCESS('Specialities initialized or updated successfully'))
def create_or_update_teachers(self): def create_or_update_teachers(self):
teachers_data = [ teachers_data = self.load_data('teachers.json')
{
"last_name": "DUMBLEDORE",
"first_name": "Albus",
"email": "albus.dumbledore@gmail.com",
"specialities": ["GROUPE"],
"droit": 1
},
{
"last_name": "ROGUE",
"first_name": "Severus",
"email": "severus.rogue@gmail.com",
"specialities": ["ANGLAIS"],
"droit": 0
},
{
"last_name": "MC GONAGALL",
"first_name": "Minerva",
"email": "minerva.mcgonagall@gmail.com",
"specialities": ["MATHS", "HISTOIRE"],
"droit": 0
},
{
"last_name": "CHOURAVE",
"first_name": "Pomona",
"email": "pomona.chourave@gmail.com",
"specialities": ["MATHS", "FRANCAIS", "SPORT"],
"droit": 0
}
]
for teacher_data in teachers_data: for teacher_data in teachers_data:
specialities = teacher_data.pop("specialities") specialities = teacher_data.pop("specialities")
email = teacher_data["email"] email = teacher_data["email"]
droit = teacher_data.pop("droit") droit = teacher_data.pop("droit")
establishment = random.choice(self.establishments)
# Create or update the user profile # Create or update the user profile
user, created = Profile.objects.update_or_create( user, created = Profile.objects.update_or_create(
email=email, email=email,
@ -303,7 +167,8 @@ class Command(BaseCommand):
"email": email, "email": email,
"is_active": True, "is_active": True,
"password": "Provisoire01!", "password": "Provisoire01!",
"droit": droit "droit": droit,
"establishment": establishment
} }
) )
if created: if created:
@ -321,51 +186,13 @@ class Command(BaseCommand):
self.stdout.write(self.style.SUCCESS('Teachers initialized or updated successfully')) self.stdout.write(self.style.SUCCESS('Teachers initialized or updated successfully'))
def create_or_update_school_classes(self): def create_or_update_school_classes(self):
establishment = Establishment.objects.get(name="N3WT") school_classes_data = self.load_data('school_classes.json')
school_classes_data = [
{
"atmosphere_name": "Classe A",
"age_range": "3-6",
"number_of_students": 14,
"teaching_language": "",
"school_year": "2024-2025",
"levels": [2, 3, 4],
"type": 1,
"time_range": ["08:30", "17:30"],
"opening_days": [1, 2, 4, 5],
"teachers": [2], # ID of Severus Rogue
"establishment": establishment
},
{
"atmosphere_name": "Classe B",
"age_range": "2-3",
"number_of_students": 5,
"teaching_language": "",
"school_year": "2024-2025",
"levels": [1],
"type": 1,
"time_range": ["08:30", "17:30"],
"opening_days": [1, 2, 4, 5],
"teachers": [3], # ID of Minerva McGonagall
"establishment": establishment
},
{
"atmosphere_name": "Classe C",
"age_range": "6-12",
"number_of_students": 21,
"teaching_language": "",
"school_year": "2024-2025",
"levels": [5, 6, 7, 8, 9],
"type": 1,
"time_range": ["08:30", "17:30"],
"opening_days": [1, 2, 4, 5],
"teachers": [4], # ID of Pomona Chourave
"establishment": establishment
}
]
for class_data in school_classes_data: for index, class_data in enumerate(school_classes_data, start=1):
teachers_ids = class_data.pop("teachers") teachers_ids = class_data.pop("teachers")
establishment = random.choice(self.establishments)
class_data["atmosphere_name"] = f"Classe {index} - {establishment.name}"
class_data["establishment"] = establishment
school_class, created = SchoolClass.objects.update_or_create( school_class, created = SchoolClass.objects.update_or_create(
atmosphere_name=class_data["atmosphere_name"], atmosphere_name=class_data["atmosphere_name"],
school_year=class_data["school_year"], school_year=class_data["school_year"],
@ -377,33 +204,29 @@ class Command(BaseCommand):
self.stdout.write(self.style.SUCCESS('SchoolClasses initialized or updated successfully')) self.stdout.write(self.style.SUCCESS('SchoolClasses initialized or updated successfully'))
def create_or_update_registration_file_group(self): def create_or_update_registration_file_group(self):
group_data_1 = { for establishment in self.establishments:
"name": "LMDE", group_data = {
"description": "Fichiers d'inscription de l'école LMDE" "name": f"Fichiers d'inscription - {establishment.name}",
"description": f"Fichiers d'inscription de l'école {establishment.name}"
} }
self.registration_file_group_1, created = RegistrationFileGroup.objects.get_or_create(name=group_data_1["name"], defaults=group_data_1) RegistrationFileGroup.objects.update_or_create(name=group_data["name"], defaults=group_data)
self.stdout.write(self.style.SUCCESS('RegistrationFileGroup 1 initialized or updated successfully')) self.stdout.write(self.style.SUCCESS(f'RegistrationFileGroup for {establishment.name} initialized or updated successfully'))
group_data_2 = {
"name": "LMDE 2",
"description": "Fichiers d'inscription de l'école LMDE 2"
}
self.registration_file_group_2, created = RegistrationFileGroup.objects.get_or_create(name=group_data_2["name"], defaults=group_data_2)
self.stdout.write(self.style.SUCCESS('RegistrationFileGroup 2 initialized or updated successfully'))
def create_register_form(self): def create_register_form(self):
fake = Faker('fr_FR') # Utiliser le locale français pour Faker fake = Faker('fr_FR') # Utiliser le locale français pour Faker
for _ in range(50): for _ in range(50):
establishment = random.choice(self.establishments)
# Générer des données fictives pour le profil # Générer des données fictives pour le profil
profile_data = { profile_data = {
"email": fake.email(), "email": fake.email(),
"droit": 2, "droit": 2,
"username": fake.user_name(), "username": fake.user_name(),
"is_active": True, "is_active": True,
"password": "Provisoire01!" "password": "Provisoire01!",
"establishment": establishment
} }
user, created = Profile.objects.update_or_create( user, created = Profile.objects.update_or_create(
@ -412,7 +235,8 @@ class Command(BaseCommand):
"username": profile_data["username"], "username": profile_data["username"],
"email": profile_data["email"], "email": profile_data["email"],
"is_active": profile_data["is_active"], "is_active": profile_data["is_active"],
"droit": profile_data["droit"] "droit": profile_data["droit"],
"establishment": profile_data["establishment"]
} }
) )
if created: if created:
@ -427,7 +251,7 @@ class Command(BaseCommand):
# Générer des données fictives pour l'étudiant # Générer des données fictives pour l'étudiant
student_data = { student_data = {
"last_name": fake.last_name(), "last_name": f"{fake.last_name()} - {establishment.name}",
"first_name": fake.first_name(), "first_name": fake.first_name(),
"address": fake.address(), "address": fake.address(),
"birth_date": fake.date_of_birth(), "birth_date": fake.date_of_birth(),
@ -457,8 +281,8 @@ class Command(BaseCommand):
# Créer les données du formulaire d'inscription # Créer les données du formulaire d'inscription
register_form_data = { register_form_data = {
"student": student, "student": student,
"fileGroup": self.registration_file_group_1, "fileGroup": RegistrationFileGroup.objects.get(name=f"Fichiers d'inscription - {establishment.name}"),
"establishment": Establishment.objects.get(id=1), "establishment": establishment,
"status": fake.random_int(min=1, max=3) "status": fake.random_int(min=1, max=3)
} }
@ -467,7 +291,7 @@ class Command(BaseCommand):
register_form.fees.set(fees) register_form.fees.set(fees)
register_form.discounts.set(discounts) register_form.discounts.set(discounts)
if not created: if not created:
register_form.fileGroup = self.registration_file_group_1 register_form.fileGroup = RegistrationFileGroup.objects.get(name=f"Fichiers d'inscription - {establishment.name}")
register_form.save() register_form.save()
self.stdout.write(self.style.SUCCESS('50 RegistrationForms initialized or updated successfully')) self.stdout.write(self.style.SUCCESS('50 RegistrationForms initialized or updated successfully'))

View File

@ -0,0 +1,16 @@
[
{
"name": "Parrainage",
"amount": "10.00",
"description": "Réduction pour parrainage",
"discount_type": 1,
"type": 1
},
{
"name": "Réinscription",
"amount": "100.00",
"description": "Réduction pour Réinscription",
"discount_type": 1,
"type": 0
}
]

View File

@ -0,0 +1,23 @@
[
{
"name": "Ecole A",
"address": "Adresse de l'Ecole A",
"total_capacity": 69,
"establishment_type": [1, 2],
"licence_code": ""
},
{
"name": "Ecole B",
"address": "Adresse de l'Ecole B",
"total_capacity": 100,
"establishment_type": [2, 3],
"licence_code": ""
},
{
"name": "Ecole C",
"address": "Adresse de l'Ecole C",
"total_capacity": 50,
"establishment_type": [1],
"licence_code": ""
}
]

View File

@ -0,0 +1,37 @@
[
{
"name": "Frais d'inscription",
"base_amount": "150.00",
"description": "Montant de base",
"is_active": true,
"type": 0
},
{
"name": "Matériel",
"base_amount": "85.00",
"description": "Livres / jouets",
"is_active": true,
"type": 0
},
{
"name": "Sorties périscolaires",
"base_amount": "120.00",
"description": "Sorties",
"is_active": true,
"type": 0
},
{
"name": "Les colibris",
"base_amount": "4500.00",
"description": "TPS / PS / MS / GS",
"is_active": true,
"type": 1
},
{
"name": "Les butterflies",
"base_amount": "5000.00",
"description": "CP / CE1 / CE2 / CM1 / CM2",
"is_active": true,
"type": 1
}
]

View File

@ -0,0 +1,12 @@
[
{
"mode": 4,
"type": 0,
"is_active": true
},
{
"mode": 2,
"type": 1,
"is_active": true
}
]

View File

@ -0,0 +1,22 @@
[
{
"frequency": 1,
"type": 0,
"is_active": true
},
{
"frequency": 3,
"type": 1,
"is_active": true
},
{
"frequency": 10,
"type": 1,
"is_active": true
},
{
"frequency": 12,
"type": 1,
"is_active": true
}
]

View File

@ -0,0 +1,57 @@
[
{
"age_range": "3-6",
"number_of_students": 14,
"teaching_language": "",
"school_year": "2024-2025",
"levels": [2, 3, 4],
"type": 1,
"time_range": ["08:30", "17:30"],
"opening_days": [1, 2, 4, 5],
"teachers": [2]
},
{
"age_range": "2-3",
"number_of_students": 5,
"teaching_language": "",
"school_year": "2024-2025",
"levels": [1],
"type": 1,
"time_range": ["08:30", "17:30"],
"opening_days": [1, 2, 4, 5],
"teachers": [3]
},
{
"age_range": "6-12",
"number_of_students": 21,
"teaching_language": "",
"school_year": "2024-2025",
"levels": [5, 6, 7, 8, 9],
"type": 1,
"time_range": ["08:30", "17:30"],
"opening_days": [1, 2, 4, 5],
"teachers": [4]
},
{
"age_range": "4-6",
"number_of_students": 18,
"teaching_language": "",
"school_year": "2024-2025",
"levels": [4, 5],
"type": 1,
"time_range": ["08:30", "17:30"],
"opening_days": [1, 2, 4, 5],
"teachers": [1]
},
{
"age_range": "7-9",
"number_of_students": 20,
"teaching_language": "",
"school_year": "2024-2025",
"levels": [6, 7],
"type": 1,
"time_range": ["08:30", "17:30"],
"opening_days": [1, 2, 4, 5],
"teachers": [2]
}
]

View File

@ -0,0 +1,26 @@
[
{
"name": "GROUPE",
"color_code": "#FF0000"
},
{
"name": "MATHS",
"color_code": "#0a98f0"
},
{
"name": "ANGLAIS",
"color_code": "#f708d7"
},
{
"name": "FRANCAIS",
"color_code": "#04f108"
},
{
"name": "HISTOIRE",
"color_code": "#ffb005"
},
{
"name": "SPORT",
"color_code": "#bbb9b9"
}
]

View File

@ -0,0 +1,30 @@
[
{
"last_name": "DUMBLEDORE",
"first_name": "Albus",
"email": "albus.dumbledore@gmail.com",
"specialities": ["GROUPE"],
"droit": 1
},
{
"last_name": "ROGUE",
"first_name": "Severus",
"email": "severus.rogue@gmail.com",
"specialities": ["ANGLAIS"],
"droit": 1
},
{
"last_name": "MC GONAGALL",
"first_name": "Minerva",
"email": "minerva.mcgonagall@gmail.com",
"specialities": ["MATHS", "HISTOIRE"],
"droit": 1
},
{
"last_name": "CHOURAVE",
"first_name": "Pomona",
"email": "pomona.chourave@gmail.com",
"specialities": ["MATHS", "FRANCAIS", "SPORT"],
"droit": 1
}
]

View File

@ -3,8 +3,7 @@ from django.utils.timezone import now
from django.conf import settings from django.conf import settings
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from Auth.models import Profile from School.models import SchoolClass, Fee, Discount
from School.models import SchoolClass, Fee, Discount, Establishment
from datetime import datetime from datetime import datetime
@ -29,7 +28,7 @@ class Guardian(models.Model):
email = 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) phone = models.CharField(max_length=200, default="", blank=True)
profession = 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) associated_profile = models.ForeignKey('Auth.Profile', on_delete=models.CASCADE)
def __str__(self): def __str__(self):
return self.last_name + "_" + self.first_name return self.last_name + "_" + self.first_name
@ -80,7 +79,7 @@ class Student(models.Model):
payment_method = models.IntegerField(choices=PaymentMethod, default=PaymentMethod.NONE, blank=True) payment_method = models.IntegerField(choices=PaymentMethod, default=PaymentMethod.NONE, blank=True)
# Many-to-Many Relationship # Many-to-Many Relationship
profiles = models.ManyToManyField(Profile, blank=True) profiles = models.ManyToManyField('Auth.Profile', blank=True)
# Many-to-Many Relationship # Many-to-Many Relationship
guardians = models.ManyToManyField(Guardian, blank=True) guardians = models.ManyToManyField(Guardian, blank=True)
@ -215,7 +214,7 @@ class RegistrationForm(models.Model):
null=True, null=True,
blank=True) blank=True)
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='register_forms') establishment = models.ForeignKey('School.Establishment', on_delete=models.CASCADE, related_name='register_forms')
def __str__(self): def __str__(self):
return "RF_" + self.student.last_name + "_" + self.student.first_name return "RF_" + self.student.last_name + "_" + self.student.first_name

View File

@ -39,6 +39,7 @@ class RegisterFormView(APIView):
openapi.Parameter('filter', openapi.IN_QUERY, description="filtre", type=openapi.TYPE_STRING, enum=['pending', 'archived', 'subscribed'], required=True), openapi.Parameter('filter', openapi.IN_QUERY, description="filtre", type=openapi.TYPE_STRING, enum=['pending', 'archived', 'subscribed'], required=True),
openapi.Parameter('search', openapi.IN_QUERY, description="search", type=openapi.TYPE_STRING, required=False), openapi.Parameter('search', openapi.IN_QUERY, description="search", type=openapi.TYPE_STRING, required=False),
openapi.Parameter('page_size', openapi.IN_QUERY, description="limite de page lors de la pagination", type=openapi.TYPE_INTEGER, required=False), openapi.Parameter('page_size', openapi.IN_QUERY, description="limite de page lors de la pagination", type=openapi.TYPE_INTEGER, required=False),
openapi.Parameter('establishment_id', openapi.IN_QUERY, description="ID de l'établissement", type=openapi.TYPE_INTEGER, required=True),
], ],
responses={200: RegistrationFormSerializer(many=True)}, responses={200: RegistrationFormSerializer(many=True)},
operation_description="Récupère les dossier d'inscriptions en fonction du filtre passé.", operation_description="Récupère les dossier d'inscriptions en fonction du filtre passé.",
@ -78,6 +79,7 @@ class RegisterFormView(APIView):
filter = request.GET.get('filter', '').strip() filter = request.GET.get('filter', '').strip()
search = request.GET.get('search', '').strip() search = request.GET.get('search', '').strip()
page_size = request.GET.get('page_size', None) page_size = request.GET.get('page_size', None)
establishment_id = request.GET.get('establishment_id', None)
# Gestion du page_size # Gestion du page_size
if page_size is not None: if page_size is not None:
@ -88,7 +90,7 @@ class RegisterFormView(APIView):
# Définir le cache_key en fonction du filtre # Définir le cache_key en fonction du filtre
page_number = request.GET.get('page', 1) page_number = request.GET.get('page', 1)
cache_key = f'N3WT_ficheInscriptions_{filter}_page_{page_number}_search_{search if filter == "pending" else ""}' cache_key = f'N3WT_ficheInscriptions_{establishment_id}_{filter}_page_{page_number}_search_{search if filter == "pending" else ""}'
cached_page = cache.get(cache_key) cached_page = cache.get(cache_key)
if cached_page: if cached_page:
return JsonResponse(cached_page, safe=False) return JsonResponse(cached_page, safe=False)
@ -105,6 +107,10 @@ class RegisterFormView(APIView):
else: else:
registerForms_List = None registerForms_List = None
if registerForms_List:
print(f'filtrate sur lestablishment : {establishment_id}')
registerForms_List = registerForms_List.filter(establishment=establishment_id)
if not registerForms_List: if not registerForms_List:
return JsonResponse({'error': 'aucune donnée trouvée', 'count': 0}, safe=False) return JsonResponse({'error': 'aucune donnée trouvée', 'count': 0}, safe=False)

View File

@ -46,11 +46,23 @@ class StudentListView(APIView):
operation_description="Retourne la liste de tous les élèves inscrits ou en cours d'inscription", operation_description="Retourne la liste de tous les élèves inscrits ou en cours d'inscription",
responses={ responses={
200: openapi.Response('Liste des élèves', StudentByRFCreationSerializer(many=True)) 200: openapi.Response('Liste des élèves', StudentByRFCreationSerializer(many=True))
} },
manual_parameters=[
openapi.Parameter(
'establishment_id', openapi.IN_QUERY,
description="ID de l'établissement",
type=openapi.TYPE_INTEGER,
required=True
)
]
) )
# Récupération de la liste des élèves inscrits ou en cours d'inscriptions # Récupération de la liste des élèves inscrits ou en cours d'inscriptions
def get(self, request): def get(self, request):
students = bdd.getAllObjects(_objectName=Student) establishment_id = request.GET.get('establishment_id', None)
if establishment_id is None:
return JsonResponse({'error': 'establishment_id est requis'}, safe=False, status=status.HTTP_400_BAD_REQUEST)
students = Student.objects.filter(registrationform__establishment_id=establishment_id)
students_serializer = StudentByRFCreationSerializer(students, many=True) students_serializer = StudentByRFCreationSerializer(students, many=True)
return JsonResponse(students_serializer.data, safe=False) return JsonResponse(students_serializer.data, safe=False)

View File

@ -15,6 +15,7 @@ import { MoreVertical, Send, Edit, Trash2, FileText, CheckCircle, Plus } from '
import Modal from '@/components/Modal'; import Modal from '@/components/Modal';
import InscriptionForm from '@/components/Inscription/InscriptionForm' import InscriptionForm from '@/components/Inscription/InscriptionForm'
import AffectationClasseForm from '@/components/AffectationClasseForm' import AffectationClasseForm from '@/components/AffectationClasseForm'
import { getSession } from 'next-auth/react';
import { import {
PENDING, PENDING,
@ -52,8 +53,6 @@ import { useCsrfToken } from '@/context/CsrfContext';
import { ESTABLISHMENT_ID } from '@/utils/Url'; import { ESTABLISHMENT_ID } from '@/utils/Url';
import logger from '@/utils/logger'; import logger from '@/utils/logger';
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
export default function Page({ params: { locale } }) { export default function Page({ params: { locale } }) {
const t = useTranslations('subscriptions'); const t = useTranslations('subscriptions');
const [registrationForms, setRegistrationForms] = useState([]); const [registrationForms, setRegistrationForms] = useState([]);
@ -88,6 +87,8 @@ export default function Page({ params: { locale } }) {
const [tuitionFees, setTuitionFees] = useState([]); const [tuitionFees, setTuitionFees] = useState([]);
const [groups, setGroups] = useState([]); const [groups, setGroups] = useState([]);
const [establishmentId, setEstablishmentId] = useState(null);
const csrfToken = useCsrfToken(); const csrfToken = useCsrfToken();
const openModal = () => { const openModal = () => {
@ -166,115 +167,131 @@ const registerFormArchivedDataHandler = (data) => {
} }
useEffect(() => { useEffect(() => {
const fetchInitialData = async () => { getSession()
try { .then(session => {
const [classesData, studentsData] = await Promise.all([ if (session && session.user) {
fetchClasses(), setEstablishmentId(session.user.establishment);
fetchStudents() }
]); })
.catch(err => {
logger.error('Error fetching session:', err);
});
}, []);
useEffect(() => {
if (establishmentId) {
const fetchInitialData = () => {
Promise.all([
fetchClasses(),
fetchStudents(establishmentId) // Utiliser l'ID de l'établissement ici
])
.then(([classesData, studentsData]) => {
setClasses(classesData); setClasses(classesData);
setEleves(studentsData); setEleves(studentsData);
logger.debug('Success - Classes:', classesData); logger.debug('Success - Classes:', classesData);
logger.debug('Success - Students:', studentsData); logger.debug('Success - Students:', studentsData);
} catch (error) { })
.catch(error => {
logger.error('Error fetching initial data:', error); logger.error('Error fetching initial data:', error);
} });
}; };
fetchInitialData(); fetchInitialData();
}, []); }
}, [establishmentId]);
useEffect(() => { useEffect(() => {
if (establishmentId) {
const fetchDataAndSetState = () => { const fetchDataAndSetState = () => {
setIsLoading(true); setIsLoading(true);
if (!useFakeData) { Promise.all([
fetchRegisterForms(PENDING, currentPage, itemsPerPage, searchTerm) fetchRegisterForms(establishmentId, PENDING, currentPage, itemsPerPage, searchTerm)
.then(registerFormPendingDataHandler) .then(registerFormPendingDataHandler)
.catch(requestErrorHandler) .catch(requestErrorHandler),
fetchRegisterForms(SUBSCRIBED) fetchRegisterForms(establishmentId, SUBSCRIBED)
.then(registerFormSubscribedDataHandler) .then(registerFormSubscribedDataHandler)
.catch(requestErrorHandler) .catch(requestErrorHandler),
fetchRegisterForms(ARCHIVED) fetchRegisterForms(establishmentId, ARCHIVED)
.then(registerFormArchivedDataHandler) .then(registerFormArchivedDataHandler)
.catch(requestErrorHandler) .catch(requestErrorHandler),
fetchRegistrationTemplateMaster() fetchRegistrationTemplateMaster()
.then((data)=> { .then(data => {
logger.debug(data); setTemplateMasters(data);
setTemplateMasters(data)
}) })
.catch((err)=>{ err = err.message; logger.debug(err);}) .catch(err => {
logger.debug(err.message);
}),
fetchRegistrationDiscounts() fetchRegistrationDiscounts()
.then(data => { .then(data => {
setRegistrationDiscounts(data); setRegistrationDiscounts(data);
}) })
.catch(requestErrorHandler) .catch(requestErrorHandler),
fetchTuitionDiscounts() fetchTuitionDiscounts()
.then(data => { .then(data => {
setTuitionDiscounts(data); setTuitionDiscounts(data);
}) })
.catch(requestErrorHandler) .catch(requestErrorHandler),
fetchRegistrationFees() fetchRegistrationFees()
.then(data => { .then(data => {
setRegistrationFees(data); setRegistrationFees(data);
}) })
.catch(requestErrorHandler) .catch(requestErrorHandler),
fetchTuitionFees() fetchTuitionFees()
.then(data => { .then(data => {
setTuitionFees(data); setTuitionFees(data);
}) })
.catch(requestErrorHandler); .catch(requestErrorHandler),
fetchRegistrationFileGroups() fetchRegistrationFileGroups()
.then(data => { .then(data => {
setGroups(data); setGroups(data);
}) })
.catch(error => logger.error('Error fetching file groups:', error)); .catch(error => {
} else { logger.error('Error fetching file groups:', error);
setTimeout(() => { })
setRegistrationFormsDataPending(mockFicheInscription); ])
}, 1000); .then(() => {
}
setIsLoading(false); setIsLoading(false);
setReloadFetch(false); setReloadFetch(false);
})
.catch(err => {
logger.error(err);
setIsLoading(false);
setReloadFetch(false);
});
}; };
fetchDataAndSetState(); fetchDataAndSetState();
}, [reloadFetch, currentPage]); }
}, [establishmentId, reloadFetch, currentPage, searchTerm]);
useEffect(() => { useEffect(() => {
if (establishmentId) {
const fetchDataAndSetState = () => { const fetchDataAndSetState = () => {
setIsLoading(true); setIsLoading(true);
if (!useFakeData) { fetchRegisterForms(establishmentId, PENDING, currentPage, itemsPerPage, searchTerm)
fetchRegisterForms(PENDING, currentPage, itemsPerPage, searchTerm)
.then(registerFormPendingDataHandler) .then(registerFormPendingDataHandler)
.catch(requestErrorHandler) .catch(requestErrorHandler)
fetchRegisterForms(SUBSCRIBED) fetchRegisterForms(establishmentId, SUBSCRIBED)
.then(registerFormSubscribedDataHandler) .then(registerFormSubscribedDataHandler)
.catch(requestErrorHandler) .catch(requestErrorHandler)
fetchRegisterForms(ARCHIVED) fetchRegisterForms(establishmentId, ARCHIVED)
.then(registerFormArchivedDataHandler) .then(registerFormArchivedDataHandler)
.catch(requestErrorHandler) .catch(requestErrorHandler)
fetchRegistrationTemplateMaster() fetchRegistrationTemplateMaster()
.then((data)=> {setTemplateMasters(data)}) .then((data)=> {setTemplateMasters(data)})
.catch((err)=>{ err = err.message; logger.debug(err);}); .catch((err)=>{ err = err.message; logger.debug(err);});
} else {
setTimeout(() => {
setRegistrationFormsDataPending(mockFicheInscription);
}, 1000);
}
setIsLoading(false); setIsLoading(false);
setReloadFetch(false); setReloadFetch(false);
}; }
const timeoutId = setTimeout(() => { const timeoutId = setTimeout(() => {
fetchDataAndSetState(); fetchDataAndSetState();
}, 500); // Debounce la recherche }, 500); // Debounce la recherche
return () => clearTimeout(timeoutId); return () => clearTimeout(timeoutId);
}
}, [searchTerm]); }, [searchTerm]);
/** /**

View File

@ -53,6 +53,11 @@ export default function Page() {
} }
const user = session.user; const user = session.user;
logger.debug('User Session:', user); logger.debug('User Session:', user);
if (user.establishment_id) {
localStorage.setItem('establishment_id', user.establishment_id);
}
if (user.droit === 0) { if (user.droit === 0) {
// Vue ECOLE // Vue ECOLE
} else if (user.droit === 1) { } else if (user.droit === 1) {

View File

@ -22,10 +22,10 @@ const requestResponseHandler = async (response) => {
throw error; throw error;
} }
export const fetchRegisterForms = (filter=PENDING, page='', pageSize='', search = '') => { export const fetchRegisterForms = (establishment, filter=PENDING, page='', pageSize='', search = '') => {
let url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}?filter=${filter}`; let url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}?filter=${filter}&establishment_id=${establishment}`;
if (page !== '' && pageSize !== '') { if (page !== '' && pageSize !== '') {
url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}?filter=${filter}&page=${page}&search=${search}`; url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}?filter=${filter}&establishment_id=${establishment}&page=${page}&search=${search}`;
} }
return fetch(url, { return fetch(url, {
headers: { headers: {
@ -99,8 +99,8 @@ export const archiveRegisterForm = (id) => {
}).then(requestResponseHandler) }).then(requestResponseHandler)
} }
export const fetchStudents = (id) => { export const fetchStudents = (id=null, establishment) => {
const url = (id)?`${BE_SUBSCRIPTION_STUDENTS_URL}/${id}`:`${BE_SUBSCRIPTION_STUDENTS_URL}`; const url = (id)?`${BE_SUBSCRIPTION_STUDENTS_URL}/${id}`:`${BE_SUBSCRIPTION_STUDENTS_URL}?establishment_id=${establishment}`;
const request = new Request( const request = new Request(
url, url,
{ {

View File

@ -88,7 +88,7 @@ const options = {
}, },
async session({ session, token }) { async session({ session, token }) {
if (token && token?.token) { if (token && token?.token) {
const {user_id, droit, email} = jwt_decode.decode(token.token); const {user_id, droit, email, establishment} = jwt_decode.decode(token.token);
session.user = { session.user = {
...session.user, ...session.user,
token: token.token, token: token.token,
@ -97,6 +97,7 @@ const options = {
session.user.user_id = user_id; session.user.user_id = user_id;
session.user.droit = droit; session.user.droit = droit;
session.user.email = email; session.user.email = email;
session.user.establishment = establishment;
} }
return session; return session;
} }