feat: Gestion des documents parent

This commit is contained in:
N3WT DE COMPET
2025-04-17 19:06:28 +02:00
parent 7564865d8f
commit 59aee80c2e
15 changed files with 402 additions and 206 deletions

View File

@ -283,8 +283,7 @@ class RegistrationSchoolFileTemplate(models.Model):
####### Parent files templates (par dossier d'inscription) ####### ####### Parent files templates (par dossier d'inscription) #######
class RegistrationParentFileTemplate(models.Model): class RegistrationParentFileTemplate(models.Model):
master = models.ForeignKey(RegistrationSchoolFileMaster, on_delete=models.CASCADE, related_name='parent_file_templates', blank=True) master = models.ForeignKey(RegistrationParentFileMaster, on_delete=models.CASCADE, related_name='parent_file_templates', blank=True)
name = models.CharField(max_length=255, default="")
registration_form = models.ForeignKey(RegistrationForm, on_delete=models.CASCADE, related_name='parent_file_templates', blank=True) registration_form = models.ForeignKey(RegistrationForm, on_delete=models.CASCADE, related_name='parent_file_templates', blank=True)
file = models.FileField(null=True,blank=True, upload_to=registration_file_upload_to) file = models.FileField(null=True,blank=True, upload_to=registration_file_upload_to)

View File

@ -1,5 +1,5 @@
from rest_framework import serializers from rest_framework import serializers
from .models import RegistrationFileGroup, RegistrationForm, Student, Guardian, Sibling, Language, RegistrationSchoolFileMaster, RegistrationSchoolFileTemplate, RegistrationParentFileMaster from .models import RegistrationFileGroup, RegistrationForm, Student, Guardian, Sibling, Language, RegistrationSchoolFileMaster, RegistrationSchoolFileTemplate, RegistrationParentFileMaster, RegistrationParentFileTemplate
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, Profile from Auth.models import ProfileRole, Profile
@ -27,6 +27,7 @@ class RegistrationParentFileMasterSerializer(serializers.ModelSerializer):
class RegistrationSchoolFileTemplateSerializer(serializers.ModelSerializer): class RegistrationSchoolFileTemplateSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False) id = serializers.IntegerField(required=False)
file_url = serializers.SerializerMethodField() file_url = serializers.SerializerMethodField()
class Meta: class Meta:
model = RegistrationSchoolFileTemplate model = RegistrationSchoolFileTemplate
fields = '__all__' fields = '__all__'
@ -38,8 +39,10 @@ class RegistrationSchoolFileTemplateSerializer(serializers.ModelSerializer):
class RegistrationParentFileTemplateSerializer(serializers.ModelSerializer): class RegistrationParentFileTemplateSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False) id = serializers.IntegerField(required=False)
file = serializers.SerializerMethodField() file = serializers.SerializerMethodField()
master_name = serializers.CharField(source='master.name', read_only=True)
master_description = serializers.CharField(source='master.description', read_only=True)
class Meta: class Meta:
model = RegistrationParentFileMaster model = RegistrationParentFileTemplate
fields = '__all__' fields = '__all__'
def get_file(self, obj): def get_file(self, obj):

View File

@ -7,7 +7,17 @@ from .views import RegisterFormView, RegisterFormWithIdView, send, resend, archi
# SubClasses # SubClasses
from .views import StudentView, GuardianView, ChildrenListView, StudentListView, DissociateGuardianView from .views import StudentView, GuardianView, ChildrenListView, StudentListView, DissociateGuardianView
# Files # Files
from .views import RegistrationSchoolFileMasterView, RegistrationSchoolFileMasterSimpleView, RegistrationSchoolFileTemplateView, RegistrationSchoolFileTemplateSimpleView, RegistrationParentFileMasterSimpleView, RegistrationParentFileMasterView from .views import (
RegistrationSchoolFileMasterView,
RegistrationSchoolFileMasterSimpleView,
RegistrationSchoolFileTemplateView,
RegistrationSchoolFileTemplateSimpleView,
RegistrationParentFileMasterSimpleView,
RegistrationParentFileMasterView,
RegistrationParentFileTemplateSimpleView,
RegistrationParentFileTemplateView
)
from .views import RegistrationFileGroupView, RegistrationFileGroupSimpleView, get_registration_files_by_group from .views import RegistrationFileGroupView, RegistrationFileGroupSimpleView, get_registration_files_by_group
from .views import registration_file_views, get_school_file_templates_by_rf, get_parent_file_templates_by_rf from .views import registration_file_views, get_school_file_templates_by_rf, get_parent_file_templates_by_rf
@ -17,7 +27,7 @@ urlpatterns = [
re_path(r'^registerForms/(?P<id>[0-9]+)/send$', send, name="send"), re_path(r'^registerForms/(?P<id>[0-9]+)/send$', send, name="send"),
re_path(r'^registerForms/(?P<id>[0-9]+)$', RegisterFormWithIdView.as_view(), name="registerForm"), re_path(r'^registerForms/(?P<id>[0-9]+)$', RegisterFormWithIdView.as_view(), name="registerForm"),
re_path(r'^registerForms/(?P<id>[0-9]+)/school_file_templates$', get_school_file_templates_by_rf, name="get_school_file_templates_by_rf"), re_path(r'^registerForms/(?P<id>[0-9]+)/school_file_templates$', get_school_file_templates_by_rf, name="get_school_file_templates_by_rf"),
re_path(r'^registerForms/(?P<id>[0-9]+)/parent_file_templatess$', get_parent_file_templates_by_rf, name="get_parent_file_templates_by_rf"), re_path(r'^registerForms/(?P<id>[0-9]+)/parent_file_templates$', get_parent_file_templates_by_rf, name="get_parent_file_templates_by_rf"),
re_path(r'^registerForms$', RegisterFormView.as_view(), name="registerForms"), re_path(r'^registerForms$', RegisterFormView.as_view(), name="registerForms"),
# Page INSCRIPTION - Liste des élèves # Page INSCRIPTION - Liste des élèves
@ -43,6 +53,9 @@ urlpatterns = [
re_path(r'^registrationSchoolFileTemplates/(?P<id>[0-9]+)$', RegistrationSchoolFileTemplateSimpleView.as_view(), name='registrationSchoolFileTemplates'), re_path(r'^registrationSchoolFileTemplates/(?P<id>[0-9]+)$', RegistrationSchoolFileTemplateSimpleView.as_view(), name='registrationSchoolFileTemplates'),
re_path(r'^registrationSchoolFileTemplates$', RegistrationSchoolFileTemplateView.as_view(), name="registrationSchoolFileTemplates"), re_path(r'^registrationSchoolFileTemplates$', RegistrationSchoolFileTemplateView.as_view(), name="registrationSchoolFileTemplates"),
re_path(r'^registrationParentFileTemplates/(?P<id>[0-9]+)$', RegistrationParentFileTemplateSimpleView.as_view(), name='registrationParentFileTemplates'),
re_path(r'^registrationParentFileTemplates$', RegistrationParentFileTemplateView.as_view(), name="registrationSchoolFileTregistrationParentFileTemplatesemplates"),
re_path(r'^students/(?P<student_id>[0-9]+)/guardians/(?P<guardian_id>[0-9]+)/dissociate', DissociateGuardianView.as_view(), name='dissociate-guardian'), re_path(r'^students/(?P<student_id>[0-9]+)/guardians/(?P<guardian_id>[0-9]+)/dissociate', DissociateGuardianView.as_view(), name='dissociate-guardian'),
] ]

