Woziii commited on
Commit
75f2f9e
·
verified ·
1 Parent(s): e4c8441

Update pdf_generator.py

Browse files
Files changed (1) hide show
  1. pdf_generator.py +342 -70
pdf_generator.py CHANGED
@@ -1,60 +1,196 @@
1
  """
2
  Module pour la génération des contrats en format PDF.
3
- Module optimisé pour une génération plus rapide et efficace.
4
  """
5
  import io
6
  import reportlab
7
  from reportlab.pdfgen import canvas
8
  from reportlab.lib.pagesizes import A4
9
  from reportlab.lib.units import mm
10
- from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
11
  from reportlab.pdfbase import pdfform
12
- from reportlab.lib.colors import black
13
  from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
14
- from reportlab.lib.enums import TA_CENTER, TA_JUSTIFY
15
  from reportlab.pdfbase import pdfmetrics
16
  from reportlab.pdfbase.ttfonts import TTFont
 
17
  import time
18
 
19
  from config import PDF_CONFIG
20
  from contract_builder import ContractBuilder
21
  from utils import create_temp_file, ensure_default_supports
22
- from contract_templates import ContractTemplates
23
 
24
  pdfmetrics.registerFont(TTFont('Vera', 'Vera.ttf'))
25
  pdfmetrics.registerFont(TTFont('VeraBd', 'VeraBd.ttf'))
26
 
27
- def get_simplified_styles():
28
  """
29
- Retourne des styles simplifiés pour une génération plus rapide.
 
 
 
 
 
30
 
31
  Returns:
32
- dict: Dictionnaire des styles simplifiés
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  """
34
  styles = getSampleStyleSheet()
35
- # Utiliser des styles plus simples avec moins d'options
36
- styles.add(ParagraphStyle(name='ContractTitle',
37
- fontName='VeraBd',
38
- fontSize=14,
39
- alignment=TA_CENTER,
40
- spaceAfter=10))
41
- styles.add(ParagraphStyle(name='ContractText',
42
- fontName='Vera',
43
- fontSize=10,
44
- alignment=TA_JUSTIFY,
45
- spaceAfter=5))
46
- styles.add(ParagraphStyle(name='ContractArticle',
47
- fontName='VeraBd',
48
- fontSize=11,
49
- spaceAfter=5))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  return styles
51
 
52
  def generate_pdf(contract_type, is_free, author_type, author_info,
53
  work_description, image_description, supports,
54
  additional_rights, remuneration, is_exclusive):
55
  """
56
- Génère un PDF du contrat avec des champs interactifs.
57
- Version optimisée pour une génération plus rapide.
58
 
59
  Args:
60
  contract_type (list): Liste des types de contrats sélectionnés
@@ -81,28 +217,194 @@ def generate_pdf(contract_type, is_free, author_type, author_info,
81
  # Créer un nom de fichier temporaire pour le PDF
82
  output_filename = create_temp_file(prefix="contrat_cession_", suffix=".pdf")
83
 
84
- # Générer le contenu du contrat - version simplifiée pour plus de rapidité
85
- contract_elements = ContractBuilder.build_contract_elements(
86
- contract_type, is_free_bool, author_type, author_info,
87
- work_description, image_description, final_supports,
88
- additional_rights, remuneration, is_exclusive_bool
89
- )
90
 
91
- # Créer un document PDF avec moins d'options pour accélérer la génération
92
  buffer = io.BytesIO()
93
 
94
- # Utiliser des marges plus petites et des réglages plus simples
95
  doc = SimpleDocTemplate(
96
  buffer,
97
  pagesize=A4,
98
- rightMargin=15*mm,
99
- leftMargin=15*mm,
100
- topMargin=15*mm,
101
- bottomMargin=15*mm
102
  )
103
 
104
- # Construire le document en une seule passe
105
- doc.build(contract_elements)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
  # Sauvegarder le PDF
108
  with open(output_filename, 'wb') as f:
@@ -135,34 +437,4 @@ def generate_pdf(contract_type, is_free, author_type, author_info,
135
 
136
  form.textfield(name='mention_cessionnaire', tooltip='Mention "Lu et approuvé"',
137
  x=350, y=95, width=150, height=15,
138
- borderWidth=0, forceBorder=True)
139
-
140
- # Finaliser et sauvegarder le PDF
141
- p.save()
142
-
143
- return output_filename
144
-
145
- def get_simplified_styles():
146
- """
147
- Retourne des styles simplifiés pour une génération plus rapide.
148
-
149
- Returns:
150
- dict: Dictionnaire des styles simplifiés
151
- """
152
- styles = getSampleStyleSheet()
153
- # Utiliser des styles plus simples avec moins d'options
154
- styles.add(ParagraphStyle(name='ContractTitle',
155
- fontName='VeraBd',
156
- fontSize=14,
157
- alignment=TA_CENTER,
158
- spaceAfter=10))
159
- styles.add(ParagraphStyle(name='ContractText',
160
- fontName='Vera',
161
- fontSize=10,
162
- alignment=TA_JUSTIFY,
163
- spaceAfter=5))
164
- styles.add(ParagraphStyle(name='ContractArticle',
165
- fontName='VeraBd',
166
- fontSize=11,
167
- spaceAfter=5))
168
- return styles
 
1
  """
