feat: Changement du rendu de la page des documents + gestion des

formulaires d'école déjà existants [N3WTS-17]
This commit is contained in:
N3WT DE COMPET
2026-01-03 17:49:25 +01:00
parent 2dc0dfa268
commit 12f5fc7aa9
17 changed files with 1622 additions and 423 deletions

View File

@ -8,6 +8,9 @@ from N3wtSchool import renderers
from N3wtSchool import bdd
from io import BytesIO
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from django.core.files.base import ContentFile
from django.core.files import File
from pathlib import Path
import os
@ -100,8 +103,9 @@ def create_templates_for_registration_form(register_form):
from Subscriptions.models import (
RegistrationSchoolFileMaster,
RegistrationSchoolFileTemplate,
# RegistrationParentFileMaster,
# RegistrationParentFileTemplate,
RegistrationParentFileMaster,
RegistrationParentFileTemplate,
registration_school_file_upload_to,
)
created = []
@ -114,25 +118,26 @@ def create_templates_for_registration_form(register_form):
for t in school_existing:
try:
if getattr(t, "file", None):
logger.info("Deleted school template %s for RF %s", t.pk, register_form.pk)
t.file.delete(save=False)
except Exception:
logger.exception("Erreur suppression fichier school template %s", getattr(t, "pk", None))
t.delete()
# parent_existing = RegistrationParentFileTemplate.objects.filter(registration_form=register_form)
# for t in parent_existing:
# try:
# if getattr(t, "file", None):
# t.file.delete(save=False)
# except Exception:
# logger.exception("Erreur suppression fichier parent template %s", getattr(t, "pk", None))
# t.delete()
parent_existing = RegistrationParentFileTemplate.objects.filter(registration_form=register_form)
for t in parent_existing:
try:
if getattr(t, "file", None):
t.file.delete(save=False)
except Exception:
logger.exception("Erreur suppression fichier parent template %s", getattr(t, "pk", None))
t.delete()
return created
school_masters = RegistrationSchoolFileMaster.objects.filter(groups=current_group).distinct()
# parent_masters = RegistrationParentFileMaster.objects.filter(groups=current_group).distinct()
parent_masters = RegistrationParentFileMaster.objects.filter(groups=current_group).distinct()
school_master_ids = {m.pk for m in school_masters}
#parent_master_ids = {m.pk for m in parent_masters}
parent_master_ids = {m.pk for m in parent_masters}
# Supprimer les school templates obsolètes
for tmpl in RegistrationSchoolFileTemplate.objects.filter(registration_form=register_form):
@ -146,15 +151,15 @@ def create_templates_for_registration_form(register_form):
logger.info("Deleted obsolete school template %s for RF %s", getattr(tmpl, "pk", None), register_form.pk)
# Supprimer les parent templates obsolètes
# for tmpl in RegistrationParentFileTemplate.objects.filter(registration_form=register_form):
# if not tmpl.master_id or tmpl.master_id not in parent_master_ids:
# try:
# if getattr(tmpl, "file", None):
# tmpl.file.delete(save=False)
# except Exception:
# logger.exception("Erreur suppression fichier parent template obsolète %s", getattr(tmpl, "pk", None))
# tmpl.delete()
# logger.info("Deleted obsolete parent template %s for RF %s", getattr(tmpl, "pk", None), register_form.pk)
for tmpl in RegistrationParentFileTemplate.objects.filter(registration_form=register_form):
if not tmpl.master_id or tmpl.master_id not in parent_master_ids:
try:
if getattr(tmpl, "file", None):
tmpl.file.delete(save=False)
except Exception:
logger.exception("Erreur suppression fichier parent template obsolète %s", getattr(tmpl, "pk", None))
tmpl.delete()
logger.info("Deleted obsolete parent template %s for RF %s", getattr(tmpl, "pk", None), register_form.pk)
# Créer les school templates manquants
for m in school_masters:
@ -163,28 +168,58 @@ def create_templates_for_registration_form(register_form):
continue
base_slug = (m.name or "master").strip().replace(" ", "_")[:40]
slug = f"{base_slug}_{register_form.pk}_{m.pk}"
# Si le master a un fichier uploadé (formulaire existant)
file_to_attach = None
if m.file:
import os
from django.core.files import File as DjangoFile
master_file_path = m.file.path
if os.path.exists(master_file_path):
filename = os.path.basename(master_file_path)
# Générer le chemin cible pour le template élève
dest_path = registration_school_file_upload_to(None, filename)
dest_dir = os.path.dirname(os.path.join(settings.MEDIA_ROOT, dest_path))
os.makedirs(dest_dir, exist_ok=True)
# Copier le fichier dans le dossier cible
dest_full_path = os.path.join(settings.MEDIA_ROOT, dest_path)
with open(master_file_path, 'rb') as src, open(dest_full_path, 'wb') as dst:
dst.write(src.read())
# Préparer le File Django à attacher au template
with open(dest_full_path, 'rb') as f:
file_to_attach = DjangoFile(f, name=dest_path)
else:
# Générer le PDF du template à partir du JSON du master
try:
pdf_file = generate_form_json_pdf(register_form, m.formMasterData)
file_to_attach = pdf_file
except Exception as e:
logger.error(f"Erreur lors de la génération du PDF pour le template: {e}")
file_to_attach = None
tmpl = RegistrationSchoolFileTemplate.objects.create(
master=m,
registration_form=register_form,
name=m.name or "",
formTemplateData=m.formMasterData or [],
slug=slug,
file=file_to_attach,
)
created.append(tmpl)
logger.info("Created school template %s from master %s for RF %s", tmpl.pk, m.pk, register_form.pk)
# Créer les parent templates manquants
# for m in parent_masters:
# exists = RegistrationParentFileTemplate.objects.filter(master=m, registration_form=register_form).exists()
# if exists:
# continue
# tmpl = RegistrationParentFileTemplate.objects.create(
# master=m,
# registration_form=register_form,
# file=None,
# )
# created.append(tmpl)
# logger.info("Created parent template %s from master %s for RF %s", tmpl.pk, m.pk, register_form.pk)
for m in parent_masters:
exists = RegistrationParentFileTemplate.objects.filter(master=m, registration_form=register_form).exists()
if exists:
continue
tmpl = RegistrationParentFileTemplate.objects.create(
master=m,
registration_form=register_form,
file=None,
)
created.append(tmpl)
logger.info("Created parent template %s from master %s for RF %s", tmpl.pk, m.pk, register_form.pk)
return created
@ -377,4 +412,52 @@ def getHistoricalYears(count=5):
historical_start_year = start_year - i
historical_years.append(f"{historical_start_year}-{historical_start_year + 1}")
return historical_years
return historical_years
def generate_form_json_pdf(register_form, form_json):
"""
Génère un PDF du rendu du formulaire dynamique à partir du JSON (formConfig)
et l'associe au RegistrationSchoolFileTemplate.
Le PDF contient le titre, les labels et types de champs.
Retourne un ContentFile prêt à être utilisé dans un FileField, avec uniquement le nom du fichier.
"""
# Récupérer le nom du formulaire
form_name = (form_json.get("title") or "formulaire").strip().replace(" ", "_")
filename = f"{form_name}.pdf"
# Générer le PDF
buffer = BytesIO()
c = canvas.Canvas(buffer, pagesize=A4)
y = 800
# Titre
c.setFont("Helvetica-Bold", 20)
c.drawString(100, y, form_json.get("title", "Formulaire"))
y -= 40
# Champs
c.setFont("Helvetica", 12)
fields = form_json.get("fields", [])
for field in fields:
label = field.get("label", field.get("id", ""))
ftype = field.get("type", "")
c.drawString(100, y, f"{label} [{ftype}]")
y -= 25
if y < 100:
c.showPage()
y = 800
c.save()
buffer.seek(0)
pdf_content = buffer.read()
# Si un fichier existe déjà sur le template, le supprimer (optionnel, à adapter selon usage)
if hasattr(register_form, "registration_file") and register_form.registration_file and register_form.registration_file.name:
existing_file_path = os.path.join(settings.MEDIA_ROOT, register_form.registration_file.name.lstrip('/'))
if os.path.exists(existing_file_path):
os.remove(existing_file_path)
register_form.registration_file.delete(save=False)
# Retourner le ContentFile avec uniquement le nom du fichier
return ContentFile(pdf_content, name=os.path.basename(filename))