diff --git a/Back-End/Subscriptions/models.py b/Back-End/Subscriptions/models.py
index d72fed4..4b793b7 100644
--- a/Back-End/Subscriptions/models.py
+++ b/Back-End/Subscriptions/models.py
@@ -27,7 +27,7 @@ class Guardian(models.Model):
"""
last_name = models.CharField(max_length=200, default="")
first_name = models.CharField(max_length=200, default="")
- birth_date = models.CharField(max_length=200, default="", blank=True)
+ birth_date = models.DateField(null=True, blank=True)
address = models.CharField(max_length=200, default="", blank=True)
phone = models.CharField(max_length=200, default="", blank=True)
profession = models.CharField(max_length=200, default="", blank=True)
@@ -43,7 +43,7 @@ class Sibling(models.Model):
id = models.AutoField(primary_key=True)
last_name = models.CharField(max_length=200, default="")
first_name = models.CharField(max_length=200, default="")
- birth_date = models.CharField(max_length=200, default="", blank=True)
+ birth_date = models.DateField(null=True, blank=True)
def __str__(self):
return "SIBLING"
diff --git a/Back-End/Subscriptions/serializers.py b/Back-End/Subscriptions/serializers.py
index 4348a49..04ed9aa 100644
--- a/Back-End/Subscriptions/serializers.py
+++ b/Back-End/Subscriptions/serializers.py
@@ -158,15 +158,33 @@ class StudentSerializer(serializers.ModelSerializer):
guardians_ids.append(guardian_instance.id)
return guardians_ids
- def create_or_update_siblings(self, siblings_data):
- siblings_ids = []
+ def create_or_update_siblings(self, siblings_data, student_instance):
+ """
+ Crée ou met à jour les frères et sœurs associés à un étudiant.
+ Supprime les frères et sœurs qui ne sont plus présents dans siblings_data.
+ """
+
+ # Si siblings_data est vide, supprimer tous les frères et sœurs associés
+ if not siblings_data:
+ student_instance.siblings.clear() # Supprime toutes les relations
+ return []
+
+ # Récupérer les IDs des frères et sœurs existants
+ existing_sibling_ids = set(student_instance.siblings.values_list('id', flat=True))
+
+ # Créer ou mettre à jour les frères et sœurs
+ updated_sibling_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
+ updated_sibling_ids.append(sibling_instance.id)
+
+ # Supprimer les frères et sœurs qui ne sont plus dans siblings_data
+ siblings_to_delete = existing_sibling_ids - set(updated_sibling_ids)
+ Sibling.objects.filter(id__in=siblings_to_delete).delete()
+ return updated_sibling_ids
def create_or_update_languages(self, languages_data):
languages_ids = []
@@ -195,8 +213,10 @@ class StudentSerializer(serializers.ModelSerializer):
languages_data = validated_data.pop('spoken_languages', [])
if guardians_data:
instance.guardians.set(self.create_or_update_guardians(guardians_data))
- if siblings_data:
- instance.siblings.set(self.create_or_update_siblings(siblings_data))
+
+ sibling_ids = self.create_or_update_siblings(siblings_data, instance)
+ instance.siblings.set(sibling_ids)
+
if languages_data:
instance.spoken_languages.set(self.create_or_update_languages(languages_data))
diff --git a/Back-End/Subscriptions/util.py b/Back-End/Subscriptions/util.py
index 3f2406b..68b02a8 100644
--- a/Back-End/Subscriptions/util.py
+++ b/Back-End/Subscriptions/util.py
@@ -146,7 +146,6 @@ def rfToPDF(registerForm, filename):
# Vérifier si le fichier existe et le supprimer
if os.path.exists(existing_file_path):
- print(f'exist ! REMOVE')
os.remove(existing_file_path)
registerForm.registration_file.delete(save=False)
else:
diff --git a/Back-End/Subscriptions/views/register_form_views.py b/Back-End/Subscriptions/views/register_form_views.py
index 36cdecb..3f3cad3 100644
--- a/Back-End/Subscriptions/views/register_form_views.py
+++ b/Back-End/Subscriptions/views/register_form_views.py
@@ -266,6 +266,23 @@ class RegisterFormWithIdView(APIView):
# Sauvegarder la photo si elle est présente dans la requête
if photo_file:
student = registerForm.student
+
+ # Vérifier si une photo existante est déjà associée à l'étudiant
+ if student.photo and student.photo.name:
+ # Construire le chemin complet du fichier existant
+ if os.path.isabs(student.photo.name):
+ existing_file_path = student.photo.name
+ else:
+ existing_file_path = os.path.join(settings.MEDIA_ROOT, student.photo.name.lstrip('/'))
+
+ # Vérifier si le fichier existe et le supprimer
+ if os.path.exists(existing_file_path):
+ os.remove(existing_file_path)
+ student.photo.delete(save=False)
+ else:
+ print(f'File does not exist: {existing_file_path}')
+
+ # Sauvegarder la nouvelle photo
student.photo.save(photo_file.name, photo_file, save=True)
else:
return JsonResponse(studentForm_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)
diff --git a/Front-End/src/components/FileUpload.js b/Front-End/src/components/FileUpload.js
index f809323..665eeec 100644
--- a/Front-End/src/components/FileUpload.js
+++ b/Front-End/src/components/FileUpload.js
@@ -1,6 +1,7 @@
import React, { useState, useRef } from 'react';
import { CloudUpload } from 'lucide-react';
import logger from '@/utils/logger';
+import { BASE_URL } from '@/utils/Url';
export default function FileUpload({
selectionMessage,
@@ -69,9 +70,18 @@ export default function FileUpload({
- {typeof existingFile === 'string' - ? existingFile.split('/').pop() - : existingFile?.name || 'Fichier inconnu'} + {typeof existingFile === 'string' ? ( + + {existingFile.split('/').pop()} + + ) : ( + existingFile?.name || 'Fichier inconnu' + )}
diff --git a/Front-End/src/components/Inscription/InscriptionFormShared.js b/Front-End/src/components/Inscription/InscriptionFormShared.js index 914b626..199dd39 100644 --- a/Front-End/src/components/Inscription/InscriptionFormShared.js +++ b/Front-End/src/components/Inscription/InscriptionFormShared.js @@ -23,6 +23,7 @@ import FilesToUpload from '@/components/Inscription/FilesToUpload'; import { DocusealForm } from '@docuseal/react'; import StudentInfoForm from '@/components/Inscription/StudentInfoForm'; import ResponsableInputFields from '@/components/Inscription/ResponsableInputFields'; +import SiblingInputFields from '@/components/Inscription/SiblingInputFields'; import PaymentMethodSelector from '@/components/Inscription/PaymentMethodSelector'; import ProgressStep from '@/components/ProgressStep'; import { CheckCircle, Hourglass } from 'lucide-react'; @@ -58,6 +59,7 @@ export default function InscriptionFormShared({ photo: '', }); const [guardians, setGuardians] = useState([]); + const [siblings, setSiblings] = useState([]); const [registrationPaymentModes, setRegistrationPaymentModes] = useState([]); const [tuitionPaymentModes, setTuitionPaymentModes] = useState([]); @@ -75,6 +77,7 @@ export default function InscriptionFormShared({ const [isPage3Valid, setIsPage3Valid] = useState(false); const [isPage4Valid, setIsPage4Valid] = useState(false); const [isPage5Valid, setIsPage5Valid] = useState(false); + const [isPage6Valid, setIsPage6Valid] = useState(false); const [hasInteracted, setHasInteracted] = useState(false); @@ -103,7 +106,7 @@ export default function InscriptionFormShared({ ); // Mettre à jour isPage4Valid en fonction de cette condition - setIsPage4Valid(allSigned); + setIsPage5Valid(allSigned); if (allSigned) { setCurrentTemplateIndex(0); @@ -116,8 +119,8 @@ export default function InscriptionFormShared({ (template) => template.file !== null ); - // Mettre à jour isPage5Valid en fonction de cette condition - setIsPage5Valid(allUploaded); + // Mettre à jour isPage6Valid en fonction de cette condition + setIsPage6Valid(allUploaded); }, [parentFileTemplates]); const handleTemplateSigned = (index) => { @@ -333,7 +336,7 @@ export default function InscriptionFormShared({ .then((response) => { logger.debug('Fichier supprimé avec succès dans la base :', response); - setIsPage5Valid(false); + setIsPage6Valid(false); // Mettre à jour l'état local pour refléter la suppression setUploadedFiles((prev) => @@ -374,6 +377,7 @@ export default function InscriptionFormShared({ student: { ...formData, guardians: guardians, + siblings: siblings, }, establishment: selectedEstablishmentId, status: isSepaPayment ? 8 : 3, @@ -383,8 +387,6 @@ export default function InscriptionFormShared({ registration_payment_plan: formData.registration_payment_plan, }; - console.log('jsonData : ', jsonData); - // Créer un objet FormData const formDataToSend = new FormData(); @@ -411,14 +413,16 @@ export default function InscriptionFormShared({ const stepTitles = { 1: 'Elève', 2: 'Responsables légaux', - 3: 'Modalités de paiement', - 4: 'Formulaires à signer', - 5: 'Pièces à fournir', + 3: 'Frères et soeurs', + 4: 'Modalités de paiement', + 5: 'Formulaires à signer', + 6: 'Pièces à fournir', }; const steps = [ 'Élève', 'Responsable', + 'Fratrie', 'Paiement', 'Formulaires', 'Documents parent', @@ -436,6 +440,8 @@ export default function InscriptionFormShared({ return isPage4Valid; case 5: return isPage5Valid; + case 6: + return isPage6Valid; default: return false; } @@ -464,6 +470,7 @@ export default function InscriptionFormShared({ setFormData={setFormData} guardians={guardians} setGuardians={setGuardians} + setSiblings={setSiblings} errors={errors} setIsPageValid={setIsPage1Valid} hasInteracted={hasInteracted} @@ -481,8 +488,19 @@ export default function InscriptionFormShared({ /> )} - {/* Page 3 : Informations sur les modalités de paiement */} + {/* Étape 3 : Frères et Sœurs */} {currentPage === 3 && ( +