2
  Module pour la génération des contrats en format PDF.
3
+ Module optimisé pour une génération plus complète et détaillée.
4
  """
5
  import io
6
  import reportlab
7
  from reportlab.pdfgen import canvas
8
  from reportlab.lib.pagesizes import A4
9
  from reportlab.lib.units import mm
10
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
11
  from reportlab.pdfbase import pdfform
12
+ from reportlab.lib.colors import black, white
13
  from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
14
+ from reportlab.lib.enums import TA_CENTER, TA_JUSTIFY, TA_LEFT
15
  from reportlab.pdfbase import pdfmetrics
16
  from reportlab.pdfbase.ttfonts import TTFont
17
+ from reportlab.lib.styles import getSampleStyleSheet
18
  import time
19
 
20
  from config import PDF_CONFIG
21
  from contract_builder import ContractBuilder
22
  from utils import create_temp_file, ensure_default_supports
23
+ from contract_templates import ContractTemplates # Import this to use title generation
24
 
25
  pdfmetrics.registerFont(TTFont('Vera', 'Vera.ttf'))
26
  pdfmetrics.registerFont(TTFont('VeraBd', 'VeraBd.ttf'))
27
 
28
+ def _format_physical_person_details(author_info, contract_type, styles):
29
  """
30
+ Formate les détails d'une personne physique pour le contrat PDF.
31
+
32
+ Args:
33
+ author_info (dict): Informations sur l'auteur
34
+ contract_type (list): Types de contrat
35
+ styles (dict): Styles de paragraphe
36
 
37
  Returns:
