feat: Refactoring de la fonction de création de profil sur guardian côté

FRONT
This commit is contained in:
N3WT DE COMPET
2025-03-11 21:58:09 +01:00
parent 023b46e16e
commit 753a8d647e
18 changed files with 326 additions and 386 deletions

View File

@ -1,24 +1,17 @@
from rest_framework import serializers from rest_framework import serializers
from Auth.models import Profile, ProfileRole from Auth.models import Profile, ProfileRole
from django.core.exceptions import ValidationError from Establishment.models import Establishment
class ProfileRoleSerializer(serializers.ModelSerializer):
class Meta:
model = ProfileRole
fields = ['role_type', 'establishment', 'is_active', 'profile']
class ProfileSerializer(serializers.ModelSerializer): class ProfileSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False) id = serializers.IntegerField(required=False)
password = serializers.CharField(write_only=True) password = serializers.CharField(write_only=True)
roles = ProfileRoleSerializer(many=True, required=False)
class Meta: class Meta:
model = Profile model = Profile
fields = ['id', 'password', 'email', 'code', 'datePeremption', 'username', 'roles'] fields = ['id', 'password', 'email', 'code', 'datePeremption', 'username']
extra_kwargs = {'password': {'write_only': True}} extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data): def create(self, validated_data):
roles_data = validated_data.pop('roles', [])
user = Profile( user = Profile(
username=validated_data['username'], username=validated_data['username'],
email=validated_data['email'], email=validated_data['email'],
@ -28,14 +21,9 @@ class ProfileSerializer(serializers.ModelSerializer):
user.set_password(validated_data['password']) user.set_password(validated_data['password'])
user.full_clean() user.full_clean()
user.save() user.save()
for role_data in roles_data:
ProfileRole.objects.create(profile=user, **role_data)
return user return user
def update(self, instance, validated_data): def update(self, instance, validated_data):
roles_data = validated_data.pop('roles', [])
password = validated_data.pop('password', None) password = validated_data.pop('password', None)
instance = super().update(instance, validated_data) instance = super().update(instance, validated_data)
@ -44,17 +32,6 @@ class ProfileSerializer(serializers.ModelSerializer):
instance.full_clean() instance.full_clean()
instance.save() instance.save()
for role_data in roles_data:
ProfileRole.objects.update_or_create(
profile=instance,
establishment_id=role_data.get('establishment_id'),
defaults={
'role_type': role_data.get('role_type'),
'is_active': role_data.get('is_active', True)
}
)
return instance return instance
def to_representation(self, instance): def to_representation(self, instance):
@ -62,6 +39,34 @@ class ProfileSerializer(serializers.ModelSerializer):
ret['password'] = '********' ret['password'] = '********'
return ret return ret
class ProfileRoleSerializer(serializers.ModelSerializer):
profile = ProfileSerializer()
establishment = serializers.PrimaryKeyRelatedField(queryset=Establishment.objects.all())
class Meta:
model = ProfileRole
fields = ['role_type', 'establishment', 'is_active', 'profile']
def create(self, validated_data):
profile_data = validated_data.pop('profile')
profile_serializer = ProfileSerializer(data=profile_data)
profile_serializer.is_valid(raise_exception=True)
profile = profile_serializer.save()
profile_role = ProfileRole.objects.create(profile=profile, **validated_data)
return profile_role
def update(self, instance, validated_data):
profile_data = validated_data.pop('profile')
profile_serializer = ProfileSerializer(instance.profile, data=profile_data)
profile_serializer.is_valid(raise_exception=True)
profile = profile_serializer.save()
instance.role_type = validated_data.get('role_type', instance.role_type)
instance.establishment_id = validated_data.get('establishment', instance.establishment.id)
instance.is_active = validated_data.get('is_active', instance.is_active)
instance.save()
return instance
class ProfilUpdateSerializer(serializers.ModelSerializer): class ProfilUpdateSerializer(serializers.ModelSerializer):
roles = ProfileRoleSerializer(many=True, required=False) roles = ProfileRoleSerializer(many=True, required=False)

View File

@ -42,7 +42,7 @@ from School.serializers import (
) )
from Auth.serializers import ProfileSerializer, ProfileRoleSerializer from Auth.serializers import ProfileSerializer, ProfileRoleSerializer
from Establishment.serializers import EstablishmentSerializer from Establishment.serializers import EstablishmentSerializer
from Subscriptions.serializers import RegistrationFormSerializer, GuardianSerializer from Subscriptions.serializers import RegistrationFormSerializer, StudentSerializer
# Définir le chemin vers le dossier mock_datas # Définir le chemin vers le dossier mock_datas
MOCK_DATAS_PATH = os.path.join(settings.BASE_DIR, 'School', 'management', 'mock_datas') MOCK_DATAS_PATH = os.path.join(settings.BASE_DIR, 'School', 'management', 'mock_datas')
@ -52,14 +52,13 @@ class Command(BaseCommand):
def handle(self, *args, **kwargs): def handle(self, *args, **kwargs):
self.init_establishments() self.init_establishments()
self.init_profiles() #self.init_profiles()
self.init_fees() self.init_fees()
self.init_discounts() self.init_discounts()
self.init_payment_modes() self.init_payment_modes()
self.init_payment_plans() self.init_payment_plans()
self.init_specialities() self.init_specialities()
self.init_teachers() self.init_teachers()
self.init_guardians()
self.init_school_classes() self.init_school_classes()
self.init_file_group() self.init_file_group()
self.init_register_form() self.init_register_form()
@ -121,7 +120,7 @@ class Command(BaseCommand):
# Create or update the profile role for each selected role using ProfileRoleSerializer # Create or update the profile role for each selected role using ProfileRoleSerializer
for role in selected_roles: for role in selected_roles:
role_data = { role_data = {
"profile": profile.id, "profile": profile.id, # Passer l'ID du profil au lieu de l'instance de modèle Profile
"establishment": role["establishment"], "establishment": role["establishment"],
"role_type": role["role_type"], "role_type": role["role_type"],
"is_active": True "is_active": True
@ -240,19 +239,32 @@ class Command(BaseCommand):
def init_teachers(self): def init_teachers(self):
fake = Faker() fake = Faker()
# Récupérer tous les profils dont le role_type est soit ECOLE soit ADMIN # Récupérer tous les établissements
profiles = Profile.objects.filter(roles__role_type__in=[ProfileRole.RoleType.PROFIL_ECOLE, ProfileRole.RoleType.PROFIL_ADMIN]).distinct() establishments = self.establishments
for profile in profiles: for establishment in establishments:
# Récupérer les rôles associés au profil # Générer des données fictives pour le profil
profile_roles = ProfileRole.objects.filter(profile=profile, role_type__in=[ProfileRole.RoleType.PROFIL_ECOLE, ProfileRole.RoleType.PROFIL_ADMIN]) profile_data = {
"username": fake.user_name(),
"email": fake.email(),
"password": "Provisoire01!",
"code": "",
"datePeremption": ""
}
for profile_role in profile_roles: # Générer des données fictives pour le profile_role
establishment = profile_role.establishment profile_role_data = {
"establishment": establishment.id,
"role_type": fake.random_int(min=ProfileRole.RoleType.PROFIL_ECOLE, max=ProfileRole.RoleType.PROFIL_ADMIN),
"is_active": True,
"profile": profile_data
}
# Générer des données fictives pour l'enseignant
teacher_data = { teacher_data = {
"last_name": fake.last_name(), "last_name": fake.last_name(),
"first_name": f"{fake.first_name()} - {establishment.name}", "first_name": f"{fake.first_name()} - {establishment.name}",
"profile_role": profile_role.id "profile_role": profile_role_data
} }
establishment_specialities = list(Speciality.objects.filter(establishment=establishment)) establishment_specialities = list(Speciality.objects.filter(establishment=establishment))
@ -272,38 +284,6 @@ 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 init_guardians(self):
fake = Faker()
# Récupérer tous les profils dont le role_type est PROFIL_PARENT
profiles = Profile.objects.filter(roles__role_type=ProfileRole.RoleType.PROFIL_PARENT).distinct()
for profile in profiles:
# Récupérer les rôles associés au profil
profile_roles = ProfileRole.objects.filter(profile=profile, role_type=ProfileRole.RoleType.PROFIL_PARENT)
for profile_role in profile_roles:
establishment = profile_role.establishment
guardian_data = {
"last_name": fake.last_name(),
"first_name": f"{fake.first_name()} - {establishment.name}",
"profile_role": profile_role.id,
"birth_date": fake.date_of_birth().strftime('%Y-%m-%d'), # Convertir en chaîne de caractères valide
"address": fake.address(),
"phone": fake.phone_number(),
"profession": fake.job()
}
# Créer le guardian si il n'existe pas
guardian_serializer = GuardianSerializer(data=guardian_data)
if guardian_serializer.is_valid():
guardian = guardian_serializer.save()
self.stdout.write(self.style.SUCCESS(f'Guardian {guardian.last_name} created successfully for establishment {establishment.name}'))
else:
self.stdout.write(self.style.ERROR(f'Error in data for guardian: {guardian_serializer.errors}'))
self.stdout.write(self.style.SUCCESS('Guardians initialized or updated successfully'))
def init_school_classes(self): def init_school_classes(self):
school_classes_data = self.load_data('school_classes.json') school_classes_data = self.load_data('school_classes.json')
@ -358,8 +338,30 @@ class Command(BaseCommand):
for _ in range(50): for _ in range(50):
establishment = random.choice(self.establishments) establishment = random.choice(self.establishments)
# Récupérer un guardian aléatoire déjà créé # Générer des données fictives pour le profil
guardian = Guardian.objects.order_by('?').first() profile_data = {
"username": fake.user_name(),
"email": fake.email(),
"password": "Provisoire01!",
"code": "",
"datePeremption": ""
}
# Générer des données fictives pour le guardian
guardian_data = {
"profile_role": {
"establishment": establishment.id,
"role_type": ProfileRole.RoleType.PROFIL_PARENT,
"is_active": True,
"profile": profile_data
},
"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 # Générer des données fictives pour l'étudiant
student_data = { student_data = {
@ -371,16 +373,19 @@ class Command(BaseCommand):
"birth_postal_code": fake.postcode(), "birth_postal_code": fake.postcode(),
"nationality": fake.country(), "nationality": fake.country(),
"attending_physician": fake.name(), "attending_physician": fake.name(),
"level": fake.random_int(min=1, max=6) "level": fake.random_int(min=1, max=6),
"guardians": [guardian_data],
"sibling": []
} }
# Créer ou mettre à jour l'étudiant # Créer ou mettre à jour l'étudiant
student, created = Student.objects.get_or_create( student_serializer = StudentSerializer(data=student_data)
last_name=student_data["last_name"], if student_serializer.is_valid():
first_name=student_data["first_name"], student = student_serializer.save()
defaults=student_data self.stdout.write(self.style.SUCCESS(f'Student {student.last_name} created successfully'))
) else:
student.guardians.add(guardian) 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 # Récupérer les frais et les réductions
fees = Fee.objects.filter(id__in=[1, 2, 3, 4]) fees = Fee.objects.filter(id__in=[1, 2, 3, 4])

View File

@ -3,6 +3,7 @@ from .models import Teacher, Speciality, SchoolClass, Planning, LEVEL_CHOICES, D
from Auth.models import Profile, ProfileRole from Auth.models import Profile, ProfileRole
from Subscriptions.models import Student from Subscriptions.models import Student
from Establishment.models import Establishment from Establishment.models import Establishment
from Auth.serializers import ProfileRoleSerializer
from N3wtSchool import settings, bdd from N3wtSchool import settings, bdd
from django.utils import timezone from django.utils import timezone
import pytz import pytz
@ -31,10 +32,10 @@ class TeacherDetailSerializer(serializers.ModelSerializer):
class TeacherSerializer(serializers.ModelSerializer): class TeacherSerializer(serializers.ModelSerializer):
specialities = serializers.PrimaryKeyRelatedField(queryset=Speciality.objects.all(), many=True, required=False) specialities = serializers.PrimaryKeyRelatedField(queryset=Speciality.objects.all(), many=True, required=False)
specialities_details = serializers.SerializerMethodField() specialities_details = serializers.SerializerMethodField()
profile_role = serializers.PrimaryKeyRelatedField(queryset=ProfileRole.objects.all(), required=True)
updated_date_formatted = serializers.SerializerMethodField() updated_date_formatted = serializers.SerializerMethodField()
role_type = serializers.SerializerMethodField() role_type = serializers.SerializerMethodField()
associated_profile_email = serializers.SerializerMethodField() associated_profile_email = serializers.SerializerMethodField()
profile_role = ProfileRoleSerializer()
class Meta: class Meta:
model = Teacher model = Teacher
@ -42,21 +43,36 @@ class TeacherSerializer(serializers.ModelSerializer):
def create(self, validated_data): def create(self, validated_data):
specialities_data = validated_data.pop('specialities', None) specialities_data = validated_data.pop('specialities', None)
profile_role = validated_data.pop('profile_role', None) profile_role_data = validated_data.pop('profile_role')
teacher = Teacher.objects.create(**validated_data) establishment_id = profile_role_data.pop('establishment').id
profile_role_data['establishment'] = establishment_id
# Créer l'instance de ProfileRole
profile_role_serializer = ProfileRoleSerializer(data=profile_role_data)
profile_role_serializer.is_valid(raise_exception=True)
profile_role = profile_role_serializer.save()
# Créer l'enseignant avec l'instance de ProfileRole
teacher = Teacher.objects.create(profile_role=profile_role, **validated_data)
if specialities_data: if specialities_data:
teacher.specialities.set(specialities_data) teacher.specialities.set(specialities_data)
if profile_role:
teacher.profile_role = profile_role
teacher.save() teacher.save()
return teacher return teacher
def update(self, instance, validated_data): def update(self, instance, validated_data):
specialities_data = validated_data.pop('specialities', []) specialities_data = validated_data.pop('specialities', [])
profile_role_data = validated_data.pop('profile_role', None)
if profile_role_data:
establishment_id = profile_role_data.pop('establishment').id
profile_role_data['establishment'] = establishment_id
profile_role_serializer = ProfileRoleSerializer(instance.profile_role, data=profile_role_data)
profile_role_serializer.is_valid(raise_exception=True)
profile_role_serializer.save()
instance.last_name = validated_data.get('last_name', instance.last_name) instance.last_name = validated_data.get('last_name', instance.last_name)
instance.first_name = validated_data.get('first_name', instance.first_name) instance.first_name = validated_data.get('first_name', instance.first_name)
instance.email = validated_data.get('email', instance.email) instance.email = validated_data.get('email', instance.email)
instance.profile_role = validated_data.get('profile_role', instance.profile_role)
instance.save() instance.save()
if specialities_data: if specialities_data:
instance.specialities.set(specialities_data) instance.specialities.set(specialities_data)

View File

@ -2,8 +2,8 @@ from rest_framework import serializers
from .models import RegistrationFileGroup, RegistrationForm, Student, Guardian, Sibling, Language, RegistrationTemplateMaster, RegistrationTemplate from .models import RegistrationFileGroup, RegistrationForm, Student, Guardian, Sibling, Language, RegistrationTemplateMaster, RegistrationTemplate
from School.models import SchoolClass, Fee, Discount, FeeType from School.models import SchoolClass, Fee, Discount, FeeType
from School.serializers import FeeSerializer, DiscountSerializer from School.serializers import FeeSerializer, DiscountSerializer
from Auth.models import ProfileRole from Auth.models import ProfileRole, Profile
from Auth.serializers import ProfileSerializer from Auth.serializers import ProfileSerializer, ProfileRoleSerializer
from GestionMessagerie.models import Messagerie from GestionMessagerie.models import Messagerie
from GestionNotification.models import Notification from GestionNotification.models import Notification
from N3wtSchool import settings from N3wtSchool import settings
@ -24,9 +24,14 @@ class RegistrationTemplateSerializer(serializers.ModelSerializer):
fields = '__all__' fields = '__all__'
class GuardianSimpleSerializer(serializers.ModelSerializer): class GuardianSimpleSerializer(serializers.ModelSerializer):
associated_profile_email = serializers.SerializerMethodField()
class Meta: class Meta:
model = Guardian model = Guardian
fields = ['id', 'email'] fields = ['id', 'associated_profile_email']
def get_associated_profile_email(self, obj):
return obj.profile_role.profile.email
class RegistrationFormSimpleSerializer(serializers.ModelSerializer): class RegistrationFormSimpleSerializer(serializers.ModelSerializer):
guardians = GuardianSimpleSerializer(many=True, source='student.guardians') guardians = GuardianSimpleSerializer(many=True, source='student.guardians')
@ -68,7 +73,7 @@ class SiblingSerializer(serializers.ModelSerializer):
class GuardianSerializer(serializers.ModelSerializer): class GuardianSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False) id = serializers.IntegerField(required=False)
profile_role = serializers.PrimaryKeyRelatedField(queryset=ProfileRole.objects.all(), required=True) profile_role = ProfileRoleSerializer()
associated_profile_email = serializers.SerializerMethodField() associated_profile_email = serializers.SerializerMethodField()
class Meta: class Meta:
@ -78,13 +83,11 @@ class GuardianSerializer(serializers.ModelSerializer):
def get_associated_profile_email(self, obj): def get_associated_profile_email(self, obj):
return obj.profile_role.profile.email return obj.profile_role.profile.email
class StudentSerializer(serializers.ModelSerializer): class StudentSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False) id = serializers.IntegerField(required=False)
guardians = GuardianSerializer(many=True, required=False) guardians = GuardianSerializer(many=True, required=False)
siblings = SiblingSerializer(many=True, required=False) siblings = SiblingSerializer(many=True, required=False)
languages = LanguageSerializer(many=True, required=False) spoken_languages = LanguageSerializer(many=True, required=False)
associated_class_id = serializers.PrimaryKeyRelatedField(queryset=SchoolClass.objects.all(), source='associated_class', required=False, write_only=False, read_only=False) associated_class_id = serializers.PrimaryKeyRelatedField(queryset=SchoolClass.objects.all(), source='associated_class', required=False, write_only=False, read_only=False)
age = serializers.SerializerMethodField() age = serializers.SerializerMethodField()
formatted_birth_date = serializers.SerializerMethodField() formatted_birth_date = serializers.SerializerMethodField()
@ -95,30 +98,19 @@ class StudentSerializer(serializers.ModelSerializer):
model = Student model = Student
fields = '__all__' fields = '__all__'
def get_or_create_packages(self, guardians_data): def create_or_update_guardians(self, guardians_data):
guardians_ids = [] guardians_ids = []
for guardian_data in guardians_data: for guardian_data in guardians_data:
guardian_instance, created = Guardian.objects.get_or_create( profile_role_data = guardian_data.pop('profile_role')
id=guardian_data.get('id'), establishment_id = profile_role_data.pop('establishment').id
defaults=guardian_data profile_role_data['establishment'] = establishment_id
)
guardians_ids.append(guardian_instance.id)
return guardians_ids
def create(self, validated_data): profile_role_serializer = ProfileRoleSerializer(data=profile_role_data)
guardians_data = validated_data.pop('guardians', []) profile_role_serializer.is_valid(raise_exception=True)
siblings_data = validated_data.pop('siblings', []) profile_role = profile_role_serializer.save()
languages_data = validated_data.pop('spoken_languages', [])
student = Student.objects.create(**validated_data)
student.guardians.set(self.get_or_create_packages(guardians_data))
student.siblings.set(self.get_or_create_packages(siblings_data))
student.spoken_languages.set(self.get_or_create_packages(languages_data))
return student guardian_data['profile_role'] = profile_role
def create_or_update_packages(self, guardians_data):
guardians_ids = []
for guardian_data in guardians_data:
guardian_instance, created = Guardian.objects.update_or_create( guardian_instance, created = Guardian.objects.update_or_create(
id=guardian_data.get('id'), id=guardian_data.get('id'),
defaults=guardian_data defaults=guardian_data
@ -126,16 +118,47 @@ class StudentSerializer(serializers.ModelSerializer):
guardians_ids.append(guardian_instance.id) guardians_ids.append(guardian_instance.id)
return guardians_ids return guardians_ids
def create_or_update_siblings(self, siblings_data):
siblings_ids = []
for sibling_data in siblings_data:
sibling_instance, created = Sibling.objects.update_or_create(
id=sibling_data.get('id'),
defaults=sibling_data
)
siblings_ids.append(sibling_instance.id)
return siblings_ids
def create_or_update_languages(self, languages_data):
languages_ids = []
for language_data in languages_data:
language_instance, created = Language.objects.update_or_create(
id=language_data.get('id'),
defaults=language_data
)
languages_ids.append(language_instance.id)
return languages_ids
def create(self, validated_data):
guardians_data = validated_data.pop('guardians', [])
siblings_data = validated_data.pop('siblings', [])
languages_data = validated_data.pop('lanspoken_languagesguages', [])
student = Student.objects.create(**validated_data)
student.guardians.set(self.create_or_update_guardians(guardians_data))
student.siblings.set(self.create_or_update_siblings(siblings_data))
student.spoken_languages.set(self.create_or_update_languages(languages_data))
return student
def update(self, instance, validated_data): def update(self, instance, validated_data):
guardians_data = validated_data.pop('guardians', []) guardians_data = validated_data.pop('guardians', [])
siblings_data = validated_data.pop('siblings', []) siblings_data = validated_data.pop('siblings', [])
languages_data = validated_data.pop('spoken_languages', []) languages_data = validated_data.pop('spoken_languages', [])
if guardians_data: if guardians_data:
instance.guardians.set(self.create_or_update_packages(guardians_data)) instance.guardians.set(self.create_or_update_guardians(guardians_data))
if siblings_data: if siblings_data:
instance.siblings.set(self.create_or_update_packages(siblings_data)) instance.siblings.set(self.create_or_update_siblings(siblings_data))
if languages_data: if languages_data:
instance.spoken_languages.set(self.create_or_update_packages(languages_data)) instance.spoken_languages.set(self.create_or_update_languages(languages_data))
for field in self.fields: for field in self.fields:
try: try:

View File

@ -20,7 +20,13 @@ class RegistrationFileGroupView(APIView):
""" """
Récupère tous les groupes de fichiers d'inscription. Récupère tous les groupes de fichiers d'inscription.
""" """
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)
groups = RegistrationFileGroup.objects.all() groups = RegistrationFileGroup.objects.all()
if groups:
groups = groups.filter(establishment_id=establishment_id).distinct()
serializer = RegistrationFileGroupSerializer(groups, many=True) serializer = RegistrationFileGroupSerializer(groups, many=True)
return Response(serializer.data) return Response(serializer.data)

View File

@ -27,14 +27,12 @@ import {
FE_ADMIN_SETTINGS_URL FE_ADMIN_SETTINGS_URL
} from '@/utils/Url'; } from '@/utils/Url';
import { disconnect, getUser } from '@/app/actions/authAction'; import { disconnect } from '@/app/actions/authAction';
import { useSession } from 'next-auth/react'; import { useSession } from 'next-auth/react';
import { fetchEstablishment } from '@/app/actions/schoolAction';
import ProtectedRoute from '@/components/ProtectedRoute'; import ProtectedRoute from '@/components/ProtectedRoute';
import { getGravatarUrl } from '@/utils/gravatar'; import { getGravatarUrl } from '@/utils/gravatar';
import Footer from '@/components/Footer'; import Footer from '@/components/Footer';
import { getRightStr, RIGHTS } from '@/utils/rights'; import { getRightStr, RIGHTS } from '@/utils/rights';
import { getSession } from 'next-auth/react';
import logger from '@/utils/logger'; import logger from '@/utils/logger';
import { useEstablishment } from '@/context/EstablishmentContext'; import { useEstablishment } from '@/context/EstablishmentContext';
@ -53,12 +51,10 @@ export default function Layout({
"settings": { "id": "settings", "name": t('settings'), "url": FE_ADMIN_SETTINGS_URL, "icon": Settings } "settings": { "id": "settings", "name": t('settings'), "url": FE_ADMIN_SETTINGS_URL, "icon": Settings }
}; };
const [establishments, setEstablishments] = useState([]);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [isPopupVisible, setIsPopupVisible] = useState(false); const [isPopupVisible, setIsPopupVisible] = useState(false);
const [user, setUser] = useState(null);
const { data: session } = useSession(); const { data: session } = useSession();
const { selectedEstablishmentId, setSelectedEstablishmentId, profileRole, setProfileRole } = useEstablishment(); const { selectedEstablishmentId, setSelectedEstablishmentId, profileRole, setProfileRole, establishments, user } = useEstablishment();
const pathname = usePathname(); const pathname = usePathname();
const currentPage = pathname.split('/').pop(); const currentPage = pathname.split('/').pop();
@ -108,39 +104,6 @@ export default function Layout({
setIsSidebarOpen(false); setIsSidebarOpen(false);
}, [pathname]); }, [pathname]);
useEffect(() => {
getSession()
.then(session => {
if (session && session.user) {
setUser(session.user);
setEstablishments(session.user.roles.map(role => ({
id: role.establishment__id,
name: role.establishment__name,
role_type: role.role_type
})));
// Sélectionner l'établissement depuis la session ou le premier établissement par défaut
if (!selectedEstablishmentId && session.user.roles.length > 0) {
setSelectedEstablishmentId(session.user.roles[0].establishment__id);
setProfileRole(session.user.roles[0].role_type);
}
}
})
.catch(err => {
logger.error('Error fetching session:', err);
});
}, []);
useEffect(() => {
const fetchUser = async () => {
if (session) { // Vérifier que la session existe
const userData = await getUser();
setUser(userData);
}
};
fetchUser();
}, [session]);
return ( return (
<ProtectedRoute requiredRight={RIGHTS.ADMIN}> <ProtectedRoute requiredRight={RIGHTS.ADMIN}>
{!isLoading && ( {!isLoading && (

View File

@ -306,7 +306,7 @@ export default function Page() {
{ {
id: 'Files', id: 'Files',
label: 'Documents d\'inscription', label: 'Documents d\'inscription',
content: <FilesGroupsManagement csrfToken={csrfToken} /> content: <FilesGroupsManagement csrfToken={csrfToken} selectedEstablishmentId={selectedEstablishmentId} />
} }
]; ];

View File

@ -369,98 +369,34 @@ useEffect(()=>{
const allFeesIds = [...selectedRegistrationFeesIds, ...selectedTuitionFeesIds]; const allFeesIds = [...selectedRegistrationFeesIds, ...selectedTuitionFeesIds];
const allDiscountsds = [...selectedRegistrationDiscountsIds, ...selectedTuitionDiscountsIds]; const allDiscountsds = [...selectedRegistrationDiscountsIds, ...selectedTuitionDiscountsIds];
if (updatedData.selectedGuardians.length !== 0) {
const selectedGuardiansIds = updatedData.selectedGuardians.map(guardianId => guardianId)
const guardianEmail = updatedData.guardianEmail
const data = { const data = {
student: { student: {
last_name: updatedData.studentLastName, last_name: updatedData.studentLastName,
first_name: updatedData.studentFirstName, first_name: updatedData.studentFirstName,
}, guardians: updatedData.selectedGuardians.length !== 0 ? updatedData.selectedGuardians.map(guardianId => ({ id: guardianId })) : [{
idGuardians: selectedGuardiansIds, profile_role: {
fees: allFeesIds, establishment: selectedEstablishmentId,
discounts: allDiscountsds, role_type: 2,
fileGroup: selectedFileGroup, is_active: false,
establishment: ESTABLISHMENT_ID profile: {
};
createRegisterForm(data, csrfToken)
.then(data => {
// Cloner les templates pour chaque templateMaster du fileGroup
const masters = templateMasters.filter(file => file.groups.includes(selectedFileGroup));
const clonePromises = masters.map((templateMaster, index) => {
return cloneTemplate(templateMaster.id, guardianEmail, templateMaster.is_required)
.then(clonedDocument => {
// Sauvegarde des templates clonés dans la base de données
const cloneData = {
name: `clone_${clonedDocument.id}`,
slug: clonedDocument.slug,
id: clonedDocument.id,
master: templateMaster.id,
registration_form: data.student.id
};
return createRegistrationTemplates(cloneData, csrfToken)
.then(response => {
logger.debug('Template enregistré avec succès:', response);
})
.catch(error => {
logger.error('Erreur lors de l\'enregistrement du template:', error);
});
})
.catch(error => {
logger.error('Error during cloning or sending:', error);
});
});
// Attendre que tous les clones soient créés
Promise.all(clonePromises)
.then(() => {
// Mise à jour immédiate des données
setRegistrationFormsDataPending(prevState => [...(prevState || []), data]);
setTotalPending(prev => prev + 1);
if (updatedData.autoMail) {
sendConfirmRegisterForm(data.student.id, updatedData.studentLastName, updatedData.studentFirstName);
}
closeModal();
// Forcer le rechargement complet des données
setReloadFetch(true);
})
.catch(error => {
logger.error('Error during cloning or sending:', error);
});
})
.catch((error) => {
logger.error('Error:', error);
});
} else {
const data = {
email: updatedData.guardianEmail, email: updatedData.guardianEmail,
password: 'Provisoire01!', password: 'Provisoire01!',
username: updatedData.guardianEmail, username: updatedData.guardianEmail,
is_active: 0,
droit: 2
} }
},
createProfile(data, csrfToken) last_name: updatedData.guardianLastName,
.then(response => { first_name: updatedData.guardianFirstName,
if (response.id) { birth_date: updatedData.guardianBirthDate,
const data = { address: updatedData.guardianAddress,
student: {
last_name: updatedData.studentLastName,
first_name: updatedData.studentFirstName,
guardians: [{
email: updatedData.guardianEmail,
phone: updatedData.guardianPhone, phone: updatedData.guardianPhone,
associated_profile: response.id profession: updatedData.guardianProfession
}], }],
sibling: [] sibling: []
}, },
fees: allFeesIds, fees: allFeesIds,
discounts: allDiscountsds, discounts: allDiscountsds,
fileGroup: selectedFileGroup, fileGroup: selectedFileGroup,
establishment: ESTABLISHMENT_ID establishment: selectedEstablishmentId
}; };
createRegisterForm(data, csrfToken) createRegisterForm(data, csrfToken)
@ -498,12 +434,10 @@ useEffect(()=>{
// Mise à jour immédiate des données // Mise à jour immédiate des données
setRegistrationFormsDataPending(prevState => [...(prevState || []), data]); setRegistrationFormsDataPending(prevState => [...(prevState || []), data]);
setTotalPending(prev => prev + 1); setTotalPending(prev => prev + 1);
if (updatedData.autoMail) { if (updatedData.autoMail) {
sendConfirmRegisterForm(data.student.id, updatedData.studentLastName, updatedData.studentFirstName); sendConfirmRegisterForm(data.student.id, updatedData.studentLastName, updatedData.studentFirstName);
} }
closeModal(); closeModal();
logger.debug('Success:', data);
// Forcer le rechargement complet des données // Forcer le rechargement complet des données
setReloadFetch(true); setReloadFetch(true);
}) })
@ -513,20 +447,7 @@ useEffect(()=>{
}) })
.catch((error) => { .catch((error) => {
logger.error('Error:', error); logger.error('Error:', error);
deleteProfile(response.id, csrfToken)
.then(() => {
logger.debug('Profile deleted due to RF creation failure');
})
.catch(deleteError => {
logger.error('Error deleting profile:', deleteError);
}); });
});
}
})
.catch(error => {
logger.error('Error:', error);
});
}
} }
const columns = [ const columns = [

View File

@ -8,7 +8,7 @@ import Logo from '@/components/Logo'; // Ajout de l'importation du composant Log
import { FE_PARENTS_HOME_URL,FE_PARENTS_MESSAGERIE_URL,FE_PARENTS_SETTINGS_URL } from '@/utils/Url'; // Ajout de l'importation de l'URL de la page d'accueil parent import { FE_PARENTS_HOME_URL,FE_PARENTS_MESSAGERIE_URL,FE_PARENTS_SETTINGS_URL } from '@/utils/Url'; // Ajout de l'importation de l'URL de la page d'accueil parent
import { fetchMessages } from '@/app/actions/messagerieAction'; import { fetchMessages } from '@/app/actions/messagerieAction';
import ProtectedRoute from '@/components/ProtectedRoute'; import ProtectedRoute from '@/components/ProtectedRoute';
import { disconnect, getUser } from '@/app/actions/authAction'; import { disconnect } from '@/app/actions/authAction';
import Popup from '@/components/Popup'; import Popup from '@/components/Popup';
import logger from '@/utils/logger'; import logger from '@/utils/logger';
import { useSession } from 'next-auth/react'; import { useSession } from 'next-auth/react';
@ -38,18 +38,6 @@ export default function Layout({
disconnect(); disconnect();
}; };
useEffect(() => {
const fetchUser = async () => {
if (session) { // Vérifier que la session existe
const userData = await getUser();
setUser(userData);
}
};
fetchUser();
}, [session]);
// useEffect(() => { // useEffect(() => {
// if (status === 'loading') return; // if (status === 'loading') return;
// if (!session) { // if (!session) {

View File

@ -179,31 +179,3 @@ export const getResetPassword = (uuid) => {
}, },
}).then(requestResponseHandler); }).then(requestResponseHandler);
}; };
/**
* Récupère les informations de l'utilisateur connecté depuis la session
* @returns {Promise} Les données de l'utilisateur
*/
export const getUser = async () => {
try {
const session = await getSession();
if (!session || !session.user) {
return null;
}
return {
id: session.user.user_id,
email: session.user.email,
roles: session.user.roles.map(role => ({
role_type: role.role_type,
establishment_id: role.establishment__id,
establishment_name: role.establishment__name
}))
};
} catch (error) {
console.error('Error getting user from session:', error);
throw error;
}
};

