mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-04-05 20:51:26 +00:00
feat: Finalisation formulaire dynamique
This commit is contained in:
@ -58,6 +58,8 @@ class RegistrationParentFileTemplateView(APIView):
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class RegistrationParentFileTemplateSimpleView(APIView):
|
||||
parser_classes = [MultiPartParser, FormParser, JSONParser]
|
||||
|
||||
@swagger_auto_schema(
|
||||
operation_description="Récupère un template d'inscription spécifique",
|
||||
responses={
|
||||
@ -82,11 +84,15 @@ class RegistrationParentFileTemplateSimpleView(APIView):
|
||||
}
|
||||
)
|
||||
def put(self, request, id):
|
||||
payload, resp = util.build_payload_from_request(request)
|
||||
if resp is not None:
|
||||
return resp
|
||||
|
||||
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, partial=True)
|
||||
serializer = RegistrationParentFileTemplateSerializer(template, data=payload, partial=True)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return Response({'message': 'Template mis à jour avec succès', 'data': serializer.data}, status=status.HTTP_200_OK)
|
||||
|
||||
@ -125,6 +125,25 @@ class RegistrationSchoolFileMasterSimpleView(APIView):
|
||||
if resp:
|
||||
return resp
|
||||
|
||||
# Garde-fou: eviter d'ecraser un master dynamique existant avec un
|
||||
# formMasterData vide/malforme (cas observe en multipart).
|
||||
if 'formMasterData' in payload:
|
||||
incoming_form_data = payload.get('formMasterData')
|
||||
current_is_dynamic = (
|
||||
isinstance(master.formMasterData, dict)
|
||||
and bool(master.formMasterData.get('fields'))
|
||||
)
|
||||
incoming_is_dynamic = (
|
||||
isinstance(incoming_form_data, dict)
|
||||
and bool(incoming_form_data.get('fields'))
|
||||
)
|
||||
if current_is_dynamic and not incoming_is_dynamic:
|
||||
logger.warning(
|
||||
"formMasterData invalide recu pour master %s: conservation de la config dynamique existante",
|
||||
master.pk,
|
||||
)
|
||||
payload['formMasterData'] = master.formMasterData
|
||||
|
||||
|
||||
logger.info(f"payload for update serializer: {payload}")
|
||||
serializer = RegistrationSchoolFileMasterSerializer(master, data=payload, partial=True)
|
||||
|
||||
@ -16,6 +16,20 @@ import Subscriptions.util as util
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _extract_nested_responses(data, max_depth=8):
|
||||
"""Extrait le dictionnaire de reponses depuis des structures imbriquees."""
|
||||
current = data
|
||||
for _ in range(max_depth):
|
||||
if not isinstance(current, dict):
|
||||
return None
|
||||
nested = current.get("responses")
|
||||
if isinstance(nested, dict):
|
||||
current = nested
|
||||
continue
|
||||
return current
|
||||
return current if isinstance(current, dict) else None
|
||||
|
||||
class RegistrationSchoolFileTemplateView(APIView):
|
||||
@swagger_auto_schema(
|
||||
operation_description="Récupère tous les templates d'inscription pour un établissement donné",
|
||||
@ -95,15 +109,26 @@ class RegistrationSchoolFileTemplateSimpleView(APIView):
|
||||
responses = None
|
||||
if "responses" in formTemplateData:
|
||||
resp = formTemplateData["responses"]
|
||||
if isinstance(resp, dict) and "responses" in resp:
|
||||
responses = resp["responses"]
|
||||
elif isinstance(resp, dict):
|
||||
responses = resp
|
||||
responses = _extract_nested_responses(resp)
|
||||
|
||||
# Nettoyer les meta-cles qui ne sont pas des reponses de champs
|
||||
if isinstance(responses, dict):
|
||||
cleaned = {
|
||||
key: value
|
||||
for key, value in responses.items()
|
||||
if key not in {"responses", "formId", "id", "templateId"}
|
||||
}
|
||||
responses = cleaned
|
||||
|
||||
if responses and "fields" in formTemplateData:
|
||||
for field in formTemplateData["fields"]:
|
||||
field_id = field.get("id")
|
||||
if field_id and field_id in responses:
|
||||
field["value"] = responses[field_id]
|
||||
|
||||
# Stocker les reponses aplaties pour eviter l'empilement responses.responses
|
||||
if isinstance(responses, dict):
|
||||
formTemplateData["responses"] = responses
|
||||
payload['formTemplateData'] = formTemplateData
|
||||
|
||||
template = bdd.getObject(_objectName=RegistrationSchoolFileTemplate, _columnName='id', _value=id)
|
||||
@ -137,7 +162,7 @@ class RegistrationSchoolFileTemplateSimpleView(APIView):
|
||||
return Response({'message': 'Template mis à jour avec succès', 'data': RegistrationSchoolFileTemplateSerializer(template).data}, status=status.HTTP_200_OK)
|
||||
|
||||
# Cas 2 : Formulaire dynamique (JSON)
|
||||
serializer = RegistrationSchoolFileTemplateSerializer(template, data=payload)
|
||||
serializer = RegistrationSchoolFileTemplateSerializer(template, data=payload, partial=True)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
# Régénérer le PDF si besoin
|
||||
@ -148,19 +173,50 @@ class RegistrationSchoolFileTemplateSimpleView(APIView):
|
||||
and formTemplateData.get("fields")
|
||||
and hasattr(template, "file")
|
||||
):
|
||||
old_pdf_name = None
|
||||
if template.file and template.file.name:
|
||||
old_pdf_name = os.path.basename(template.file.name)
|
||||
# Lire le contenu du fichier source en mémoire AVANT suppression.
|
||||
# Priorité au fichier master (document source admin) pour éviter
|
||||
# de re-générer à partir d'un PDF template déjà enrichi.
|
||||
base_pdf_content = None
|
||||
base_file_ext = None
|
||||
if template.master and template.master.file and template.master.file.name:
|
||||
base_file_ext = os.path.splitext(template.master.file.name)[1].lower()
|
||||
try:
|
||||
template.master.file.open('rb')
|
||||
base_pdf_content = template.master.file.read()
|
||||
template.master.file.close()
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur lecture fichier source master: {e}")
|
||||
elif template.file and template.file.name:
|
||||
base_file_ext = os.path.splitext(template.file.name)[1].lower()
|
||||
try:
|
||||
template.file.open('rb')
|
||||
base_pdf_content = template.file.read()
|
||||
template.file.close()
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur lecture fichier source template: {e}")
|
||||
try:
|
||||
old_path = template.file.path
|
||||
template.file.delete(save=False)
|
||||
if os.path.exists(template.file.path):
|
||||
os.remove(template.file.path)
|
||||
if os.path.exists(old_path):
|
||||
os.remove(old_path)
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur lors de la suppression du fichier existant: {e}")
|
||||
from Subscriptions.util import generate_form_json_pdf
|
||||
pdf_file = generate_form_json_pdf(template.registration_form, formTemplateData)
|
||||
pdf_filename = old_pdf_name or f"{template.name}_{template.id}.pdf"
|
||||
template.file.save(pdf_filename, pdf_file, save=True)
|
||||
pdf_file = generate_form_json_pdf(
|
||||
template.registration_form,
|
||||
formTemplateData,
|
||||
base_pdf_content=base_pdf_content,
|
||||
base_file_ext=base_file_ext,
|
||||
)
|
||||
form_name = (formTemplateData.get("title") or template.name or f"formulaire_{template.id}").strip().replace(" ", "_")
|
||||
pdf_filename = f"{form_name}.pdf"
|
||||
util.save_file_field_without_suffix(
|
||||
template,
|
||||
'file',
|
||||
pdf_filename,
|
||||
pdf_file,
|
||||
save=True,
|
||||
)
|
||||
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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user