from django.core.management.base import BaseCommand from Subscriptions.models import ( RegistrationForm, RegistrationFileGroup ) from Auth.models import Profile, ProfileRole from School.models import ( FeeType, Speciality, Teacher, PaymentModeType, PaymentPlanType, DiscountType, Fee, Discount, ) from django.utils import timezone from dateutil.relativedelta import relativedelta import os from django.conf import settings from faker import Faker import random import json from School.serializers import ( FeeSerializer, DiscountSerializer, PaymentModeSerializer, PaymentPlanSerializer, SpecialitySerializer, TeacherSerializer, SchoolClassSerializer ) from Auth.serializers import ProfileSerializer, ProfileRoleSerializer from Establishment.serializers import EstablishmentSerializer from Subscriptions.serializers import StudentSerializer from Subscriptions.util import getCurrentSchoolYear, getNextSchoolYear # Import des fonctions nécessaires # 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): help = 'Initialise toutes les données mock' def handle(self, *args, **kwargs): self.init_establishments() self.init_profiles() self.init_fees() self.init_discounts() self.init_payment_modes() self.init_payment_plans() self.init_specialities() self.init_teachers() self.init_school_classes() self.init_file_group() self.init_register_form() def load_data(self, filename): with open(os.path.join(MOCK_DATAS_PATH, filename), 'r') as file: return json.load(file) def init_establishments(self): establishments_data = self.load_data('establishments.json') self.establishments = [] for establishment_data in establishments_data: serializer = EstablishmentSerializer(data=establishment_data) if serializer.is_valid(): establishment = serializer.save() self.establishments.append(establishment) self.stdout.write(self.style.SUCCESS(f'Establishment {establishment.name} created or updated successfully')) else: self.stdout.write(self.style.ERROR(f'Error in data for establishment: {serializer.errors}')) def init_profiles(self): fake = Faker() for _ in range(50): # Générer des données fictives pour le profil profile_data = { "username": fake.user_name(), "email": fake.email(), "password": "Provisoire01!", "code": "", "datePeremption": "" } # Créer le profil profile_serializer = ProfileSerializer(data=profile_data) if profile_serializer.is_valid(): profile = profile_serializer.save() profile.set_password(profile_data["password"]) profile.save() self.stdout.write(self.style.SUCCESS(f'Profile {profile.email} created successfully')) # Créer entre 1 et 3 ProfileRole pour chaque profil num_roles = random.randint(1, 3) created_roles = set() for _ in range(num_roles): establishment = random.choice(self.establishments) role_type = random.choice([ProfileRole.RoleType.PROFIL_ECOLE, ProfileRole.RoleType.PROFIL_ADMIN, ProfileRole.RoleType.PROFIL_PARENT]) # Vérifier si le rôle existe déjà pour cet établissement if (establishment.id, role_type) in created_roles: continue profile_role_data = { "profile": profile.id, "establishment": establishment.id, "role_type": role_type, "is_active": random.choice([True, False]) } profile_role_serializer = ProfileRoleSerializer(data=profile_role_data) if profile_role_serializer.is_valid(): profile_role_serializer.save() created_roles.add((establishment.id, role_type)) self.stdout.write(self.style.SUCCESS(f'ProfileRole for {profile.email} created successfully with role type {role_type}')) else: self.stdout.write(self.style.ERROR(f'Error in data for profile role: {profile_role_serializer.errors}')) else: self.stdout.write(self.style.ERROR(f'Error in data for profile: {profile_serializer.errors}')) def init_fees(self): fees_data = self.load_data('fees.json') for fee_data in fees_data: establishment = random.choice(self.establishments) print(f'establishment : {establishment}') fee_data["name"] = fee_data['name'] fee_data["establishment"] = establishment.id fee_data["type"] = random.choice([FeeType.REGISTRATION_FEE, FeeType.TUITION_FEE]) serializer = FeeSerializer(data=fee_data) if serializer.is_valid(): fee = serializer.save() self.stdout.write(self.style.SUCCESS(f'Fee {fee.name} created successfully')) else: self.stdout.write(self.style.ERROR(f'Error in data for fee: {serializer.errors}')) def init_discounts(self): discounts_data = self.load_data('discounts.json') for discount_data in discounts_data: establishment = random.choice(self.establishments) discount_data["name"] = discount_data['name'] discount_data["establishment"] = establishment.id discount_data["type"] = random.choice([FeeType.REGISTRATION_FEE, FeeType.TUITION_FEE]) discount_data["discount_type"] = random.choice([DiscountType.CURRENCY, DiscountType.PERCENT]) serializer = DiscountSerializer(data=discount_data) if serializer.is_valid(): discount = serializer.save() self.stdout.write(self.style.SUCCESS(f'Discount {discount.name} created successfully')) else: self.stdout.write(self.style.ERROR(f'Error in data for discount: {serializer.errors}')) def init_payment_modes(self): modes = list(PaymentModeType.objects.filter(code__in=["SEPA", "TRANSFER", "CHECK", "CASH"])) types = [FeeType.REGISTRATION_FEE, FeeType.TUITION_FEE] for establishment in self.establishments: for mode in modes: for type in types: payment_mode_data = { "mode": mode.pk, "type": type, "establishment": establishment.id } serializer = PaymentModeSerializer(data=payment_mode_data) if serializer.is_valid(): payment_mode = serializer.save() self.stdout.write(self.style.SUCCESS(f'Payment Mode {payment_mode} created successfully')) else: self.stdout.write(self.style.ERROR(f'Error in data for payment mode: {serializer.errors}')) def init_payment_plans(self): frequencies = list(PaymentPlanType.objects.filter(code__in=["ONE_TIME", "THREE_TIMES", "TEN_TIMES", "TWELVE_TIMES"])) types = [FeeType.REGISTRATION_FEE, FeeType.TUITION_FEE] current_date = timezone.now().date() for establishment in self.establishments: for frequency in frequencies: for type in types: payment_plan_data = { "frequency": frequency.pk, "type": type, "establishment": establishment.id, "due_dates": self.generate_due_dates(frequency, current_date) } serializer = PaymentPlanSerializer(data=payment_plan_data) if serializer.is_valid(): payment_plan = serializer.save() self.stdout.write(self.style.SUCCESS(f'Payment Plan {payment_plan} created successfully')) else: self.stdout.write(self.style.ERROR(f'Error in data for payment plan: {serializer.errors}')) def generate_due_dates(self, frequency, start_date): if frequency.code == "ONE_TIME": return [start_date + relativedelta(months=1)] elif frequency.code == "THREE_TIMES": return [start_date + relativedelta(months=1+4*i) for i in range(3)] elif frequency.code == "TEN_TIMES": return [start_date + relativedelta(months=1+i) for i in range(10)] elif frequency.code == "TWELVE_TIMES": return [start_date + relativedelta(months=1+i) for i in range(12)] def init_specialities(self): specialities_data = self.load_data('specialities.json') for speciality_data in specialities_data: establishment = random.choice(self.establishments) speciality_data["name"] = speciality_data['name'] speciality_data["establishment"] = establishment.id serializer = SpecialitySerializer(data=speciality_data) if serializer.is_valid(): speciality = serializer.save() self.stdout.write(self.style.SUCCESS(f'Speciality {speciality.name} created successfully')) else: self.stdout.write(self.style.ERROR(f'Error in data for speciality: {serializer.errors}')) def init_teachers(self): fake = Faker() # Récupérer tous les profils existants avec un rôle ECOLE ou ADMIN profiles_with_roles = Profile.objects.filter(roles__role_type__in=[ProfileRole.RoleType.PROFIL_ECOLE, ProfileRole.RoleType.PROFIL_ADMIN]).distinct() if not profiles_with_roles.exists(): self.stdout.write(self.style.ERROR('No profiles with role_type ECOLE or ADMIN found')) return used_profiles = set() for _ in range(15): # Récupérer un profil aléatoire qui n'a pas encore été utilisé available_profiles = profiles_with_roles.exclude(id__in=used_profiles) if not available_profiles.exists(): self.stdout.write(self.style.ERROR('Not enough profiles with role_type ECOLE or ADMIN available')) break profile = random.choice(available_profiles) used_profiles.add(profile.id) # Récupérer les ProfileRole associés au profil avec les rôles ECOLE ou ADMIN profile_roles = ProfileRole.objects.filter(profile=profile, role_type__in=[ProfileRole.RoleType.PROFIL_ECOLE, ProfileRole.RoleType.PROFIL_ADMIN]) if not profile_roles.exists(): self.stdout.write(self.style.ERROR(f'No ProfileRole with role_type ECOLE or ADMIN found for profile {profile.email}')) continue profile_role = random.choice(profile_roles) # Générer des données fictives pour l'enseignant teacher_data = { "last_name": fake.last_name(), "first_name": fake.first_name(), "profile_role": profile_role.id } establishment_specialities = list(Speciality.objects.filter(establishment=profile_role.establishment)) num_specialities = min(random.randint(1, 3), len(establishment_specialities)) selected_specialities = random.sample(establishment_specialities, num_specialities) # Créer l'enseignant si il n'existe pas teacher_serializer = TeacherSerializer(data=teacher_data) if teacher_serializer.is_valid(): teacher = teacher_serializer.save() # Associer les spécialités teacher.specialities.set(selected_specialities) teacher.save() self.stdout.write(self.style.SUCCESS(f'Teacher {teacher.last_name} created successfully for establishment {profile_role.establishment.name}')) else: self.stdout.write(self.style.ERROR(f'Error in data for teacher: {teacher_serializer.errors}')) self.stdout.write(self.style.SUCCESS('Teachers initialized or updated successfully')) def init_school_classes(self): school_classes_data = self.load_data('school_classes.json') for index, class_data in enumerate(school_classes_data, start=1): # Randomize establishment establishment = random.choice(self.establishments) class_data["atmosphere_name"] = f"Classe {index}" class_data["establishment"] = establishment.id # Randomize levels class_data["levels"] = random.sample(range(1, 10), random.randint(1, 5)) # Randomize teachers establishment_teachers = list(Teacher.objects.filter(profile_role__establishment=establishment)) if len(establishment_teachers) > 0: num_teachers = min(2, len(establishment_teachers)) selected_teachers = random.sample(establishment_teachers, num_teachers) teachers_ids = [teacher.id for teacher in selected_teachers] else: teachers_ids = [] # Use the serializer to create or update the school class class_data["teachers"] = teachers_ids serializer = SchoolClassSerializer(data=class_data) if serializer.is_valid(): school_class = serializer.save() self.stdout.write(self.style.SUCCESS(f'SchoolClass {school_class.atmosphere_name} created or updated successfully')) else: self.stdout.write(self.style.ERROR(f'Error in data for school class: {serializer.errors}')) self.stdout.write(self.style.SUCCESS('SchoolClasses initialized or updated successfully')) def init_file_group(self): fake = Faker() for establishment in self.establishments: for i in range(1, 4): # Créer 3 groupes de fichiers par établissement name = f"Fichiers d'inscription - {fake.word()}" description = fake.sentence() group_data = { "name": name, "description": description, "establishment": establishment } RegistrationFileGroup.objects.update_or_create(name=name, defaults=group_data) self.stdout.write(self.style.SUCCESS(f'RegistrationFileGroup {name} initialized or updated successfully')) self.stdout.write(self.style.SUCCESS('All RegistrationFileGroups initialized or updated successfully')) def init_register_form(self): fake = Faker('fr_FR') # Utiliser le locale français pour Faker file_group_count = RegistrationFileGroup.objects.count() # Récupérer tous les profils existants avec un ProfileRole Parent profiles_with_parent_role = Profile.objects.filter(roles__role_type=ProfileRole.RoleType.PROFIL_PARENT).distinct() if not profiles_with_parent_role.exists(): self.stdout.write(self.style.ERROR('No profiles with ProfileRole Parent found')) return used_profiles = set() for _ in range(50): # Récupérer un profil aléatoire qui n'a pas encore été utilisé available_profiles = profiles_with_parent_role.exclude(id__in=used_profiles) if not available_profiles.exists(): self.stdout.write(self.style.ERROR('Not enough profiles with ProfileRole Parent available')) break profile = random.choice(available_profiles) used_profiles.add(profile.id) # Récupérer le ProfileRole Parent associé au profil profile_roles = ProfileRole.objects.filter(profile=profile, role_type=ProfileRole.RoleType.PROFIL_PARENT) profile_role = random.choice(profile_roles) # Générer des données fictives pour le guardian guardian_data = { "profile_role": profile_role.id, "last_name": fake.last_name(), "first_name": fake.first_name(), "birth_date": fake.date_of_birth().strftime('%Y-%m-%d'), "address": fake.address(), "phone": "+33122334455", "profession": fake.job() } # Générer des données fictives pour l'étudiant student_data = { "last_name": fake.last_name(), "first_name": fake.first_name(), "address": fake.address(), "birth_date": fake.date_of_birth(), "birth_place": fake.city(), "birth_postal_code": fake.postcode(), "nationality": fake.country(), "attending_physician": fake.name(), "level": fake.random_int(min=1, max=6), "guardians": [guardian_data], "sibling": [] } # Créer ou mettre à jour l'étudiant student_serializer = StudentSerializer(data=student_data) if student_serializer.is_valid(): student = student_serializer.save() self.stdout.write(self.style.SUCCESS(f'Student {student.last_name} created successfully')) else: self.stdout.write(self.style.ERROR(f'Error in data for student: {student_serializer.errors}')) continue # Récupérer les frais et les réductions fees = Fee.objects.filter(id__in=[1, 2, 3, 4]) discounts = Discount.objects.filter(id__in=[1]) # Déterminer l'année scolaire (soit l'année en cours, soit l'année prochaine) school_year = random.choice([getCurrentSchoolYear(), getNextSchoolYear()]) # Créer les données du formulaire d'inscription register_form_data = { "fileGroup": RegistrationFileGroup.objects.get(id=fake.random_int(min=1, max=file_group_count)), "establishment": profile_role.establishment, "status": fake.random_int(min=1, max=3), "school_year": school_year # Ajouter l'année scolaire } # Créer ou mettre à jour le formulaire d'inscription register_form, created = RegistrationForm.objects.get_or_create( student=student, establishment=profile_role.establishment, defaults=register_form_data ) if created: register_form.fees.set(fees) register_form.discounts.set(discounts) self.stdout.write(self.style.SUCCESS(f'RegistrationForm for student {student.last_name} created successfully with school year {school_year}')) else: self.stdout.write(self.style.SUCCESS(f'RegistrationForm for student {student.last_name} already exists')) self.stdout.write(self.style.SUCCESS('50 RegistrationForms initialized or updated successfully'))