diff --git a/Back-End/Auth/models.py b/Back-End/Auth/models.py index 2728edb..c3ac742 100644 --- a/Back-End/Auth/models.py +++ b/Back-End/Auth/models.py @@ -30,4 +30,4 @@ class ProfileRole(models.Model): updated_date = models.DateTimeField(auto_now=True) def __str__(self): - return f"{self.profile.email} - {self.get_role_type_display()} - {self.establishment.name}" \ No newline at end of file + return f"{self.profile.email} - {self.get_role_type_display()}" \ No newline at end of file diff --git a/Back-End/Auth/serializers.py b/Back-End/Auth/serializers.py index 0ba320e..6f1db3e 100644 --- a/Back-End/Auth/serializers.py +++ b/Back-End/Auth/serializers.py @@ -104,6 +104,9 @@ class ProfileRoleSerializer(serializers.ModelSerializer): elif profile: profile = Profile.objects.get(id=profile.id) + if profile: + instance.profile = profile + 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) diff --git a/Back-End/Subscriptions/serializers.py b/Back-End/Subscriptions/serializers.py index 2ecdcb6..ff37c71 100644 --- a/Back-End/Subscriptions/serializers.py +++ b/Back-End/Subscriptions/serializers.py @@ -141,26 +141,61 @@ class StudentSerializer(serializers.ModelSerializer): profile_role = guardian_data.pop('profile_role', None) if profile_role_data: + # Vérifiez si 'profile_data' est fourni pour créer un nouveau profil + profile_data = profile_role_data.pop('profile_data', None) + if profile_data: + # Créer un nouveau profil + profile_serializer = ProfileSerializer(data=profile_data) + profile_serializer.is_valid(raise_exception=True) + profile = profile_serializer.save() + profile.set_password(profile_data['password']) + profile.save() + profile_role_data['profile'] = profile.id # Associer le profil créé + # Vérifiez si 'profile' est un objet ou une clé primaire if isinstance(profile_role_data.get('profile'), Profile): profile_role_data['profile'] = profile_role_data['profile'].id + establishment_id = profile_role_data.pop('establishment').id profile_role_data['establishment'] = establishment_id - profile_role_serializer = ProfileRoleSerializer(data=profile_role_data) - profile_role_serializer.is_valid(raise_exception=True) - profile_role = profile_role_serializer.save() + # Vérifiez si un ProfileRole existe déjà pour ce profile et cet établissement + existing_profile_role = ProfileRole.objects.filter( + profile_id=profile_role_data['profile'], + establishment=profile_role_data['establishment'], + role_type=profile_role_data['role_type'] + ).first() + + if existing_profile_role: + # Mettre à jour le ProfileRole existant + profile_role_serializer = ProfileRoleSerializer(existing_profile_role, data=profile_role_data) + profile_role_serializer.is_valid(raise_exception=True) + profile_role = profile_role_serializer.save() + else: + # Créer un nouveau ProfileRole si aucun n'existe + profile_role_serializer = ProfileRoleSerializer(data=profile_role_data) + profile_role_serializer.is_valid(raise_exception=True) + profile_role = profile_role_serializer.save() elif profile_role: + # Récupérer un ProfileRole existant par son ID profile_role = ProfileRole.objects.get(id=profile_role.id) if profile_role: guardian_data['profile_role'] = profile_role - guardian_instance, created = Guardian.objects.update_or_create( - id=guardian_data.get('id'), - defaults=guardian_data - ) - guardians_ids.append(guardian_instance.id) + # Vérifiez si un Guardian existe déjà pour ce ProfileRole + existing_guardian = Guardian.objects.filter(profile_role=profile_role).first() + if existing_guardian: + # Mettre à jour le Guardian existant + for key, value in guardian_data.items(): + setattr(existing_guardian, key, value) + existing_guardian.save() + guardians_ids.append(existing_guardian.id) + else: + # Créer un nouveau Guardian + guardian_instance = Guardian.objects.create(**guardian_data) + guardians_ids.append(guardian_instance.id) + return guardians_ids def create_or_update_siblings(self, siblings_data, student_instance): @@ -375,3 +410,4 @@ class NotificationSerializer(serializers.ModelSerializer): class Meta: model = Notification fields = '__all__' + diff --git a/Back-End/Subscriptions/views/register_form_views.py b/Back-End/Subscriptions/views/register_form_views.py index 309c268..18db66a 100644 --- a/Back-End/Subscriptions/views/register_form_views.py +++ b/Back-End/Subscriptions/views/register_form_views.py @@ -236,6 +236,7 @@ class RegisterFormWithIdView(APIView): studentForm_data = request.data.get('data', '{}') try: data = json.loads(studentForm_data) + print(f'data : {data}') except json.JSONDecodeError: return JsonResponse({"error": "Invalid JSON format in 'data'"}, status=status.HTTP_400_BAD_REQUEST) diff --git a/Front-End/src/app/[locale]/admin/subscriptions/createSubscription/page.js b/Front-End/src/app/[locale]/admin/subscriptions/createSubscription/page.js index 116f38c..93b2f64 100644 --- a/Front-End/src/app/[locale]/admin/subscriptions/createSubscription/page.js +++ b/Front-End/src/app/[locale]/admin/subscriptions/createSubscription/page.js @@ -23,6 +23,7 @@ import { fetchRegisterForm, fetchStudents, createRegisterForm, + editRegisterForm, } from '@/app/actions/subscriptionAction'; import { fetchRegistrationDiscounts, @@ -53,7 +54,9 @@ export default function CreateSubscriptionPage() { guardianFirstName: '', guardianEmail: '', guardianPhone: '', + guardianProfileRole: '', selectedGuardians: [], + associatedGuardians: [], autoMail: false, selectedRegistrationDiscounts: [], selectedRegistrationFees: [], @@ -86,6 +89,8 @@ export default function CreateSubscriptionPage() { const [selectedStudent, setSelectedEleve] = useState(null); const [isNewResponsable, setIsNewResponsable] = useState(true); + const [initialGuardianEmail, setInitialGuardianEmail] = useState(''); + const { getNiveauLabel } = useClasses(); const formDataRef = useRef(formData); @@ -164,11 +169,13 @@ export default function CreateSubscriptionPage() { useEffect(() => { if (!formData.guardianEmail) { - // Si l'email est vide, réinitialiser existingProfileId + // Si l'email est vide, réinitialiser existingProfileId et existingProfileInSchool setFormData((prevData) => ({ ...prevData, isExistingParentProfile: false, existingProfileId: null, + existingProfileInSchool: false, + associatedGuardians: [], })); return; } @@ -179,12 +186,28 @@ export default function CreateSubscriptionPage() { ); if (existingProfile) { - // Si un profil avec cet email existe, valoriser isExistingParentProfile et existingProfileId + // Vérifiez si le profil parent est associé à l'établissement sélectionné + const isInSchool = existingProfile.roles.some( + (role) => + role.role_type === 2 && role.establishment === selectedEstablishmentId + ); + + // Récupérer l'ID de l'id_associated_person si applicable + const associatedPersonId = existingProfile.roles.find( + (role) => + role.role_type === 2 && role.establishment === selectedEstablishmentId + )?.id_associated_person; + + // Mettre à jour les variables en fonction des résultats setFormData((prevData) => ({ ...prevData, isExistingParentProfile: true, existingProfileId: existingProfile.id, // Récupérer l'ID du profil associé - guardianEmail: existingProfile.email || '' + existingProfileInSchool: isInSchool, // Vérifie si le profil est dans l'établissement + guardianEmail: existingProfile.email || '', + associatedGuardians: associatedPersonId + ? [associatedPersonId] // Ajouter l'ID de l'id_associated_person si trouvé + : [], })); } else { // Si aucun profil avec cet email n'existe, réinitialiser les champs @@ -192,9 +215,11 @@ export default function CreateSubscriptionPage() { ...prevData, isExistingParentProfile: false, existingProfileId: null, + existingProfileInSchool: false, + associatedGuardians: [], })); } - }, [formData.guardianEmail, profiles]); + }, [formData.guardianEmail, profiles, selectedEstablishmentId]); useEffect(() => { fetchProfiles() @@ -214,11 +239,19 @@ export default function CreateSubscriptionPage() { studentGender: data?.student?.gender || '', guardianLastName: data?.student?.guardians[0]?.last_name || '', guardianFirstName: data?.student?.guardians[0]?.first_name || '', - guardianEmail: data?.student?.guardians[0]?.associated_profile_email || '', + guardianEmail: + data?.student?.guardians[0]?.associated_profile_email || '', guardianPhone: data?.student?.guardians[0]?.phone || '', selectedFileGroup: data?.fileGroup || '', schoolYear: data?.school_year || '', + guardianProfileRole: + data?.student?.guardians[0]?.profile_role || '', })); + + // Définir l'email initial + setInitialGuardianEmail( + data?.student?.guardians[0]?.associated_profile_email || '' + ); }) .catch(requestErrorHandler); } @@ -317,8 +350,8 @@ export default function CreateSubscriptionPage() { } }; - const createRF = () => { - logger.debug('createRF formData:', formDataRef.current); + const submit = () => { + logger.debug('formData:', formDataRef.current); const selectedRegistrationFeesIds = formDataRef.current.selectedRegistrationFees.map((feeId) => feeId); @@ -344,6 +377,79 @@ export default function CreateSubscriptionPage() { ...selectedTuitionDiscountsIds, ]; + // Vérifiez si le profil existe dans la liste des profils + const existingProfile = profiles.find( + (profile) => profile.id === formDataRef.current.existingProfileId + ); + + // Affichez le profil existant dans la console + console.log('Profil existant trouvé :', existingProfile?.email); + console.log('debug : ', initialGuardianEmail); + + const guardians = (() => { + if (formDataRef.current.selectedGuardians.length > 0) { + // Cas 3 : Des guardians sont sélectionnés + console.log('Cas 3 : Des guardians sont sélectionnés'); + return formDataRef.current.selectedGuardians.map((guardianId) => ({ + id: guardianId, + })); + } else if (formDataRef.current.isExistingParentProfile) { + if (initialGuardianEmail !== existingProfile?.email) { + // Cas 2 : Profil existant différent de l'ancien + console.log( + "Cas 2 : Profil existant différent de l'ancien, mise à jour du profil", + { + existingProfile, + guardianEmail: formDataRef.current.guardianEmail, + } + ); + return [ + { + profile_role_data: { + establishment: selectedEstablishmentId, + role_type: 2, + is_active: true, + profile: formDataRef.current.existingProfileId, + }, + last_name: formDataRef.current.guardianLastName, + first_name: formDataRef.current.guardianFirstName, + birth_date: formDataRef.current.guardianBirthDate, + phone: formDataRef.current.guardianPhone, + }, + ]; + } else { + // Cas 4 : Profil existant avec le même email + console.log('Cas 4 : Profil existant avec le même email', { + existingProfile, + }); + return []; + } + } else { + // Cas 1 : Profil inexistant + console.log("Cas 1 : Profil inexistant, création d'un nouveau profil"); + return [ + { + profile_role_data: { + establishment: selectedEstablishmentId, + role_type: 2, + is_active: false, + profile_data: { + email: formDataRef.current.guardianEmail, + password: 'Provisoire01!', + username: formDataRef.current.guardianEmail, + }, + }, + last_name: formDataRef.current.guardianLastName, + first_name: formDataRef.current.guardianFirstName, + birth_date: formDataRef.current.guardianBirthDate, + phone: formDataRef.current.guardianPhone, + }, + ]; + } + })(); + + console.log('test : ', guardians); + const data = { student: { last_name: formDataRef.current.studentLastName, @@ -354,42 +460,7 @@ export default function CreateSubscriptionPage() { ...(formDataRef.current.studentGender && { gender: formDataRef.current.studentGender, }), - guardians: formDataRef.current.selectedGuardians.length - ? formDataRef.current.selectedGuardians.map((guardianId) => ({ - id: guardianId, - })) - : formDataRef.current.isExistingParentProfile - ? [ - { - profile_role_data: { - establishment: selectedEstablishmentId, - role_type: 2, - is_active: true, - profile: formDataRef.current.existingProfileId, - }, - last_name: formDataRef.current.guardianLastName, - first_name: formDataRef.current.guardianFirstName, - birth_date: formDataRef.current.guardianBirthDate, - phone: formDataRef.current.guardianPhone, - }, - ] - : [ - { - profile_role_data: { - establishment: selectedEstablishmentId, - role_type: 2, - is_active: false, - profile_data: { - email: formDataRef.current.guardianEmail, - password: 'Provisoire01!', - username: formDataRef.current.guardianEmail, - }, - }, - last_name: formDataRef.current.guardianLastName, - first_name: formDataRef.current.guardianFirstName, - phone: formDataRef.current.guardianPhone, - }, - ], + guardians, sibling: [], }, fees: allFeesIds, @@ -400,90 +471,113 @@ export default function CreateSubscriptionPage() { }; setIsLoading(true); + if (registerFormID) { + const formData = new FormData(); - // Création du dossier d'inscription - createRegisterForm(data, csrfToken) - .then((data) => { - // Clonage des schoolFileTemplates - const masters = schoolFileMasters.filter((file) => - file.groups.includes(selectedFileGroup) - ); - const parentMasters = parentFileMasters.filter((file) => - file.groups.includes(selectedFileGroup) - ); + // Ajouter les données JSON sous forme de chaîne + formData.append('data', JSON.stringify(data)); + // Mode édition + editRegisterForm(registerFormID, formData, csrfToken) + .then((response) => { + logger.debug('Dossier mis à jour avec succès:', response); + router.push(FE_ADMIN_SUBSCRIPTIONS_URL); + }) + .catch((error) => { + setIsLoading(false); + logger.error('Erreur lors de la mise à jour du dossier:', error); + }); + } else { + // Création du dossier d'inscription + createRegisterForm(data, csrfToken) + .then((data) => { + // Clonage des schoolFileTemplates + const masters = schoolFileMasters.filter((file) => + file.groups.includes(selectedFileGroup) + ); + const parentMasters = parentFileMasters.filter((file) => + file.groups.includes(selectedFileGroup) + ); - const clonePromises = masters.map((templateMaster) => - cloneTemplate( - templateMaster.id, - formData.guardianEmail, - templateMaster.is_required - ) - .then((clonedDocument) => { - const cloneData = { - name: `${templateMaster.name}_${formData.studentFirstName}_${formData.studentLastName}`, - slug: clonedDocument.slug, - id: clonedDocument.id, - master: templateMaster.id, - registration_form: data.student.id, - }; + const clonePromises = masters.map((templateMaster) => + cloneTemplate( + templateMaster.id, + formData.guardianEmail, + templateMaster.is_required + ) + .then((clonedDocument) => { + const cloneData = { + name: `${templateMaster.name}_${formData.studentFirstName}_${formData.studentLastName}`, + slug: clonedDocument.slug, + id: clonedDocument.id, + master: templateMaster.id, + registration_form: data.student.id, + }; - return createRegistrationSchoolFileTemplate(cloneData, csrfToken) - .then((response) => - logger.debug('Template enregistré avec succès:', response) + return createRegistrationSchoolFileTemplate( + cloneData, + csrfToken ) - .catch((error) => { - setIsLoading(false); - logger.error( - "Erreur lors de l'enregistrement du template:", - error - ); - }); + .then((response) => + logger.debug('Template enregistré avec succès:', response) + ) + .catch((error) => { + setIsLoading(false); + logger.error( + "Erreur lors de l'enregistrement du template:", + error + ); + }); + }) + .catch((error) => { + setIsLoading(false); + logger.error('Error during cloning or sending:', error); + }) + ); + + // Clonage des parentFileTemplates + const parentClonePromises = parentMasters.map((parentMaster) => { + const parentTemplateData = { + master: parentMaster.id, + registration_form: data.student.id, + }; + + return createRegistrationParentFileTemplate( + parentTemplateData, + csrfToken + ) + .then((response) => + logger.debug( + 'Parent template enregistré avec succès:', + response + ) + ) + .catch((error) => { + setIsLoading(false); + logger.error( + "Erreur lors de l'enregistrement du parent template:", + error + ); + }); + }); + + // Attendre que tous les clones soient créés + Promise.all([...clonePromises, ...parentClonePromises]) + .then(() => { + // Redirection après succès + router.push(FE_ADMIN_SUBSCRIPTIONS_URL); }) .catch((error) => { setIsLoading(false); logger.error('Error during cloning or sending:', error); - }) - ); - - // Clonage des parentFileTemplates - const parentClonePromises = parentMasters.map((parentMaster) => { - const parentTemplateData = { - master: parentMaster.id, - registration_form: data.student.id, - }; - - return createRegistrationParentFileTemplate( - parentTemplateData, - csrfToken - ) - .then((response) => - logger.debug('Parent template enregistré avec succès:', response) - ) - .catch((error) => { - setIsLoading(false); - logger.error( - "Erreur lors de l'enregistrement du parent template:", - error - ); }); + }) + .catch((error) => { + setIsLoading(false); + logger.error('Error during register form creation:', error); }); - - // Attendre que tous les clones soient créés - Promise.all([...clonePromises, ...parentClonePromises]) - .then(() => { - // Redirection après succès - router.push(FE_ADMIN_SUBSCRIPTIONS_URL); - }) - .catch((error) => { - setIsLoading(false); - logger.error('Error during cloning or sending:', error); - }); - }) - .catch((error) => { - setIsLoading(false); - logger.error('Error during register form creation:', error); - }); + } }; + const handleEleveSelection = (student) => { setSelectedEleve(student); setExistingGuardians(student.guardians); @@ -1086,7 +1180,7 @@ export default function CreateSubscriptionPage() {