38
+ list: Éléments de paragraphe pour les détails de l'auteur
39
+ """
40
+ elements = []
41
+ gentille = author_info.get("gentille", "M.")
42
+ nom = author_info.get("nom", "")
43
+ prenom = author_info.get("prenom", "")
44
+ date_naissance = author_info.get("date_naissance", "")
45
+ nationalite = author_info.get("nationalite", "")
46
+ adresse = author_info.get("adresse", "")
47
+ contact = author_info.get("contact", "")
48
+
49
+ # Construire la description de l'auteur
50
+ author_description = f"{gentille} {prenom} {nom}"
51
+ if date_naissance:
52
+ author_description += f", né(e) le {date_naissance}"
53
+ if nationalite:
54
+ author_description += f", de nationalité {nationalite}"
55
+ author_description += f", domicilié(e) au {adresse}"
56
+ if contact:
57
+ author_description += f", joignable à {contact}"
58
+
59
+ # Ajouter la description
60
+ elements.append(Paragraph(author_description, styles['ContractNormalText']))
61
+ elements.append(Spacer(1, 6))
62
+
63
+ # Dénomination de l'auteur
64
+ if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
65
+ denomination = "ci-après dénommé(e) \"l'Auteur et le Modèle\","
66
+ elif "Auteur (droits d'auteur)" in contract_type:
67
+ denomination = "ci-après dénommé(e) \"l'Auteur\","
68
+ else:
69
+ denomination = "ci-après dénommé(e) \"le Modèle\","
70
+
71
+ elements.append(Paragraph(denomination, styles['ContractNormalText']))
72
+ elements.append(Spacer(1, 6))
73
+
74
+ return elements
75
+
76
+ def _format_legal_entity_details(author_info, contract_type, styles):
77
+ """
78
+ Formate les détails d'une personne morale pour le contrat PDF.
79
+
80
+ Args:
81
+ author_info (dict): Informations sur l'entité légale
82
+ contract_type (list): Types de contrat
83
+ styles (dict): Styles de paragraphe
84
+
85
+ Returns:
86
+ list: Éléments de paragraphe pour les détails de l'entité
87
+ """
88
+ elements = []
89
+ nom_societe = author_info.get("nom_societe", "")
90
+ statut = author_info.get("statut", "")
91
+ rcs = author_info.get("rcs", "")
92
+ siege = author_info.get("siege", "")
93
+ contact = author_info.get("contact", "")
94
+
95
+ # Construire la description de l'entité
96
+ entity_description = f"La société {nom_societe}, {statut}, immatriculée sous le numéro {rcs} au Registre du Commerce et des Sociétés, dont le siège social est situé {siege}"
97
+ if contact:
98
+ entity_description += f", joignable à {contact}"
99
+
100
+ # Ajouter la description
101
+ elements.append(Paragraph(entity_description, styles['ContractNormalText']))
102
+ elements.append(Spacer(1, 6))
103
+
104
+ # Dénomination de l'auteur
105
+ if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
106
+ denomination = "ci-après dénommée \"l'Auteur et le Modèle\","
107
+ elif "Auteur (droits d'auteur)" in contract_type:
108
+ denomination = "ci-après dénommée \"l'Auteur\","
109
+ else:
110
+ denomination = "ci-après dénommée \"le Modèle\","
111
+
112
+ elements.append(Paragraph(denomination, styles['ContractNormalText']))
113
+ elements.append(Spacer(1, 6))
114
+
115
+ return elements
116
+
117
+ def get_enriched_styles():
118
+ """
119
+ Retourne des styles enrichis pour la génération du PDF.
120
+
121
+ Returns:
122
+ dict: Dictionnaire des styles enrichis
123
  """
124
  styles = getSampleStyleSheet()
125
+
126
+ # Style pour le titre du contrat
127
+ styles.add(ParagraphStyle(
128
+ name='ContractTitle',
129
+ fontName='VeraBd',
130
+ fontSize=16,
131
+ alignment=TA_CENTER,
132
+ spaceAfter=12,
133
+ textColor=black
134
+ ))
135
+
136
+ # Style pour les titres de section
137
+ styles.add(ParagraphStyle(
138
+ name='ContractSectionHeader',
139
+ fontName='VeraBd',
140
+ fontSize=12,
141
+ alignment=TA_LEFT,
142
+ spaceAfter=6,
143
+ textColor=black
144
+ ))
145
+
146
+ # Style pour les articles principaux
147
+ styles.add(ParagraphStyle(
148
+ name='ContractArticle',
149
+ fontName='VeraBd',
150
+ fontSize=12,
151
+ alignment=TA_LEFT,
152
+ spaceAfter=6,
153
+ textColor=black
154
+ ))
155
+
156
+ # Style pour les sous-articles
157
+ styles.add(ParagraphStyle(
158
+ name='ContractSubArticle',
159
+ fontName='VeraBd',
160
+ fontSize=11,
161
+ alignment=TA_LEFT,
162
+ spaceAfter=6,
163
+ textColor=black
164
+ ))
165
+
166
+ # Style pour le texte normal du contrat
167
+ styles.add(ParagraphStyle(
168
+ name='ContractNormalText',
169
+ fontName='Vera',
170
+ fontSize=10,
171
+ alignment=TA_JUSTIFY,
172
+ spaceAfter=6,
173
+ textColor=black
174
+ ))
175
+
176
+ # Style pour les éléments de liste
177
+ styles.add(ParagraphStyle(
178
+ name='ContractListItem',
179
+ fontName='Vera',
180
+ fontSize=10,
181
+ alignment=TA_LEFT,
182
+ spaceAfter=3,
183
+ textColor=black,
184
+ leftIndent=20
185
+ ))
186
+
187
  return styles
188
 
189
  def generate_pdf(contract_type, is_free, author_type, author_info,
190
  work_description, image_description, supports,
191
  additional_rights, remuneration, is_exclusive):
192
  """