View File

@ -17,8 +17,8 @@ const requestResponseHandler = async (response) => {
throw error; throw error;
} }
export async function fetchRegistrationFileGroups() { export async function fetchRegistrationFileGroups(establishment) {
const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}`, { const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}?establishment_id=${establishment}`, {
credentials: 'include', credentials: 'include',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',

View File

@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import ToggleSwitch from '@/components/ToggleSwitch'; // Import du composant ToggleSwitch import ToggleSwitch from '@/components/ToggleSwitch'; // Import du composant ToggleSwitch
import DraggableFileUpload from './DraggableFileUpload'; import DraggableFileUpload from './DraggableFileUpload';
import { fetchRegistrationFileGroups } from '@/app/actions/registerFileGroupAction'; import { fetchRegistrationFileGroups } from '@/app/actions/registerFileGroupAction';
import { useEstablishment } from '@/context/EstablishmentContext';
export default function FileUpload({ onFileUpload, fileToEdit = null }) { export default function FileUpload({ onFileUpload, fileToEdit = null }) {
const [fileName, setFileName] = useState(''); const [fileName, setFileName] = useState('');
@ -11,8 +12,10 @@ export default function FileUpload({ onFileUpload, fileToEdit = null }) {
const [groups, setGroups] = useState([]); const [groups, setGroups] = useState([]);
const [selectedGroup, setSelectedGroup] = useState(''); const [selectedGroup, setSelectedGroup] = useState('');
const { selectedEstablishmentId } = useEstablishment();
useEffect(() => { useEffect(() => {
fetchRegistrationFileGroups().then(data => setGroups(data)); fetchRegistrationFileGroups(selectedEstablishmentId).then(data => setGroups(data));
if (fileToEdit) { if (fileToEdit) {
setFileName(fileToEdit.name || ''); setFileName(fileToEdit.name || '');

View File

@ -44,7 +44,7 @@ function Sidebar({ establishments, currentPage, items, onCloseMobile, onEstablis
<div className="w-64 bg-white border-r h-full border-gray-200 py-6 px-4"> <div className="w-64 bg-white border-r h-full border-gray-200 py-6 px-4">
<div className="flex items-center mb-8 px-2"> <div className="flex items-center mb-8 px-2">
<select <select
value={selectedEstablishmentId} value={selectedEstablishmentId || ''}
onChange={handleEstablishmentChange} onChange={handleEstablishmentChange}
className="form-select block w-full mt-1" className="form-select block w-full mt-1"
> >

View File

@ -7,6 +7,7 @@ import { BE_DOCUSEAL_GET_JWT, BASE_URL } from '@/utils/Url';
import Button from '@/components/Button'; // Import du composant Button import Button from '@/components/Button'; // Import du composant Button
import MultiSelect from '@/components/MultiSelect'; // Import du composant MultiSelect import MultiSelect from '@/components/MultiSelect'; // Import du composant MultiSelect
import { useCsrfToken } from '@/context/CsrfContext'; import { useCsrfToken } from '@/context/CsrfContext';
import { useEstablishment } from '@/context/EstablishmentContext';
export default function FileUpload({ handleCreateTemplateMaster, handleEditTemplateMaster, fileToEdit = null, onSuccess }) { export default function FileUpload({ handleCreateTemplateMaster, handleEditTemplateMaster, fileToEdit = null, onSuccess }) {
const [isRequired, setIsRequired] = useState(false); // État pour le toggle isRequired const [isRequired, setIsRequired] = useState(false); // État pour le toggle isRequired
@ -20,8 +21,10 @@ export default function FileUpload({ handleCreateTemplateMaster, handleEditTempl
const csrfToken = useCsrfToken(); const csrfToken = useCsrfToken();
const { selectedEstablishmentId } = useEstablishment();
useEffect(() => { useEffect(() => {
fetchRegistrationFileGroups().then(data => setGroups(data)); fetchRegistrationFileGroups(selectedEstablishmentId).then(data => setGroups(data));
if (fileToEdit) { if (fileToEdit) {
setUploadedFileName(fileToEdit.name || ''); setUploadedFileName(fileToEdit.name || '');

View File

@ -18,7 +18,7 @@ import {
import RegistrationFileGroupForm from '@/components/Structure/Files/RegistrationFileGroupForm'; import RegistrationFileGroupForm from '@/components/Structure/Files/RegistrationFileGroupForm';
import logger from '@/utils/logger'; import logger from '@/utils/logger';
export default function FilesGroupsManagement({ csrfToken }) { export default function FilesGroupsManagement({ csrfToken, selectedEstablishmentId }) {
const [templateMasters, setTemplateMasters] = useState([]); const [templateMasters, setTemplateMasters] = useState([]);
const [templates, setTemplates] = useState([]); const [templates, setTemplates] = useState([]);
const [groups, setGroups] = useState([]); const [groups, setGroups] = useState([]);
@ -43,9 +43,10 @@ export default function FilesGroupsManagement({ csrfToken }) {
}; };
useEffect(() => { useEffect(() => {
if (selectedEstablishmentId) {
Promise.all([ Promise.all([
fetchRegistrationTemplateMaster(), fetchRegistrationTemplateMaster(),
fetchRegistrationFileGroups(), fetchRegistrationFileGroups(selectedEstablishmentId),
fetchRegistrationTemplates() fetchRegistrationTemplates()
]).then(([filesTemplateMasters, groupsData, filesTemplates]) => { ]).then(([filesTemplateMasters, groupsData, filesTemplates]) => {
setGroups(groupsData); setGroups(groupsData);
@ -58,7 +59,8 @@ export default function FilesGroupsManagement({ csrfToken }) {
}).finally(() => { }).finally(() => {
setReloadTemplates(false); setReloadTemplates(false);
}); });
}, [reloadTemplates]); }
}, [reloadTemplates, selectedEstablishmentId]);
const deleteTemplateMaster = (templateMaster) => { const deleteTemplateMaster = (templateMaster) => {
// Supprimer les clones associés via l'API DocuSeal // Supprimer les clones associés via l'API DocuSeal

View File

@ -19,6 +19,7 @@ import {
editRegistrationFileGroup editRegistrationFileGroup
} from '@/app/actions/registerFileGroupAction'; } from '@/app/actions/registerFileGroupAction';
import RegistrationFileGroupForm from '@/components/RegistrationFileGroupForm'; import RegistrationFileGroupForm from '@/components/RegistrationFileGroupForm';
import { useEstablishment } from '@/context/EstablishmentContext';
export default function FilesManagement({ csrfToken }) { export default function FilesManagement({ csrfToken }) {
const [fichiers, setFichiers] = useState([]); const [fichiers, setFichiers] = useState([]);
@ -29,7 +30,8 @@ export default function FilesManagement({ csrfToken }) {
const [fileToEdit, setFileToEdit] = useState(null); const [fileToEdit, setFileToEdit] = useState(null);
const [isGroupModalOpen, setIsGroupModalOpen] = useState(false); const [isGroupModalOpen, setIsGroupModalOpen] = useState(false);
const [groupToEdit, setGroupToEdit] = useState(null); const [groupToEdit, setGroupToEdit] = useState(null);
const [token]
const { selectedEstablishmentId } = useEstablishment();
// Fonction pour transformer les données des fichiers avec les informations complètes du groupe // Fonction pour transformer les données des fichiers avec les informations complètes du groupe
const transformFileData = (file, groups) => { const transformFileData = (file, groups) => {
@ -45,7 +47,7 @@ export default function FilesManagement({ csrfToken }) {
useEffect(() => { useEffect(() => {
Promise.all([ Promise.all([
fetchRegisterFormFileTemplate(), fetchRegisterFormFileTemplate(),
fetchRegistrationFileGroups() fetchRegistrationFileGroups(selectedEstablishmentId)
]).then(([filesData, groupsData]) => { ]).then(([filesData, groupsData]) => {
setGroups(groupsData); setGroups(groupsData);
// Sélectionner automatiquement le premier groupe s'il existe // Sélectionner automatiquement le premier groupe s'il existe

View File

@ -1,11 +1,14 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { fetchRegistrationFileGroups } from '@/app/actions/registerFileGroupAction'; import { fetchRegistrationFileGroups } from '@/app/actions/registerFileGroupAction';
import { useEstablishment } from '@/context/EstablishmentContext';
export default function RegistrationFileGroupList() { export default function RegistrationFileGroupList() {
const [groups, setGroups] = useState([]); const [groups, setGroups] = useState([]);
const { selectedEstablishmentId } = useEstablishment();
useEffect(() => { useEffect(() => {
fetchRegistrationFileGroups().then(data => setGroups(data)); fetchRegistrationFileGroups(selectedEstablishmentId).then(data => setGroups(data));
}, []); }, []);
return ( return (

View File

@ -1,13 +1,41 @@
import React, { createContext, useContext, useState, useEffect } from 'react'; import React, { createContext, useContext, useState, useEffect } from 'react';
import { getSession } from 'next-auth/react';
import logger from '@/utils/logger';
const EstablishmentContext = createContext(); const EstablishmentContext = createContext();
export const EstablishmentProvider = ({ children }) => { export const EstablishmentProvider = ({ children }) => {
const [selectedEstablishmentId, setSelectedEstablishmentId] = useState(null); const [selectedEstablishmentId, setSelectedEstablishmentId] = useState(null);
const [profileRole, setProfileRole] = useState(null); const [profileRole, setProfileRole] = useState(null);
const [establishments, setEstablishments] = useState([]);
const [user, setUser] = useState(null);
useEffect(() => {
getSession()
.then(session => {
if (session && session.user) {
setUser(session.user);
console.log("getSession")
const userEstablishments = session.user.roles.map(role => ({
id: role.establishment__id,
name: role.establishment__name,
role_type: role.role_type
}));
setEstablishments(userEstablishments);
// Sélectionner l'établissement depuis la session ou le premier établissement par défaut
if (userEstablishments.length > 0) {
setSelectedEstablishmentId(userEstablishments[0].id);
setProfileRole(userEstablishments[0].role_type);
}
}
})
.catch(err => {
logger.error('Error fetching session:', err);
});
}, []);
return ( return (
<EstablishmentContext.Provider value={{ selectedEstablishmentId, setSelectedEstablishmentId, profileRole, setProfileRole }}> <EstablishmentContext.Provider value={{ selectedEstablishmentId, setSelectedEstablishmentId, profileRole, setProfileRole, establishments, user }}>
{children} {children}
</EstablishmentContext.Provider> </EstablishmentContext.Provider>
); );