From 1617b132c4f67fdbaf261808a0a9596b7a72a4dc Mon Sep 17 00:00:00 2001 From: N3WT DE COMPET Date: Sat, 26 Apr 2025 10:37:28 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20conflits=20+=20closeModal=20lors=20de=20?= =?UTF-8?q?la=20cr=C3=A9ation=20d'un=20RF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../views/register_form_views.py | 40 ++-- .../app/[locale]/admin/subscriptions/page.js | 224 +++++++++++------- .../validateSubscription/page.js | 5 +- .../Inscription/ValidateSubscription.js | 53 +---- 4 files changed, 178 insertions(+), 144 deletions(-) diff --git a/Back-End/Subscriptions/views/register_form_views.py b/Back-End/Subscriptions/views/register_form_views.py index 2646af3..ab1da49 100644 --- a/Back-End/Subscriptions/views/register_form_views.py +++ b/Back-End/Subscriptions/views/register_form_views.py @@ -261,21 +261,6 @@ class RegisterFormWithIdView(APIView): initial_pdf = f"{base_dir}/Inscription_{registerForm.student.last_name}_{registerForm.student.first_name}.pdf" registerForm.registration_file = util.rfToPDF(registerForm, initial_pdf) registerForm.save() - - # Récupération des fichiers d'inscription - # fileNames = RegistrationSchoolFileTemplate.get_files_from_rf(registerForm.pk) - # if registerForm.registration_file: - # fileNames.insert(0, registerForm.registration_file.path) - - # # Création du fichier PDF Fusionné - # merged_pdf_content = util.merge_files_pdf(fileNames) - - # # Mise à jour du champ registration_file avec le fichier fusionné - # registerForm.registration_file.save( - # f"dossier_complet.pdf", - # File(merged_pdf_content), - # save=True - # ) # Mise à jour de l'automate # Vérification de la présence du fichier SEPA @@ -295,16 +280,35 @@ class RegisterFormWithIdView(APIView): updateStateMachine(registerForm, 'EVENT_REFUSE') util.delete_registration_files(registerForm) elif _status == RegistrationForm.RegistrationFormStatus.RF_SEPA_SENT: + # Vérifier si le paramètre fusion est activé via l'URL + fusion = studentForm_data.get('fusion', False) + if fusion: + # Fusion des documents + # Récupération des fichiers d'inscription + fileNames = RegistrationSchoolFileTemplate.get_files_from_rf(registerForm.pk) + if registerForm.registration_file: + fileNames.insert(0, registerForm.registration_file.path) + + # Création du fichier PDF Fusionné + merged_pdf_content = util.merge_files_pdf(fileNames) + + # Mise à jour du champ registration_file avec le fichier fusionné + registerForm.registration_file.save( + f"dossier_complet.pdf", + File(merged_pdf_content), + save=True + ) + # Sauvegarde du mandat SEPA student = registerForm.student guardian = student.getMainGuardian() email = guardian.profile_role.profile.email errorMessage = mailer.sendMandatSEPA(email, registerForm.establishment.pk) if errorMessage == '': - registerForm.last_update=util.convertToStr(util._now(), '%d-%m-%Y %H:%M') + registerForm.last_update = util.convertToStr(util._now(), '%d-%m-%Y %H:%M') updateStateMachine(registerForm, 'EVENT_SEND_SEPA') - return JsonResponse({"message": f"Le mandat SEPA a bien été envoyé à l'addresse {email}"}, safe=False) - return JsonResponse({"errorMessage":errorMessage}, safe=False, status=status.HTTP_400_BAD_REQUEST) + return JsonResponse({"message": f"Le mandat SEPA a bien été envoyé à l'adresse {email}"}, safe=False) + return JsonResponse({"errorMessage": errorMessage}, safe=False, status=status.HTTP_400_BAD_REQUEST) # Retourner les données mises à jour return JsonResponse(studentForm_serializer.data, safe=False) diff --git a/Front-End/src/app/[locale]/admin/subscriptions/page.js b/Front-End/src/app/[locale]/admin/subscriptions/page.js index 20e88fe..2948470 100644 --- a/Front-End/src/app/[locale]/admin/subscriptions/page.js +++ b/Front-End/src/app/[locale]/admin/subscriptions/page.js @@ -24,7 +24,6 @@ import Modal from '@/components/Modal'; import InscriptionForm from '@/components/Inscription/InscriptionForm'; import AffectationClasseForm from '@/components/AffectationClasseForm'; import { useEstablishment } from '@/context/EstablishmentContext'; -import ValidateSubscription from '@/components/Inscription/ValidateSubscription'; import { PENDING, @@ -56,8 +55,6 @@ import { } from '@/app/actions/schoolAction'; import { - createProfile, - deleteProfile, fetchProfiles, } from '@/app/actions/authAction'; @@ -115,6 +112,9 @@ export default function Page({ params: { locale } }) { const [profiles, setProfiles] = useState([]); const [isOpenAddGuardian, setIsOpenAddGuardian] = useState(false); + const [isFilesModalOpen, setIsFilesModalOpen] = useState(false); + const [selectedRowFiles, setSelectedRowFiles] = useState([]); + const csrfToken = useCsrfToken(); const router = useRouter(); const { selectedEstablishmentId } = useEstablishment(); @@ -141,7 +141,30 @@ export default function Page({ params: { locale } }) { setStudent(eleveSelected); }; - const requestErrorHandler = (err) => { + const openFilesModal = (row) => { + const files = []; + if (row.registration_file) { + files.push({ + name: 'Fichier d\'inscription', + url: `${BASE_URL}${row.registration_file}`, + }); + } + if (row.sepa_file) { + files.push({ + name: 'Mandat SEPA', + url: `${BASE_URL}${row.sepa_file}`, + }); + } + setSelectedRowFiles(files); + setIsFilesModalOpen(true); + }; + + const closeFilesModal = () => { + setIsFilesModalOpen(false); + setSelectedRowFiles([]); + }; + + const requestErrorHandler = (err)=>{ logger.error('Error fetching data:', err); }; @@ -451,6 +474,7 @@ export default function Page({ params: { locale } }) { const createRF = (updatedData) => { logger.debug('createRF updatedData:', updatedData); + const selectedRegistrationFeesIds = updatedData.selectedRegistrationFees.map((feeId) => feeId); const selectedRegistrationDiscountsIds = @@ -538,74 +562,66 @@ export default function Page({ params: { locale } }) { const parent_masters = parentFileMasters.filter((file) => file.groups.includes(selectedFileGroup) ); - const clonePromises = masters - .map((templateMaster, index) => { - return cloneTemplate( - templateMaster.id, - updatedData.guardianEmail, - templateMaster.is_required - ) - .then((clonedDocument) => { - // Sauvegarde des schoolFileTemplates clonés dans la base de données - const cloneData = { - name: `${templateMaster.name}_${updatedData.guardianFirstName}_${updatedData.guardianLastName}`, - 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); - }) - .catch((error) => { - logger.error( - "Erreur lors de l'enregistrement du template:", - error - ); - }); - }) - .catch((error) => { - logger.error('Error during cloning or sending:', error); - }); - }) - .catch((error) => { - logger.error('Error:', error); - }); + const clonePromises = masters.map((templateMaster) => { + return cloneTemplate( + templateMaster.id, + updatedData.guardianEmail, + templateMaster.is_required + ) + .then((clonedDocument) => { + // Sauvegarde des schoolFileTemplates clonés dans la base de données + const cloneData = { + name: `${templateMaster.name}_${updatedData.guardianFirstName}_${updatedData.guardianLastName}`, + 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); + }) + .catch((error) => { + logger.error( + 'Erreur lors de l\'enregistrement du template:', + error + ); + }); + }) + .catch((error) => { + logger.error('Error during cloning or sending:', error); + }); + }); // Créer les parentFileTemplates pour chaque parentMaster - const parentClonePromises = parent_masters.map( - (parentMaster, index) => { - const parentTemplateData = { - master: parentMaster.id, - registration_form: data.student.id, - }; + const parentClonePromises = parent_masters.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) => { - logger.error( - "Erreur lors de l'enregistrement du parent template:", - error - ); - }); - } - ); + return createRegistrationParentFileTemplate( + parentTemplateData, + csrfToken + ) + .then((response) => { + logger.debug( + 'Parent template enregistré avec succès:', + response + ); + }) + .catch((error) => { + logger.error( + 'Erreur lors de l\'enregistrement du parent template:', + error + ); + }); + }); - // Attendre que tous les clones soient créés - Promise.all(clonePromises) + // Attendre que tous les clones (school et parent) soient créés + Promise.all([...clonePromises, ...parentClonePromises]) .then(() => { // Mise à jour immédiate des données setRegistrationFormsDataPending((prevState) => [ @@ -620,7 +636,7 @@ export default function Page({ params: { locale } }) { updatedData.studentFirstName ); } - closeModal(); + closeModal(); // Appeler closeModal ici après que tout soit terminé // Forcer le rechargement complet des données setReloadFetch(true); }) @@ -755,6 +771,14 @@ export default function Page({ params: { locale } }) { }, ], 3: [ + { + icon: ( + + + + ), + onClick: () => openFilesModal(row), + }, { icon: ( @@ -781,6 +805,16 @@ export default function Page({ params: { locale } }) { onClick: () => openModalAssociationEleve(row.student), }, ], + 7: [ + { + icon: ( + + + + ), + onClick: () => openFilesModal(row), + }, + ], default: [ { icon: ( @@ -1132,21 +1166,45 @@ export default function Page({ params: { locale } }) { /> )} {isOpenAddGuardian && ( - ( - - )} - /> - )} + ( + + )} + /> + )} + {isFilesModalOpen && ( + ( + + )} + /> + )} ); } diff --git a/Front-End/src/app/[locale]/admin/subscriptions/validateSubscription/page.js b/Front-End/src/app/[locale]/admin/subscriptions/validateSubscription/page.js index 132395a..1b57098 100644 --- a/Front-End/src/app/[locale]/admin/subscriptions/validateSubscription/page.js +++ b/Front-End/src/app/[locale]/admin/subscriptions/validateSubscription/page.js @@ -23,11 +23,12 @@ export default function Page() { const handleAcceptRF = (data) => { logger.debug('Mise à jour du RF avec les données:', data); - const { status, sepa_file } = data; + const {status, sepa_file, fusionParam} = data const formData = new FormData(); formData.append('status', status); // Ajoute le statut formData.append('sepa_file', sepa_file); // Ajoute le fichier SEPA - + formData.append('fusion', fusionParam); + // Appeler l'API pour mettre à jour le RF sendSEPARegisterForm(studentId, formData, csrfToken) .then((response) => { diff --git a/Front-End/src/components/Inscription/ValidateSubscription.js b/Front-End/src/components/Inscription/ValidateSubscription.js index 44838ed..f16e143 100644 --- a/Front-End/src/components/Inscription/ValidateSubscription.js +++ b/Front-End/src/components/Inscription/ValidateSubscription.js @@ -4,10 +4,7 @@ import Button from '@/components/Button'; import ToggleSwitch from '@/components/ToggleSwitch'; // Import du composant ToggleSwitch import { BASE_URL } from '@/utils/Url'; import { generateToken } from '@/app/actions/registerFileGroupAction'; -import { - fetchSchoolFileTemplatesFromRegistrationFiles, - fetchParentFileTemplatesFromRegistrationFiles, -} from '@/app/actions/subscriptionAction'; +import { fetchSchoolFileTemplatesFromRegistrationFiles, fetchParentFileTemplatesFromRegistrationFiles } from '@/app/actions/subscriptionAction'; import logger from '@/utils/logger'; import { GraduationCap } from 'lucide-react'; import FileUpload from '@/components/FileUpload'; @@ -50,12 +47,7 @@ export default function ValidateSubscription({ setSchoolFileTemplates(data); logger.debug('Fichiers schoolFileTemplates récupérés:', data); }) - .catch((error) => - logger.error( - 'Erreur lors de la récupération des schoolFileTemplates:', - error - ) - ); + .catch((error) => logger.error('Erreur lors de la récupération des schoolFileTemplates:', error)); // Récupérer les fichiers parentFileTemplates pour l'étudiant fetchParentFileTemplatesFromRegistrationFiles(studentId) @@ -63,12 +55,7 @@ export default function ValidateSubscription({ setParentFileTemplates(data); logger.debug('Fichiers parentFileTemplates récupérés:', data); }) - .catch((error) => - logger.error( - 'Erreur lors de la récupération des parentFileTemplates:', - error - ) - ); + .catch((error) => logger.error('Erreur lors de la récupération des parentFileTemplates:', error)); }, [studentId]); const handleAccept = () => { @@ -76,16 +63,16 @@ export default function ValidateSubscription({ logger.error('Aucun fichier sélectionné pour le champ SEPA.'); return; } - + // Ajouter le paramètre fusion dans l'URL const fusionParam = mergeDocuments ? 'true' : 'false'; - + const data = { status: 7, sepa_file: selectedFile, // Utilise le fichier sélectionné depuis l'état - fusionParam: fusionParam, + fusionParam: fusionParam }; - + // Appeler la fonction passée par le parent pour mettre à jour le RF onAccept(data); }; @@ -98,11 +85,7 @@ export default function ValidateSubscription({ const isValidateButtonDisabled = isSepa && !uploadedFileName; const goToNextPage = () => { - const totalPages = - 1 + - schoolFileTemplates.length + - parentFileTemplates.length + - (isSepa ? 1 : 0); + const totalPages = 1 + schoolFileTemplates.length + parentFileTemplates.length + (isSepa ? 1 : 0); if (currentPage < totalPages) { setCurrentPage(currentPage + 1); } @@ -114,11 +97,7 @@ export default function ValidateSubscription({ } }; - const totalPages = - 1 + - schoolFileTemplates.length + - parentFileTemplates.length + - (isSepa ? 1 : 0); + const totalPages = 1 + schoolFileTemplates.length + parentFileTemplates.length + (isSepa ? 1 : 0); const renderContent = () => { if (currentPage === 1) { @@ -135,10 +114,7 @@ export default function ValidateSubscription({ }} /> ); - } else if ( - currentPage > 1 && - currentPage <= 1 + schoolFileTemplates.length - ) { + } else if (currentPage > 1 && currentPage <= 1 + schoolFileTemplates.length) { // Pages des schoolFileTemplates const index = currentPage - 2; // Décalage pour correspondre à l'index du tableau return ( @@ -153,10 +129,7 @@ export default function ValidateSubscription({ }} /> ); - } else if ( - currentPage > 1 + schoolFileTemplates.length && - currentPage <= 1 + schoolFileTemplates.length + parentFileTemplates.length - ) { + } else if (currentPage > 1 + schoolFileTemplates.length && currentPage <= 1 + schoolFileTemplates.length + parentFileTemplates.length) { // Pages des parentFileTemplates const index = currentPage - 2 - schoolFileTemplates.length; // Décalage pour correspondre à l'index du tableau return ( @@ -202,9 +175,7 @@ export default function ValidateSubscription({ {/* Option de fusion des documents (affichée uniquement sur la dernière page) */} {currentPage === totalPages && (
- - Fusionner les documents en un seul fichier PDF - + Fusionner les documents en un seul fichier PDF