193
+ Génère un PDF du contrat avec des champs interactifs et tous les détails.
 
194
 
195
  Args:
196
  contract_type (list): Liste des types de contrats sélectionnés
 
217
  # Créer un nom de fichier temporaire pour le PDF
218
  output_filename = create_temp_file(prefix="contrat_cession_", suffix=".pdf")
219
 
220
+ # Préparer les styles
221
+ styles = get_enriched_styles()
 
 
 
 
222
 
223
+ # Créer un buffer pour le PDF
224
  buffer = io.BytesIO()
225
 
226
+ # Créer le document PDF avec des marges adaptées
227
  doc = SimpleDocTemplate(
228
  buffer,
229
  pagesize=A4,
230
+ rightMargin=25*mm,
231
+ leftMargin=25*mm,
232
+ topMargin=20*mm,
233
+ bottomMargin=20*mm
234
  )
235
 
236
+ # Liste pour stocker les éléments du document
237
+ elements = []
238
+
239
+ # Titre du contrat
240
+ title = Paragraph(ContractTemplates.get_title(contract_type), styles['ContractTitle'])
241
+ elements.append(title)
242
+ elements.append(Spacer(1, 12))
243
+
244
+ # Ajouter le préambule
245
+ elements.append(Paragraph("ENTRE LES SOUSSIGNÉS :", styles['ContractSectionHeader']))
246
+ elements.append(Spacer(1, 6))
247
+
248
+ # Informations sur l'auteur/modèle
249
+ if author_type == "Personne physique":
250
+ author_details = _format_physical_person_details(author_info, contract_type, styles)
251
+ elements.extend(author_details)
252
+ else:
253
+ author_details = _format_legal_entity_details(author_info, contract_type, styles)
254
+ elements.extend(author_details)
255
+
256
+ # Informations sur Tellers
257
+ elements.append(Paragraph("Tellers, société par actions simplifiée unipersonnelle au capital de 1000 €, " +
258
+ "immatriculée sous le numéro 932 553 266 R.C.S. Lyon, et dont le siège social est situé au : " +
259
+ "12 RUE DE LA PART-DIEU, 69003 LYON, représentée par son Président en exercice dûment habilité à l'effet des présentes, " +
260
+ "ci-après dénommée \"le Cessionnaire\",", styles['ContractNormalText']))
261
+ elements.append(Spacer(1, 6))
262
+
263
+ # Introduction
264
+ elements.append(Paragraph("Ci-après dénommées ensemble \"les Parties\" ou individuellement \"la Partie\",", styles['ContractNormalText']))
265
+ elements.append(Spacer(1, 6))
266
+ elements.append(Paragraph("CECI EXPOSÉ, IL A ÉTÉ CONVENU CE QUI SUIT :", styles['ContractSectionHeader']))
267
+ elements.append(Spacer(1, 12))
268
+
269
+ # ARTICLE 1 - OBJET DU CONTRAT
270
+ elements.append(Paragraph("ARTICLE 1 – OBJET DU CONTRAT", styles['ContractArticle']))
271
+ elements.append(Spacer(1, 6))
272
+
273
+ # Œuvre concernée si droits d'auteur
274
+ if "Auteur (droits d'auteur)" in contract_type:
275
+ elements.append(Paragraph("1.1 Œuvre concernée", styles['ContractSubArticle']))
276
+ elements.append(Paragraph("L'Auteur déclare être le créateur et titulaire exclusif des droits d'auteur sur l'œuvre suivante :",
277
+ styles['ContractNormalText']))
278
+ elements.append(Paragraph(work_description, styles['ContractNormalText']))
279
+ elements.append(Spacer(1, 6))
280
+
281
+ # Image concernée si droit à l'image
282
+ if "Image (droit à l'image)" in contract_type:
283
+ elements.append(Paragraph("1.2 Images concernées", styles['ContractSubArticle']))
284
+ elements.append(Paragraph("Le Modèle autorise l'utilisation de son image telle qu'elle apparaît dans :",
285
+ styles['ContractNormalText']))
286
+ elements.append(Paragraph(image_description, styles['ContractNormalText']))
287
+ elements.append(Spacer(1, 6))
288
+
289
+ # ARTICLE 2 - DROITS CÉDÉS
290
+ elements.append(Paragraph("ARTICLE 2 – ÉTENDUE DES DROITS CÉDÉS", styles['ContractArticle']))
291
+ elements.append(Spacer(1, 6))
292
+
293
+ elements.append(Paragraph("2.1 Nature de la cession", styles['ContractSubArticle']))
294
+
295
+ # Détails de la cession
296
+ cession_details = "L'Auteur cède au Cessionnaire, "
297
+ cession_details += "à titre exclusif, " if is_exclusive_bool else "à titre non exclusif, "
298
+ cession_details += "gratuitement et pour la durée précisée à l'article 4, les droits patrimoniaux suivants :" if is_free_bool else "pour la durée précisée à l'article 4 et moyennant rémunération, les droits suivants :"
299
+
300
+ elements.append(Paragraph(cession_details, styles['ContractNormalText']))
301
+ elements.append(Spacer(1, 6))
302
+
303
+ elements.append(Paragraph("2.2 Droits patrimoniaux cédés", styles['ContractSubArticle']))
304
+
305
+ # Droits de base
306
+ elements.append(Paragraph("- Droit de reproduction", styles['ContractListItem']))
307
+ elements.append(Paragraph("- Droit de représentation", styles['ContractListItem']))
308
+
309
+ # Droits supplémentaires
310
+ if not is_free_bool and additional_rights:
311
+ elements.append(Paragraph("Droits supplémentaires inclus :", styles['ContractNormalText']))
312
+ for right in additional_rights:
313
+ short_name = right.split(" - ")[0] if " - " in right else right
314
+ elements.append(Paragraph(f"- {short_name}", styles['ContractListItem']))
315
+
316
+ elements.append(Spacer(1, 6))
317
+
318
+ # Article sur l'image si applicable
319
+ article_num = 3
320
+ if "Image (droit à l'image)" in contract_type:
321
+ elements.append(Paragraph(f"ARTICLE {article_num} – AUTORISATION D'EXPLOITATION DE L'IMAGE", styles['ContractArticle']))
322
+ elements.append(Spacer(1, 6))
323
+
324
+ image_rights_details = "Le Modèle autorise expressément le Cessionnaire à exploiter son image "
325
+ image_rights_details += "à titre exclusif" if is_exclusive_bool else "à titre non exclusif"
326
+ image_rights_details += " et gratuit" if is_free_bool else ""
327
+ image_rights_details += " selon les modalités détaillées dans le contrat complet."
328
+
329
+ elements.append(Paragraph(image_rights_details, styles['ContractNormalText']))
330
+ elements.append(Spacer(1, 6))
331
+
332
+ article_num += 1
333
+
334
+ # Article DURÉE ET TERRITOIRE
335
+ elements.append(Paragraph(f"ARTICLE {article_num} – DURÉE ET TERRITOIRE", styles['ContractArticle']))
336
+ elements.append(Spacer(1, 6))
337
+
338
+ elements.append(Paragraph("4.1 Durée", styles['ContractSubArticle']))
339
+ elements.append(Paragraph("La cession est consentie pour une durée d'un (1) an, renouvelable par tacite reconduction.",
340
+ styles['ContractNormalText']))
341
+ elements.append(Spacer(1, 6))
342
+
343
+ elements.append(Paragraph("4.2 Territoire", styles['ContractSubArticle']))
344
+ elements.append(Paragraph("La cession est consentie pour le monde entier.", styles['ContractNormalText']))
345
+ elements.append(Spacer(1, 6))
346
+
347
+ article_num += 1
348
+
349
+ # Article SUPPORTS D'EXPLOITATION
350
+ elements.append(Paragraph(f"ARTICLE {article_num} – SUPPORTS D'EXPLOITATION", styles['ContractArticle']))
351
+ elements.append(Spacer(1, 6))
352
+ elements.append(Paragraph("5.1 Supports autorisés", styles['ContractSubArticle']))
353
+ elements.append(Paragraph("Les supports d'exploitation autorisés sont :", styles['ContractNormalText']))
354
+
355
+ for support in final_supports:
356
+ elements.append(Paragraph(f"- {support}", styles['ContractListItem']))
357
+
358
+ elements.append(Spacer(1, 6))
359
+ article_num += 1
360
+
361
+ # Article RÉMUNÉRATION
362
+ elements.append(Paragraph(f"ARTICLE {article_num} – RÉMUNÉRATION", styles['ContractArticle']))
363
+ elements.append(Spacer(1, 6))
364
+
365
+ if is_free_bool:
366
+ elements.append(Paragraph("La présente cession est consentie à titre gratuit, sans contrepartie financière.",
367
+ styles['ContractNormalText']))
368
+ else:
369
+ elements.append(Paragraph("En contrepartie de la présente cession, le Cessionnaire versera au Cédant :",
370
+ styles['ContractNormalText']))
371
+ elements.append(Paragraph(remuneration, styles['ContractNormalText']))
372
+
373
+ elements.append(Spacer(1, 6))
374
+ article_num += 1
375
+
376
+ # Articles supplémentaires (résumés)
377
+ articles_complementaires = [
378
+ "GARANTIES ET RESPONSABILITÉS",
379
+ "RÉSILIATION",
380
+ "DISPOSITIONS DIVERSES",
381
+ "LOI APPLICABLE ET JURIDICTION COMPÉTENTE"
382
+ ]
383
+
384
+ for art in articles_complementaires:
385
+ elements.append(Paragraph(f"ARTICLE {article_num} – {art}", styles['ContractArticle']))
386
+ elements.append(Spacer(1, 6))
387
+ article_num += 1
388
+
389
+ # Signature
390
+ elements.append(Paragraph("Fait à ________________, le ________________", styles['ContractNormalText']))
391
+ elements.append(Spacer(1, 6))
392
+ elements.append(Paragraph("En deux exemplaires originaux.", styles['ContractNormalText']))
393
+ elements.append(Spacer(1, 12))
394
+
395
+ # Lignes de signature
396
+ signature_text = ""
397
+ if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
398
+ signature_text = "Pour l'Auteur et Modèle : Pour le Cessionnaire :"
399
+ elif "Auteur (droits d'auteur)" in contract_type:
400
+ signature_text = "Pour l'Auteur : Pour le Cessionnaire :"
401
+ else:
402
+ signature_text = "Pour le Modèle : Pour le Cessionnaire :"
403
+
404
+ elements.append(Paragraph(signature_text, styles['ContractNormalText']))
405
+
406
+ # Construire le document
407
+ doc.build(elements)
408
 
409
  # Sauvegarder le PDF
410
  with open(output_filename, 'wb') as f:
 
437
 
438
  form.textfield(name='mention_cessionnaire', tooltip='Mention "Lu et approuvé"',
439
  x=350, y=95, width=150, height=15,
440
+ borderWidth=0, forceBorder=True)