from django.core.management.base import BaseCommand from Subscriptions.models import ( RegistrationForm, Student, Guardian, Fee, Discount, RegistrationFileGroup, RegistrationTemplateMaster, RegistrationTemplate ) from Auth.models import Profile, ProfileRole from School.models import ( FeeType, Speciality, Teacher, SchoolClass, PaymentMode, PaymentModeType, PaymentPlan, PaymentPlanType, DiscountType ) from django.utils import timezone from dateutil.relativedelta import relativedelta from django.core.files import File from django.core.exceptions import SuspiciousFileOperation 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 RegistrationFormSerializer, StudentSerializer # 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) 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]) profile_role_data = { "profile": profile.id, "establishment": establishment.id, "role_type": role_type, "is_active": True } profile_role_serializer = ProfileRoleSerializer(data=profile_role_data) if profile_role_serializer.is_valid(): profile_role_serializer.save() 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"] = f"{fee_data['name']} - {establishment.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"] = f"{discount_data['name']} - {establishment.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 = [PaymentModeType.SEPA, PaymentModeType.TRANSFER, PaymentModeType.CHECK, PaymentModeType.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, "type": type, "is_active": random.choice([True, False]), "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 = [PaymentPlanType.ONE_TIME, PaymentPlanType.THREE_TIMES, PaymentPlanType.TEN_TIMES, PaymentPlanType.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, "type": type, "is_active": random.choice([True, False]), "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 == PaymentPlanType.ONE_TIME: return [start_date + relativedelta(months=1)] elif frequency == PaymentPlanType.THREE_TIMES: return [start_date + relativedelta(months=1+4*i) for i in range(3)] elif frequency == PaymentPlanType.TEN_TIMES: return [start_date + relativedelta(months=1+i) for i in range(10)] elif frequency == PaymentPlanType.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"] = f"{speciality_data['name']} - {establishment.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": f"{fake.first_name()} - {profile_role.establishment.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} - {establishment.name}" 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)) num_teachers = min(random.randint(1, 10), len(establishment_teachers)) selected_teachers = random.sample(establishment_teachers, num_teachers) teachers_ids = [teacher.id for teacher in selected_teachers] # 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()} - {establishment.name}" 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): establishment = random.choice(self.establishments) # 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_role = ProfileRole.objects.filter(profile=profile, role_type=ProfileRole.RoleType.PROFIL_PARENT).first() # 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": fake.phone_number(), "profession": fake.job() } # Générer des données fictives pour l'étudiant student_data = { "last_name": fake.last_name(), "first_name": f"{fake.first_name()} - {establishment.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]) # 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": establishment, "status": fake.random_int(min=1, max=3) } # Créer ou mettre à jour le formulaire d'inscription register_form, created = RegistrationForm.objects.get_or_create( student=student, establishment=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')) 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'))