View File

@ -1,5 +1,14 @@
from .register_form_views import RegisterFormView, RegisterFormWithIdView, send, resend, archive, get_school_file_templates_by_rf, get_parent_file_templates_by_rf from .register_form_views import RegisterFormView, RegisterFormWithIdView, send, resend, archive, get_school_file_templates_by_rf, get_parent_file_templates_by_rf
from .registration_file_views import RegistrationSchoolFileMasterView, RegistrationSchoolFileMasterSimpleView, RegistrationSchoolFileTemplateView, RegistrationSchoolFileTemplateSimpleView, RegistrationParentFileMasterView, RegistrationParentFileMasterSimpleView from .registration_file_views import (
RegistrationSchoolFileMasterView,
RegistrationSchoolFileMasterSimpleView,
RegistrationSchoolFileTemplateView,
RegistrationSchoolFileTemplateSimpleView,
RegistrationParentFileMasterView,
RegistrationParentFileMasterSimpleView,
RegistrationParentFileTemplateSimpleView,
RegistrationParentFileTemplateView
)
from .registration_file_group_views import RegistrationFileGroupView, RegistrationFileGroupSimpleView, get_registration_files_by_group from .registration_file_group_views import RegistrationFileGroupView, RegistrationFileGroupSimpleView, get_registration_files_by_group
from .student_views import StudentView, StudentListView, ChildrenListView from .student_views import StudentView, StudentListView, ChildrenListView
from .guardian_views import GuardianView, DissociateGuardianView from .guardian_views import GuardianView, DissociateGuardianView
@ -16,6 +25,8 @@ __all__ = [
'RegistrationParentFileMasterView', 'RegistrationParentFileMasterView',
'RegistrationSchoolFileMasterView', 'RegistrationSchoolFileMasterView',
'RegistrationSchoolFileMasterSimpleView', 'RegistrationSchoolFileMasterSimpleView',
'RegistrationParentFileTemplateSimpleView',
'RegistrationParentFileTemplateView',
'RegistrationFileGroupView', 'RegistrationFileGroupView',
'RegistrationFileGroupSimpleView', 'RegistrationFileGroupSimpleView',
'get_registration_files_by_group', 'get_registration_files_by_group',

View File

@ -14,9 +14,9 @@ from django.core.files import File
import Subscriptions.mailManager as mailer import Subscriptions.mailManager as mailer
import Subscriptions.util as util import Subscriptions.util as util
from Subscriptions.serializers import RegistrationFormSerializer, RegistrationSchoolFileTemplateSerializer, RegistrationParentFileMasterSerializer from Subscriptions.serializers import RegistrationFormSerializer, RegistrationSchoolFileTemplateSerializer, RegistrationParentFileTemplateSerializer
from Subscriptions.pagination import CustomPagination from Subscriptions.pagination import CustomPagination
from Subscriptions.models import Student, Guardian, RegistrationForm, RegistrationSchoolFileTemplate, RegistrationFileGroup, RegistrationParentFileMaster from Subscriptions.models import Student, Guardian, RegistrationForm, RegistrationSchoolFileTemplate, RegistrationFileGroup, RegistrationParentFileTemplate
from Subscriptions.automate import updateStateMachine from Subscriptions.automate import updateStateMachine
from N3wtSchool import settings, bdd from N3wtSchool import settings, bdd
@ -441,12 +441,12 @@ def get_school_file_templates_by_rf(request, id):
def get_parent_file_templates_by_rf(request, id): def get_parent_file_templates_by_rf(request, id):
try: try:
# Récupérer les pièces à fournir associés au RegistrationForm donné # Récupérer les pièces à fournir associés au RegistrationForm donné
parent_files = RegistrationParentFileMaster.objects.filter(registration_form=id) parent_files = RegistrationParentFileTemplate.objects.filter(registration_form=id)
# Sérialiser les données # Sérialiser les données
serializer = RegistrationParentFileMasterSerializer(parent_files, many=True) serializer = RegistrationParentFileTemplateSerializer(parent_files, many=True)
# Retourner les données sérialisées # Retourner les données sérialisées
return JsonResponse(serializer.data, safe=False) return JsonResponse(serializer.data, safe=False)
except RegistrationSchoolFileTemplate.DoesNotExist: except RegistrationParentFileTemplate.DoesNotExist:
return JsonResponse({'error': 'Aucune pièce à fournir trouvée pour ce dossier d\'inscription'}, status=status.HTTP_404_NOT_FOUND) return JsonResponse({'error': 'Aucune pièce à fournir trouvée pour ce dossier d\'inscription'}, status=status.HTTP_404_NOT_FOUND)

View File

@ -6,8 +6,8 @@ from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework import status from rest_framework import status
from Subscriptions.serializers import RegistrationSchoolFileMasterSerializer, RegistrationSchoolFileTemplateSerializer, RegistrationParentFileMasterSerializer from Subscriptions.serializers import RegistrationSchoolFileMasterSerializer, RegistrationSchoolFileTemplateSerializer, RegistrationParentFileMasterSerializer, RegistrationParentFileTemplateSerializer
from Subscriptions.models import RegistrationSchoolFileMaster, RegistrationSchoolFileTemplate, RegistrationParentFileMaster from Subscriptions.models import RegistrationSchoolFileMaster, RegistrationSchoolFileTemplate, RegistrationParentFileMaster, RegistrationParentFileTemplate
from N3wtSchool import bdd from N3wtSchool import bdd
class RegistrationSchoolFileMasterView(APIView): class RegistrationSchoolFileMasterView(APIView):
@ -183,7 +183,6 @@ class RegistrationParentFileMasterView(APIView):
return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class RegistrationParentFileMasterSimpleView(APIView): class RegistrationParentFileMasterSimpleView(APIView):
@swagger_auto_schema( @swagger_auto_schema(
operation_description="Récupère un fichier parent spécifique", operation_description="Récupère un fichier parent spécifique",
@ -232,3 +231,77 @@ class RegistrationParentFileMasterSimpleView(APIView):
return JsonResponse({'message': 'La suppression du fichier parent a été effectuée avec succès'}, safe=False, status=status.HTTP_204_NO_CONTENT) return JsonResponse({'message': 'La suppression du fichier parent a été effectuée avec succès'}, safe=False, status=status.HTTP_204_NO_CONTENT)
else: else:
return JsonResponse({'erreur': 'Le fichier parent n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND) return JsonResponse({'erreur': 'Le fichier parent n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
class RegistrationParentFileTemplateView(APIView):
@swagger_auto_schema(
operation_description="Récupère tous les templates d'inscription",
responses={200: RegistrationParentFileTemplateSerializer(many=True)}
)
def get(self, request):
templates = RegistrationParentFileTemplate.objects.all()
serializer = RegistrationParentFileTemplateSerializer(templates, many=True)
return Response(serializer.data)
@swagger_auto_schema(
operation_description="Crée un nouveau template d'inscription",
request_body=RegistrationParentFileTemplateSerializer,
responses={
201: RegistrationParentFileTemplateSerializer,
400: "Données invalides"
}
)
def post(self, request):
serializer = RegistrationParentFileTemplateSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class RegistrationParentFileTemplateSimpleView(APIView):
@swagger_auto_schema(
operation_description="Récupère un template d'inscription spécifique",
responses={
200: RegistrationParentFileTemplateSerializer,
404: "Template non trouvé"
}
)
def get(self, request, id):
template = bdd.getObject(_objectName=RegistrationParentFileTemplate, _columnName='id', _value=id)
if template is None:
return JsonResponse({"errorMessage":'Le template d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
serializer = RegistrationParentFileTemplateSerializer(template)
return JsonResponse(serializer.data, safe=False)
@swagger_auto_schema(
operation_description="Met à jour un template d'inscription existant",
request_body=RegistrationParentFileTemplateSerializer,
responses={
200: RegistrationParentFileTemplateSerializer,
400: "Données invalides",
404: "Template non trouvé"
}
)
def put(self, request, id):
template = bdd.getObject(_objectName=RegistrationParentFileTemplate, _columnName='id', _value=id)
if template is None:
return JsonResponse({'erreur': 'Le template d\'inscription n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
serializer = RegistrationParentFileTemplateSerializer(template, data=request.data)
if serializer.is_valid():
serializer.save()
return Response({'message': 'Template mis à jour avec succès', 'data': serializer.data}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@swagger_auto_schema(
operation_description="Supprime un template d'inscription",
responses={
204: "Suppression réussie",
404: "Template non trouvé"
}
)
def delete(self, request, id):
template = bdd.getObject(_objectName=RegistrationParentFileTemplate, _columnName='id', _value=id)
if template is not None:
template.delete()
return JsonResponse({'message': 'La suppression du template a été effectuée avec succès'}, safe=False, status=status.HTTP_204_NO_CONTENT)
else:
return JsonResponse({'erreur': 'Le template n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)

View File

@ -29,7 +29,9 @@ import {
import { import {
fetchRegistrationSchoolFileMasters, fetchRegistrationSchoolFileMasters,
createRegistrationTemplates, fetchRegistrationParentFileMasters,
createRegistrationSchoolFileTemplate,
createRegistrationParentFileTemplate,
fetchRegistrationFileGroups, fetchRegistrationFileGroups,
cloneTemplate cloneTemplate
} from "@/app/actions/registerFileGroupAction"; } from "@/app/actions/registerFileGroupAction";
@ -73,6 +75,7 @@ export default function Page({ params: { locale } }) {
const [itemsPerPage, setItemsPerPage] = useState(10); // Définir le nombre d'éléments par page const [itemsPerPage, setItemsPerPage] = useState(10); // Définir le nombre d'éléments par page
const [schoolFileMasters, setSchoolFileMasters] = useState([]); const [schoolFileMasters, setSchoolFileMasters] = useState([]);
const [parentFileMasters, setParentFileMasters] = useState([]);
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [isOpenAffectationClasse, setIsOpenAffectationClasse] = useState(false); const [isOpenAffectationClasse, setIsOpenAffectationClasse] = useState(false);
const [student, setStudent] = useState(''); const [student, setStudent] = useState('');
@ -220,6 +223,13 @@ useEffect(() => {
.catch(err => { .catch(err => {
logger.debug(err.message); logger.debug(err.message);
}), }),
fetchRegistrationParentFileMasters()
.then(data => {
setParentFileMasters(data);
})
.catch(err => {
logger.debug(err.message);
}),
fetchRegistrationDiscounts(selectedEstablishmentId) fetchRegistrationDiscounts(selectedEstablishmentId)
.then(data => { .then(data => {
setRegistrationDiscounts(data); setRegistrationDiscounts(data);
@ -462,6 +472,7 @@ useEffect(()=>{
.then(data => { .then(data => {
// Cloner les schoolFileTemplates pour chaque templateMaster du fileGroup // Cloner les schoolFileTemplates pour chaque templateMaster du fileGroup
const masters = schoolFileMasters.filter(file => file.groups.includes(selectedFileGroup)); const masters = schoolFileMasters.filter(file => file.groups.includes(selectedFileGroup));
const parent_masters = parentFileMasters.filter(file => file.groups.includes(selectedFileGroup));
const clonePromises = masters.map((templateMaster, index) => { const clonePromises = masters.map((templateMaster, index) => {
return cloneTemplate(templateMaster.id, updatedData.guardianEmail, templateMaster.is_required) return cloneTemplate(templateMaster.id, updatedData.guardianEmail, templateMaster.is_required)
.then(clonedDocument => { .then(clonedDocument => {
@ -474,7 +485,7 @@ useEffect(()=>{
registration_form: data.student.id registration_form: data.student.id
}; };
return createRegistrationTemplates(cloneData, csrfToken) return createRegistrationSchoolFileTemplate(cloneData, csrfToken)
.then(response => { .then(response => {
logger.debug('Template enregistré avec succès:', response); logger.debug('Template enregistré avec succès:', response);
}) })
@ -487,6 +498,22 @@ useEffect(()=>{
}); });
}); });
// Créer les parentFileTemplates pour chaque parentMaster
const parentClonePromises = parent_masters.map((parentMaster, index) => {
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);
});
});
// Attendre que tous les clones soient créés // Attendre que tous les clones soient créés
Promise.all(clonePromises) Promise.all(clonePromises)
.then(() => { .then(() => {

View File

@ -1,7 +1,8 @@
import { BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL, import { BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL,
BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL, BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL,
BE_SUBSCRIPTION_REGISTRATIONSCHOOL_FILE_MASTERS_URL, BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL,
BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL, BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL,
BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_TEMPLATES_URL,
FE_API_DOCUSEAL_CLONE_URL, FE_API_DOCUSEAL_CLONE_URL,
FE_API_DOCUSEAL_DOWNLOAD_URL, FE_API_DOCUSEAL_DOWNLOAD_URL,
FE_API_DOCUSEAL_GENERATE_TOKEN FE_API_DOCUSEAL_GENERATE_TOKEN
@ -17,7 +18,9 @@ const requestResponseHandler = async (response) => {
const error = new Error(body?.errorMessage || "Une erreur est survenue"); const error = new Error(body?.errorMessage || "Une erreur est survenue");
error.details = body; error.details = body;
throw error; throw error;
} };
// FETCH requests
export async function fetchRegistrationFileGroups(establishment) { export async function fetchRegistrationFileGroups(establishment) {
const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}?establishment_id=${establishment}`, { const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}?establishment_id=${establishment}`, {
@ -29,58 +32,11 @@ export async function fetchRegistrationFileGroups(establishment) {
if (!response.ok) { if (!response.ok) {
throw new Error('Failed to fetch file groups'); throw new Error('Failed to fetch file groups');
} }
return response.json();
}
export async function createRegistrationFileGroup(groupData, csrfToken) {
const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
body: JSON.stringify(groupData),
credentials: 'include'
});
if (!response.ok) {
throw new Error('Failed to create file group');
}
return response.json();
}
export async function deleteRegistrationFileGroup(groupId, csrfToken) {
const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}`, {
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include'
});
return response;
}
export const editRegistrationFileGroup = async (groupId, groupData, csrfToken) => {
const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
body: JSON.stringify(groupData),
});
if (!response.ok) {
throw new Error('Erreur lors de la modification du groupe');
}
return response.json(); return response.json();
}; };
export const fetchRegistrationFileFromGroup = async (groupId) => { export const fetchRegistrationFileFromGroup = async (groupId) => {
const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}/schoolFileTemplates`, { const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}/school_file_templates`, {
credentials: 'include', credentials: 'include',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
@ -90,7 +46,24 @@ export const fetchRegistrationFileFromGroup = async (groupId) => {
throw new Error('Erreur lors de la récupération des fichiers associés au groupe'); throw new Error('Erreur lors de la récupération des fichiers associés au groupe');
} }
return response.json(); return response.json();
};
export const fetchRegistrationSchoolFileMasters = (id = null) => {
let url = `${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL}`;
if(id){
url = `${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL}/${id}`;
} }
const request = new Request(
`${url}`,
{
method:'GET',
headers: {
'Content-Type':'application/json'
},
}
);
return fetch(request).then(requestResponseHandler)
};
export const fetchRegistrationParentFileMasters = (id = null) => { export const fetchRegistrationParentFileMasters = (id = null) => {
let url = `${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}` let url = `${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}`
@ -109,43 +82,6 @@ export const fetchRegistrationParentFileMasters = (id = null) => {
return fetch(request).then(requestResponseHandler) return fetch(request).then(requestResponseHandler)
}; };
export const createRegistrationParentFileMaster = (data,csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}`, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'X-CSRFToken': csrfToken,
'Content-Type': 'application/json',
},
credentials: 'include',
})
.then(requestResponseHandler)
}
export const editRegistrationParentFileMaster = (id, data, csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}/${id}`, {
method: 'PUT',
body: JSON.stringify(data),
headers: {
'X-CSRFToken': csrfToken,
'Content-Type': 'application/json',
},
credentials: 'include',
})
.then(requestResponseHandler)
}
export const deleteRegistrationParentFileMaster = (id, csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}/${id}`, {
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
}
export const fetchRegistrationSchoolFileTemplates = (id = null) => { export const fetchRegistrationSchoolFileTemplates = (id = null) => {
let url = `${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}` let url = `${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}`
if (id) { if (id) {
@ -163,20 +99,53 @@ export const fetchRegistrationSchoolFileTemplates = (id = null) => {
return fetch(request).then(requestResponseHandler) return fetch(request).then(requestResponseHandler)
}; };
export const editRegistrationTemplates = (fileId, data, csrfToken) => { // CREATE requests
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}/${fileId}`, {
method: 'PUT', export async function createRegistrationFileGroup(groupData, csrfToken) {
body: data, const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
body: JSON.stringify(groupData),
credentials: 'include'
});
if (!response.ok) {
throw new Error('Failed to create file group');
}
return response.json();
};
export const createRegistrationSchoolFileMaster = (data,csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL}`, {
method: 'POST',
body: JSON.stringify(data),
headers: { headers: {
'X-CSRFToken': csrfToken, 'X-CSRFToken': csrfToken,
'Content-Type':'application/json'
}, },
credentials: 'include', credentials: 'include',
}) })
.then(requestResponseHandler) .then(requestResponseHandler)
} };
export const createRegistrationTemplates = (data,csrfToken) => { export const createRegistrationParentFileMaster = (data,csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}`, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'X-CSRFToken': csrfToken,
'Content-Type': 'application/json',
},
credentials: 'include',
})
.then(requestResponseHandler)
};
export const createRegistrationSchoolFileTemplate = (data,csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}`, { return fetch(`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}`, {
method: 'POST', method: 'POST',
body: JSON.stringify(data), body: JSON.stringify(data),
@ -187,61 +156,43 @@ export const createRegistrationTemplates = (data,csrfToken) => {
credentials: 'include', credentials: 'include',
}) })
.then(requestResponseHandler) .then(requestResponseHandler)
}
export const deleteRegistrationTemplates = (fileId,csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}/${fileId}`, {
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
}
export const fetchRegistrationSchoolFileMasters = (id = null) => {
let url = `${BE_SUBSCRIPTION_REGISTRATIONSCHOOL_FILE_MASTERS_URL}`;
if(id){
url = `${BE_SUBSCRIPTION_REGISTRATIONSCHOOL_FILE_MASTERS_URL}/${id}`;
}
const request = new Request(
`${url}`,
{
method:'GET',
headers: {
'Content-Type':'application/json'
},
}
);
return fetch(request).then(requestResponseHandler)
}; };
export const createRegistrationSchoolFileMaster = (data,csrfToken) => { export const createRegistrationParentFileTemplate = (data,csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATIONSCHOOL_FILE_MASTERS_URL}`, { return fetch(`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_TEMPLATES_URL}`, {
method: 'POST', method: 'POST',
body: JSON.stringify(data), body: JSON.stringify(data),
headers: { headers: {
'X-CSRFToken': csrfToken, 'X-CSRFToken': csrfToken,
'Content-Type':'application/json' 'Content-Type': 'application/json',
}, },
credentials: 'include', credentials: 'include',
}) })
.then(requestResponseHandler) .then(requestResponseHandler)
} };
export const deleteRegistrationSchoolFileMaster = (fileId,csrfToken) => { // EDIT requests
return fetch(`${BE_SUBSCRIPTION_REGISTRATIONSCHOOL_FILE_MASTERS_URL}/${fileId}`, {
method: 'DELETE', export const editRegistrationFileGroup = async (groupId, groupData, csrfToken) => {
const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}`, {
method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken, 'X-CSRFToken': csrfToken,
}, },
credentials: 'include', body: JSON.stringify(groupData),
}) });
if (!response.ok) {
throw new Error('Erreur lors de la modification du groupe');
} }
return response.json();
};
export const editRegistrationSchoolFileMaster = (fileId, data, csrfToken) => { export const editRegistrationSchoolFileMaster = (fileId, data, csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATIONSCHOOL_FILE_MASTERS_URL}/${fileId}`, { return fetch(`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL}/${fileId}`, {
method: 'PUT', method: 'PUT',
body: JSON.stringify(data), body: JSON.stringify(data),
headers: { headers: {
@ -251,7 +202,78 @@ export const editRegistrationSchoolFileMaster = (fileId, data, csrfToken) => {
credentials: 'include', credentials: 'include',
}) })
.then(requestResponseHandler) .then(requestResponseHandler)
} };
export const editRegistrationParentFileMaster = (id, data, csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}/${id}`, {
method: 'PUT',
body: JSON.stringify(data),
headers: {
'X-CSRFToken': csrfToken,
'Content-Type': 'application/json',
},
credentials: 'include',
})
.then(requestResponseHandler)
};
export const editRegistrationSchoolFileTemplates = (fileId, data, csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}/${fileId}`, {
method: 'PUT',
body: data,
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
.then(requestResponseHandler)
};
// DELETE requests
export async function deleteRegistrationFileGroup(groupId, csrfToken) {
const response = await fetch(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}`, {
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include'
});
return response;
};
export const deleteRegistrationSchoolFileMaster = (fileId,csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL}/${fileId}`, {
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
};
export const deleteRegistrationParentFileMaster = (id, csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}/${id}`, {
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
};
export const deleteRegistrationSchoolFileTemplates = (fileId,csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}/${fileId}`, {
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
};
// API requests
export const cloneTemplate = (templateId, email, is_required) => { export const cloneTemplate = (templateId, email, is_required) => {
return fetch(`${FE_API_DOCUSEAL_CLONE_URL}`, { return fetch(`${FE_API_DOCUSEAL_CLONE_URL}`, {
@ -266,7 +288,7 @@ export const cloneTemplate = (templateId, email, is_required) => {
}) })
}) })
.then(requestResponseHandler) .then(requestResponseHandler)
} };
export const downloadTemplate = (slug) => { export const downloadTemplate = (slug) => {
return fetch(`${FE_API_DOCUSEAL_DOWNLOAD_URL}/${slug}`, { return fetch(`${FE_API_DOCUSEAL_DOWNLOAD_URL}/${slug}`, {
@ -276,7 +298,7 @@ export const downloadTemplate = (slug) => {
} }
}) })
.then(requestResponseHandler) .then(requestResponseHandler)
} };
export const generateToken = (email, id = null) => { export const generateToken = (email, id = null) => {
return fetch(`${FE_API_DOCUSEAL_GENERATE_TOKEN}`, { return fetch(`${FE_API_DOCUSEAL_GENERATE_TOKEN}`, {

View File

@ -162,7 +162,20 @@ export const fetchSchoolFileTemplatesFromRegistrationFiles = async (id) => {
throw new Error('Erreur lors de la récupération des fichiers associés au groupe'); throw new Error('Erreur lors de la récupération des fichiers associés au groupe');
} }
return response.json(); return response.json();
};
export const fetchParentFileTemplatesFromRegistrationFiles = async (id) => {
const response = await fetch(`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/parent_file_templates`, {
credentials: 'include',
headers: {
'Accept': 'application/json',
} }
});
if (!response.ok) {
throw new Error('Erreur lors de la récupération des fichiers associés au groupe');
}
return response.json();
};
export const dissociateGuardian = async (studentId, guardianId) => { export const dissociateGuardian = async (studentId, guardianId) => {
const response = await fetch(`${BE_SUBSCRIPTION_STUDENTS_URL}/${studentId}/guardians/${guardianId}/dissociate`, { const response = await fetch(`${BE_SUBSCRIPTION_STUDENTS_URL}/${studentId}/guardians/${guardianId}/dissociate`, {

View File

@ -1,12 +1,12 @@
import React from 'react'; import React from 'react';
import Table from '@/components/Table'; import Table from '@/components/Table';
export default function FilesToUpload({ fileTemplates, columns }) { export default function FilesToUpload({ parentFileTemplates, columns }) {
return ( return (
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200"> <div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
<h2 className="text-xl font-bold mb-4 text-gray-800">Fichiers à uploader</h2> <h2 className="text-xl font-bold mb-4 text-gray-800">Fichiers à uploader</h2>
<Table <Table
data={fileTemplates} data={parentFileTemplates}
columns={columns} columns={columns}
itemsPerPage={5} itemsPerPage={5}
currentPage={1} currentPage={1}

View File

@ -3,11 +3,11 @@ import React, { useState, useEffect } from 'react';
import Loader from '@/components/Loader'; import Loader from '@/components/Loader';
import Button from '@/components/Button'; import Button from '@/components/Button';
import DjangoCSRFToken from '@/components/DjangoCSRFToken'; import DjangoCSRFToken from '@/components/DjangoCSRFToken';
import { fetchRegisterForm, fetchSchoolFileTemplatesFromRegistrationFiles } from '@/app/actions/subscriptionAction'; import { fetchRegisterForm, fetchSchoolFileTemplatesFromRegistrationFiles, fetchParentFileTemplatesFromRegistrationFiles } from '@/app/actions/subscriptionAction';
import { downloadTemplate, import { downloadTemplate,
createRegistrationTemplates, createRegistrationSchoolFileTemplate,
editRegistrationTemplates, editRegistrationSchoolFileTemplates,
deleteRegistrationTemplates deleteRegistrationSchoolFileTemplates
} from '@/app/actions/registerFileGroupAction'; } from '@/app/actions/registerFileGroupAction';
import { import {
fetchRegistrationPaymentModes, fetchRegistrationPaymentModes,
@ -63,7 +63,8 @@ export default function InscriptionFormShared({
// États pour la gestion des fichiers // États pour la gestion des fichiers
const [uploadedFiles, setUploadedFiles] = useState([]); const [uploadedFiles, setUploadedFiles] = useState([]);
const [fileTemplates, setFileTemplates] = useState([]); const [schoolFileTemplates, setSchoolFileTemplates] = useState([]);
const [parentFileTemplates, setParentFileTemplates] = useState([]);
const [fileGroup, setFileGroup] = useState(null); const [fileGroup, setFileGroup] = useState(null);
const [fileName, setFileName] = useState(""); const [fileName, setFileName] = useState("");
const [file, setFile] = useState(""); const [file, setFile] = useState("");
@ -113,11 +114,13 @@ export default function InscriptionFormShared({
useEffect(() => { useEffect(() => {
fetchSchoolFileTemplatesFromRegistrationFiles(studentId).then((data) => { fetchSchoolFileTemplatesFromRegistrationFiles(studentId).then((data) => {
setFileTemplates(data); setSchoolFileTemplates(data);
})
fetchParentFileTemplatesFromRegistrationFiles(studentId).then((data) => {
setParentFileTemplates(data);
}) })
}, []);
useEffect(() => {
if (selectedEstablishmentId) { if (selectedEstablishmentId) {
// Fetch data for registration payment modes // Fetch data for registration payment modes
handleRegistrationPaymentModes(); handleRegistrationPaymentModes();
@ -164,7 +167,7 @@ export default function InscriptionFormShared({
data.append('register_form', formData.id); data.append('register_form', formData.id);
try { try {
const response = await createRegistrationTemplates(data, csrfToken); const response = await createRegistrationSchoolFileTemplate(data, csrfToken);
if (response) { if (response) {
setUploadedFiles(prev => { setUploadedFiles(prev => {
const newFiles = prev.filter(f => parseInt(f.template) !== currentTemplateId); const newFiles = prev.filter(f => parseInt(f.template) !== currentTemplateId);
@ -205,7 +208,7 @@ export default function InscriptionFormShared({
if (!fileToDelete) return; if (!fileToDelete) return;
try { try {
await deleteRegistrationTemplates(fileToDelete.id, csrfToken); await deleteRegistrationSchoolFileTemplates(fileToDelete.id, csrfToken);
setUploadedFiles(prev => prev.filter(f => parseInt(f.template) !== templateId)); setUploadedFiles(prev => prev.filter(f => parseInt(f.template) !== templateId));
} catch (error) { } catch (error) {
logger.error('Error deleting file:', error); logger.error('Error deleting file:', error);
@ -249,12 +252,10 @@ export default function InscriptionFormShared({
setCurrentPage(currentPage - 1); setCurrentPage(currentPage - 1);
}; };
const requiredFileTemplates = fileTemplates;
// Configuration des colonnes pour le tableau des fichiers // Configuration des colonnes pour le tableau des fichiers
const columns = [ const columns = [
{ name: 'Nom du fichier', transform: (row) => row.name }, { name: 'Nom du fichier', transform: (row) => row.master_name },
{ name: 'Fichier à Remplir', transform: (row) => row.is_required ? 'Oui' : 'Non' }, { name: 'Description du fichier', transform: (row) => row.master_description },
{ name: 'Fichier de référence', transform: (row) => row.file && <div className="flex items-center justify-center gap-2"> <a href={`${BASE_URL}${row.file}`} target='_blank' className="text-blue-500 hover:text-blue-700"> { name: 'Fichier de référence', transform: (row) => row.file && <div className="flex items-center justify-center gap-2"> <a href={`${BASE_URL}${row.file}`} target='_blank' className="text-blue-500 hover:text-blue-700">
<Download size={16} /> <Download size={16} />
</a> </div>}, </a> </div>},
@ -328,34 +329,34 @@ export default function InscriptionFormShared({
)} )}
{/* Pages suivantes : Section Fichiers d'inscription */} {/* Pages suivantes : Section Fichiers d'inscription */}
{currentPage > 1 && currentPage <= requiredFileTemplates.length + 1 && ( {currentPage > 1 && currentPage <= schoolFileTemplates.length + 1 && (
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200"> <div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
{/* Titre du document */} {/* Titre du document */}
<div className="mb-4"> <div className="mb-4">
<h2 className="text-lg font-semibold text-gray-800"> <h2 className="text-lg font-semibold text-gray-800">
{requiredFileTemplates[currentPage - 2].name || "Document sans nom"} {schoolFileTemplates[currentPage - 2].name || "Document sans nom"}
</h2> </h2>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
{requiredFileTemplates[currentPage - 2].description || "Aucune description disponible pour ce document."} {schoolFileTemplates[currentPage - 2].description || "Aucune description disponible pour ce document."}
</p> </p>
</div> </div>
{/* Affichage du formulaire ou du document */} {/* Affichage du formulaire ou du document */}
{requiredFileTemplates[currentPage - 2].file === null ? ( {schoolFileTemplates[currentPage - 2].file === null ? (
<DocusealForm <DocusealForm
id="docusealForm" id="docusealForm"
src={"https://docuseal.com/s/" + requiredFileTemplates[currentPage - 2].slug} src={"https://docuseal.com/s/" + schoolFileTemplates[currentPage - 2].slug}
withDownloadButton={false} withDownloadButton={false}
onComplete={() => { onComplete={() => {
downloadTemplate(requiredFileTemplates[currentPage - 2].slug) downloadTemplate(schoolFileTemplates[currentPage - 2].slug)
.then((data) => fetch(data)) .then((data) => fetch(data))
.then((response) => response.blob()) .then((response) => response.blob())
.then((blob) => { .then((blob) => {
const file = new File([blob], `${requiredFileTemplates[currentPage - 2].name}.pdf`, { type: blob.type }); const file = new File([blob], `${schoolFileTemplates[currentPage - 2].name}.pdf`, { type: blob.type });
const updateData = new FormData(); const updateData = new FormData();
updateData.append('file', file); updateData.append('file', file);
return editRegistrationTemplates(requiredFileTemplates[currentPage - 2].id, updateData, csrfToken); return editRegistrationSchoolFileTemplates(schoolFileTemplates[currentPage - 2].id, updateData, csrfToken);
}) })
.then((data) => { .then((data) => {
logger.debug("EDIT TEMPLATE : ", data); logger.debug("EDIT TEMPLATE : ", data);
@ -367,7 +368,7 @@ export default function InscriptionFormShared({
/> />
) : ( ) : (
<iframe <iframe
src={`${BASE_URL}/${requiredFileTemplates[currentPage - 2].file}`} src={`${BASE_URL}/${schoolFileTemplates[currentPage - 2].file}`}
title="Document Viewer" title="Document Viewer"
className="w-full" className="w-full"
style={{ style={{
@ -380,10 +381,10 @@ export default function InscriptionFormShared({
)} )}
{/* Dernière page : Section Fichiers parents */} {/* Dernière page : Section Fichiers parents */}
{currentPage === requiredFileTemplates.length + 2 && ( {currentPage === schoolFileTemplates.length + 2 && (
<> <>
<FilesToUpload <FilesToUpload
fileTemplates={fileTemplates.filter(template => !template.is_required)} parentFileTemplates={parentFileTemplates}
columns={columns} columns={columns}
/> />
<FileUpload <FileUpload
@ -409,7 +410,7 @@ export default function InscriptionFormShared({
{currentPage > 1 && ( {currentPage > 1 && (
<Button text="Précédent" onClick={(e) => { e.preventDefault(); handlePreviousPage(); }} /> <Button text="Précédent" onClick={(e) => { e.preventDefault(); handlePreviousPage(); }} />
)} )}
{currentPage < requiredFileTemplates.length + 2 && ( {currentPage < schoolFileTemplates.length + 2 && (
<Button <Button
text="Suivant" text="Suivant"
onClick={(e) => { e.preventDefault(); handleNextPage(); }} onClick={(e) => { e.preventDefault(); handleNextPage(); }}
@ -423,12 +424,12 @@ export default function InscriptionFormShared({
name="Next" name="Next"
/> />
)} )}
{currentPage === requiredFileTemplates.length + 2 && ( {currentPage === schoolFileTemplates.length + 2 && (
<Button type="submit" text="Valider" primary /> <Button type="submit" text="Valider" primary />
)} )}
</div> </div>
</form> </form>
{fileTemplates.length > 0 && ( {schoolFileTemplates.length > 0 && (
<Modal <Modal
isOpen={showUploadModal} isOpen={showUploadModal}
setIsOpen={setShowUploadModal} setIsOpen={setShowUploadModal}

View File

@ -1,17 +1,12 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import ToggleSwitch from '@/components/ToggleSwitch'; // Import du composant ToggleSwitch import { fetchRegistrationFileGroups, createRegistrationSchoolFileTemplate, cloneTemplate, generateToken } from '@/app/actions/registerFileGroupAction';
import { fetchRegistrationFileGroups, createRegistrationTemplates, cloneTemplate, generateToken } from '@/app/actions/registerFileGroupAction';
import { DocusealBuilder } from '@docuseal/react'; import { DocusealBuilder } from '@docuseal/react';
import logger from '@/utils/logger'; import logger from '@/utils/logger';
import { BE_DOCUSEAL_GET_JWT, BASE_URL, FE_API_DOCUSEAL_GENERATE_TOKEN } from '@/utils/Url';
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'; import { useEstablishment } from '@/context/EstablishmentContext';
export default function FileUploadDocuSeal({ handleCreateTemplateMaster, handleEditTemplateMaster, fileToEdit = null, onSuccess }) { export default function FileUploadDocuSeal({ handleCreateTemplateMaster, handleEditTemplateMaster, fileToEdit = null, onSuccess }) {
const [isRequired, setIsRequired] = useState(false); // État pour le toggle isRequired
const [order, setOrder] = useState(0);
const [groups, setGroups] = useState([]); const [groups, setGroups] = useState([]);
const [token, setToken] = useState(null); const [token, setToken] = useState(null);
const [templateMaster, setTemplateMaster] = useState(null); const [templateMaster, setTemplateMaster] = useState(null);
@ -43,10 +38,6 @@ export default function FileUploadDocuSeal({ handleCreateTemplateMaster, handleE
.catch((error) => console.error('Erreur lors de la génération du token:', error)); .catch((error) => console.error('Erreur lors de la génération du token:', error));
}, [fileToEdit]); }, [fileToEdit]);
const handleFileNameChange = (event) => {
setUploadedFileName(event.target.value);
};
const handleGroupChange = (selectedGroups) => { const handleGroupChange = (selectedGroups) => {
setSelectedGroups(selectedGroups); setSelectedGroups(selectedGroups);
@ -110,7 +101,7 @@ export default function FileUploadDocuSeal({ handleCreateTemplateMaster, handleE
master: templateMaster?.id, master: templateMaster?.id,
registration_form: guardian.registration_form registration_form: guardian.registration_form
}; };
createRegistrationTemplates(data, csrfToken) createRegistrationSchoolFileTemplate(data, csrfToken)
.then(response => { .then(response => {
logger.debug('Template enregistré avec succès:', response); logger.debug('Template enregistré avec succès:', response);
onSuccess(); onSuccess();

View File

@ -333,14 +333,17 @@ export default function FilesGroupsManagement({ csrfToken, selectedEstablishment
const handleCreate = (newParentFile) => { const handleCreate = (newParentFile) => {
return createRegistrationParentFileMaster(newParentFile, csrfToken) return createRegistrationParentFileMaster(newParentFile, csrfToken)
.then((createdFile) => { .then((response) => {
const createdFile = response;
// Ajouter le nouveau fichier parent à la liste existante // Ajouter le nouveau fichier parent à la liste existante
setParentFileMasters((prevFiles) => [...prevFiles, createdFile]); setParentFileMasters((prevFiles) => [...prevFiles, createdFile]);
logger.debug('Document parent créé avec succès:', createdFile); logger.debug('Document parent créé avec succès:', createdFile);
return createdFile;
}) })
.catch((error) => { .catch((error) => {
logger.error('Erreur lors de la création du document parent:', error); logger.error('Erreur lors de la création du document parent:', error);
alert('Une erreur est survenue lors de la création du document parent.'); alert('Une erreur est survenue lors de la création du document parent.');
throw error;
}); });
}; };

View File

@ -5,18 +5,24 @@ import InputText from '@/components/InputText';
import MultiSelect from '@/components/MultiSelect'; import MultiSelect from '@/components/MultiSelect';
import Popup from '@/components/Popup'; import Popup from '@/components/Popup';
import logger from '@/utils/logger'; import logger from '@/utils/logger';
import { createRegistrationParentFileTemplate } from '@/app/actions/registerFileGroupAction';
import { useCsrfToken } from '@/context/CsrfContext';
export default function ParentFilesSection({ parentFiles, groups, handleCreate, handleEdit, handleDelete }) { export default function ParentFilesSection({ parentFiles, groups, handleCreate, handleEdit, handleDelete }) {
const [editingDocumentId, setEditingDocumentId] = useState(null); const [editingDocumentId, setEditingDocumentId] = useState(null);
const [formData, setFormData] = useState(null); const [formData, setFormData] = useState(null);
const [selectedGroups, setSelectedGroups] = useState([]); // Gestion des groupes sélectionnés const [selectedGroups, setSelectedGroups] = useState([]); // Gestion des groupes sélectionnés
const [guardianDetails, setGuardianDetails] = useState([]);
const [popupVisible, setPopupVisible] = useState(false); const [popupVisible, setPopupVisible] = useState(false);
const [popupMessage, setPopupMessage] = useState(""); const [popupMessage, setPopupMessage] = useState("");
const [removePopupVisible, setRemovePopupVisible] = useState(false); const [removePopupVisible, setRemovePopupVisible] = useState(false);
const [removePopupMessage, setRemovePopupMessage] = useState(""); const [removePopupMessage, setRemovePopupMessage] = useState("");
const [removePopupOnConfirm, setRemovePopupOnConfirm] = useState(() => {}); const [removePopupOnConfirm, setRemovePopupOnConfirm] = useState(() => {});
const csrfToken = useCsrfToken();
const handleAddEmptyRequiredDocument = () => { const handleAddEmptyRequiredDocument = () => {
setEditingDocumentId('new'); setEditingDocumentId('new');
setFormData({ name: '', description: '', groups: [] }); setFormData({ name: '', description: '', groups: [] });
@ -44,10 +50,27 @@ export default function ParentFilesSection({ parentFiles, groups, handleCreate,
}; };
if (editingDocumentId === 'new') { if (editingDocumentId === 'new') {
handleCreate(updatedFormData).then(() => { handleCreate(updatedFormData).then((createdDocument) => {
setEditingDocumentId(null); setEditingDocumentId(null);
setFormData(null); setFormData(null);
setSelectedGroups([]); setSelectedGroups([]);
guardianDetails.forEach((guardian, index) => {
// Création des templates
const data = {
master: createdDocument?.id,
registration_form: guardian.registration_form
};
console.log(guardian)
createRegistrationParentFileTemplate(data, csrfToken)
.then(response => {
logger.debug('Template enregistré avec succès:', response);
onSuccess();
})
.catch(error => {
logger.error('Erreur lors de l\'enregistrement du template:', error);
});
});
}); });
} else { } else {
handleEdit(editingDocumentId, updatedFormData).then(() => { handleEdit(editingDocumentId, updatedFormData).then(() => {
@ -78,6 +101,22 @@ export default function ParentFilesSection({ parentFiles, groups, handleCreate,
const handleGroupChange = (selected) => { const handleGroupChange = (selected) => {
setSelectedGroups(selected); setSelectedGroups(selected);
console.log('selected : ', selected)
// Extraire les guardians associés aux register_forms des groupes sélectionnés
const details = selected.flatMap(group =>
group.registration_forms.flatMap(form =>
form.guardians.map(guardian => ({
email: guardian.associated_profile_email,
last_name: form.last_name, // Extraire depuis form
first_name: form.first_name, // Extraire depuis form
registration_form: form.student_id // Utiliser student_id comme ID du register_form
}))
)
);
console.log("Guardians associés : ", details);
setGuardianDetails(details); // Mettre à jour la variable d'état avec les détails des guardians
}; };
const renderRequiredDocumentCell = (document, column) => { const renderRequiredDocumentCell = (document, column) => {
@ -110,7 +149,7 @@ export default function ParentFilesSection({ parentFiles, groups, handleCreate,
<MultiSelect <MultiSelect
name="groups" name="groups"
label="Sélection de groupes de fichiers" label="Sélection de groupes de fichiers"
options={groups.map((group) => ({ id: group.id, name: group.name }))} options={groups}
selectedOptions={selectedGroups} selectedOptions={selectedGroups}
onChange={handleGroupChange} onChange={handleGroupChange}
errorMsg={null} errorMsg={null}

View File

@ -26,10 +26,11 @@ export const BE_AUTH_INFO_SESSION = `${BASE_URL}/Auth/infoSession`
export const BE_SUBSCRIPTION_STUDENTS_URL = `${BASE_URL}/Subscriptions/students` // Récupère la liste des élèves inscrits ou en cours d'inscriptions export const BE_SUBSCRIPTION_STUDENTS_URL = `${BASE_URL}/Subscriptions/students` // Récupère la liste des élèves inscrits ou en cours d'inscriptions
export const BE_SUBSCRIPTION_CHILDRENS_URL = `${BASE_URL}/Subscriptions/children` // Récupère la liste des élèves d'un profil export const BE_SUBSCRIPTION_CHILDRENS_URL = `${BASE_URL}/Subscriptions/children` // Récupère la liste des élèves d'un profil
export const BE_SUBSCRIPTION_REGISTERFORMS_URL = `${BASE_URL}/Subscriptions/registerForms` export const BE_SUBSCRIPTION_REGISTERFORMS_URL = `${BASE_URL}/Subscriptions/registerForms`
export const BE_SUBSCRIPTION_REGISTRATIONSCHOOL_FILE_MASTERS_URL = `${BASE_URL}/Subscriptions/registrationSchoolFileMasters`
export const BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL = `${BASE_URL}/Subscriptions/registrationSchoolFileTemplates`
export const BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL = `${BASE_URL}/Subscriptions/registrationFileGroups` export const BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL = `${BASE_URL}/Subscriptions/registrationFileGroups`
export const BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL = `${BASE_URL}/Subscriptions/registrationSchoolFileMasters`
export const BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL = `${BASE_URL}/Subscriptions/registrationSchoolFileTemplates`
export const BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL = `${BASE_URL}/Subscriptions/registrationParentFileMasters` export const BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL = `${BASE_URL}/Subscriptions/registrationParentFileMasters`
export const BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_TEMPLATES_URL = `${BASE_URL}/Subscriptions/registrationParentFileTemplates`
export const BE_SUBSCRIPTION_LAST_GUARDIAN_ID_URL = `${BASE_URL}/Subscriptions/lastGuardianId` export const BE_SUBSCRIPTION_LAST_GUARDIAN_ID_URL = `${BASE_URL}/Subscriptions/lastGuardianId`