Woziii commited on
Commit
2e25654
·
verified ·
1 Parent(s): 2b8173c

Upload 10 files

Browse files
Files changed (10) hide show
  1. app.py +19 -0
  2. config.py +84 -0
  3. contract_builder.py +174 -0
  4. contract_previewer.py +173 -0
  5. contract_templates.py +423 -0
  6. interface.py +359 -0
  7. pdf_generator-py.py +165 -0
  8. readme.md +84 -0
  9. requirements.txt +2 -0
  10. utils.py +122 -0
app.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from interface import create_interface
3
+ from pdf_generator import generate_pdf
4
+ from contract_previewer import preview_contract
5
+
6
+ # Point d'entrée principal de l'application
7
+ def main():
8
+ """
9
+ Point d'entrée principal de l'application.
10
+ Crée l'interface Gradio et lance l'application.
11
+ """
12
+ # Création de l'interface Gradio avec injection des fonctions de génération et prévisualisation
13
+ demo = create_interface(generate_pdf, preview_contract)
14
+
15
+ # Lancement de l'application
16
+ demo.launch()
17
+
18
+ if __name__ == "__main__":
19
+ main()
config.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Fichier de configuration contenant les constantes et paramètres utilisés dans l'application.
3
+ """
4
+
5
+ # Informations sur le cessionnaire (Tellers)
6
+ TELLERS_INFO = {
7
+ "nom": "Tellers",
8
+ "forme_juridique": "société par actions simplifiée unipersonnelle",
9
+ "capital": "1000 €",
10
+ "rcs": "932 553 266 R.C.S. Lyon",
11
+ "siege": "12 RUE DE LA PART-DIEU, 69003 LYON"
12
+ }
13
+
14
+ # Options pour les différents types de contrats
15
+ CONTRACT_TYPES = [
16
+ "Auteur (droits d'auteur)",
17
+ "Image (droit à l'image)"
18
+ ]
19
+
20
+ # Options pour le mode de cession
21
+ CESSION_MODES = [
22
+ "Gratuite",
23
+ "Onéreuse"
24
+ ]
25
+
26
+ # Options pour les droits supplémentaires (cession onéreuse uniquement)
27
+ ADDITIONAL_RIGHTS = [
28
+ "distribution - droit de distribuer l'original ou les copies de l'œuvre au public",
29
+ "usage - droit d'utiliser l'œuvre pour les besoins du cessionnaire",
30
+ "adaptation - droit de modifier, transformer, traduire l'œuvre",
31
+ "pret - droit de mettre l'œuvre à disposition pour un usage temporaire",
32
+ "location - droit de mettre l'œuvre à disposition contre rémunération",
33
+ "suite - droit de percevoir un pourcentage lors de reventes (œuvres graphiques/plastiques uniquement)"
34
+ ]
35
+
36
+ # Options pour le type d'auteur
37
+ AUTHOR_TYPES = [
38
+ "Personne physique",
39
+ "Personne morale"
40
+ ]
41
+
42
+ # Options pour la civilité
43
+ CIVILITY_OPTIONS = [
44
+ "M.",
45
+ "Mme"
46
+ ]
47
+
48
+ # Options pour les supports d'exploitation
49
+ SUPPORTS_OPTIONS = [
50
+ "Réseaux sociaux (Facebook, Instagram, Twitter, etc.)",
51
+ "Applications mobiles",
52
+ "Plateformes de diffusion vidéo (YouTube, Twitch, etc.)",
53
+ "Supports imprimés (catalogues, flyers, affiches)",
54
+ "Présentations lors d'événements",
55
+ "Publicités en ligne",
56
+ "Plateformes tierces (marketplaces, sites partenaires)",
57
+ "Emails et newsletters"
58
+ ]
59
+
60
+ # Supports toujours inclus (obligatoires)
61
+ DEFAULT_SUPPORTS = [
62
+ "site web",
63
+ "Discord"
64
+ ]
65
+
66
+ # Paramètres PDF
67
+ PDF_CONFIG = {
68
+ "page_size": "A4",
69
+ "margin_right": 25, # mm
70
+ "margin_left": 25, # mm
71
+ "margin_top": 20, # mm
72
+ "margin_bottom": 20, # mm
73
+ "font_main": "Helvetica",
74
+ "font_bold": "Helvetica-Bold",
75
+ "font_size_title": 14,
76
+ "font_size_subtitle": 12,
77
+ "font_size_normal": 10,
78
+ "font_size_article": 11
79
+ }
80
+
81
+ # Durée et territoire par défaut
82
+ DEFAULT_DURATION = "un (1) an"
83
+ DEFAULT_RENEWAL = "renouvellement par tacite reconduction pour des périodes successives d'un (1) an"
84
+ DEFAULT_TERRITORY = "monde entier"
contract_builder.py ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Module pour la construction des contrats à partir des templates.
3
+ """
4
+ from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
5
+ from reportlab.lib.enums import TA_CENTER, TA_JUSTIFY
6
+ from reportlab.platypus import Paragraph, Spacer
7
+
8
+ from contract_templates import ContractTemplates
9
+ from utils import ensure_default_supports, sanitize_text
10
+
11
+
12
+ class ContractBuilder:
13
+ """
14
+ Classe responsable de la construction des contrats complets à partir des templates.
15
+ """
16
+
17
+ @staticmethod
18
+ def get_styles():
19
+ """
20
+ Retourne les styles pour le document PDF.
21
+
22
+ Returns:
23
+ dict: Dictionnaire des styles
24
+ """
25
+ styles = getSampleStyleSheet()
26
+ styles.add(ParagraphStyle(name='Titre',
27
+ fontName='Helvetica-Bold',
28
+ fontSize=14,
29
+ alignment=TA_CENTER,
30
+ spaceAfter=12))
31
+ styles.add(ParagraphStyle(name='Sous-titre',
32
+ fontName='Helvetica-Bold',
33
+ fontSize=12,
34
+ spaceAfter=10))
35
+ styles.add(ParagraphStyle(name='Normal',
36
+ fontName='Helvetica',
37
+ fontSize=10,
38
+ alignment=TA_JUSTIFY,
39
+ spaceAfter=6))
40
+ styles.add(ParagraphStyle(name='Article',
41
+ fontName='Helvetica-Bold',
42
+ fontSize=11,
43
+ spaceAfter=8))
44
+ return styles
45
+
46
+ @staticmethod
47
+ def build_contract_elements(contract_type, is_free, author_type, author_info,
48
+ work_description, image_description, supports,
49
+ additional_rights, remuneration, is_exclusive):
50
+ """
51
+ Construit tous les éléments du contrat.
52
+
53
+ Args:
54
+ contract_type (list): Liste des types de contrats sélectionnés
55
+ is_free (bool): True si la cession est gratuite, False sinon
56
+ author_type (str): Type d'auteur ("Personne physique" ou "Personne morale")
57
+ author_info (dict): Informations sur l'auteur
58
+ work_description (str): Description de l'œuvre
59
+ image_description (str): Description de l'image
60
+ supports (list): Liste des supports sélectionnés
61
+ additional_rights (list): Liste des droits supplémentaires sélectionnés
62
+ remuneration (str): Modalités de rémunération
63
+ is_exclusive (bool): True si la cession est exclusive, False sinon
64
+
65
+ Returns:
66
+ list: Liste des éléments du contrat pour ReportLab
67
+ """
68
+ # Obtenir les styles
69
+ styles = ContractBuilder.get_styles()
70
+
71
+ # Initialiser la liste des éléments
72
+ elements = []
73
+
74
+ # 1. Titre du contrat
75
+ title = ContractTemplates.get_title(contract_type)
76
+ elements.append(Paragraph(title, styles['Titre']))
77
+ elements.append(Spacer(1, 10))
78
+
79
+ # 2. Préambule
80
+ preamble_text = ContractTemplates.get_preamble_text(contract_type, author_type, author_info)
81
+ for paragraph in preamble_text.split('\n\n'):
82
+ if paragraph.strip():
83
+ elements.append(Paragraph(paragraph, styles['Normal']))
84
+ elements.append(Spacer(1, 6))
85
+
86
+ # 3. Article 1 - Objet
87
+ object_clause = ContractTemplates.get_object_clause(
88
+ contract_type,
89
+ sanitize_text(work_description),
90
+ sanitize_text(image_description)
91
+ )
92
+ elements.append(Paragraph(object_clause, styles['Article']))
93
+ elements.append(Spacer(1, 10))
94
+
95
+ # Compteur d'articles
96
+ article_num = 2
97
+
98
+ # 4. Article 2 - Droits cédés (pour contrat droits d'auteur)
99
+ if "Auteur (droits d'auteur)" in contract_type:
100
+ rights_clause = ContractTemplates.get_author_rights_clause(is_free, is_exclusive, additional_rights)
101
+ for paragraph in rights_clause.split('\n\n'):
102
+ if paragraph.strip():
103
+ elements.append(Paragraph(paragraph, styles['Normal']))
104
+ elements.append(Spacer(1, 6))
105
+ article_num += 1
106
+
107
+ # 5. Article sur les droits à l'image (pour contrat droit à l'image)
108
+ if "Image (droit à l'image)" in contract_type:
109
+ image_rights_article_num = article_num if "Auteur (droits d'auteur)" not in contract_type else article_num
110
+ image_clause = ContractTemplates.get_image_rights_clause(is_free, is_exclusive)
111
+ image_clause = image_clause.replace("Article 2", f"Article {image_rights_article_num}")
112
+ for paragraph in image_clause.split('\n\n'):
113
+ if paragraph.strip():
114
+ elements.append(Paragraph(paragraph, styles['Normal']))
115
+ elements.append(Spacer(1, 6))
116
+ article_num += 1
117
+
118
+ # 6. Article - Durée et territoire
119
+ duration_clause = ContractTemplates.get_duration_territory_clause(article_num)
120
+ for paragraph in duration_clause.split('\n\n'):
121
+ if paragraph.strip():
122
+ elements.append(Paragraph(paragraph, styles['Normal']))
123
+ elements.append(Spacer(1, 6))
124
+ article_num += 1
125
+
126
+ # 7. Article - Supports d'exploitation
127
+ final_supports = ensure_default_supports(supports)
128
+ supports_clause = ContractTemplates.get_supports_clause(article_num, final_supports)
129
+ for paragraph in supports_clause.split('\n\n'):
130
+ if paragraph.strip():
131
+ elements.append(Paragraph(paragraph, styles['Normal']))
132
+ elements.append(Spacer(1, 6))
133
+ article_num += 1
134
+
135
+ # 8. Article - Rémunération
136
+ remuneration_clause = ContractTemplates.get_remuneration_clause(article_num, is_free, sanitize_text(remuneration))
137
+ for paragraph in remuneration_clause.split('\n\n'):
138
+ if paragraph.strip():
139
+ elements.append(Paragraph(paragraph, styles['Normal']))
140
+ elements.append(Spacer(1, 6))
141
+ article_num += 1
142
+
143
+ # 9. Article - Garanties
144
+ warranties_clause = ContractTemplates.get_warranties_clause(article_num, contract_type)
145
+ for paragraph in warranties_clause.split('\n\n'):
146
+ if paragraph.strip():
147
+ elements.append(Paragraph(paragraph, styles['Normal']))
148
+ elements.append(Spacer(1, 6))
149
+ article_num += 1
150
+
151
+ # 10. Article - Résiliation
152
+ termination_clause = ContractTemplates.get_termination_clause(article_num)
153
+ for paragraph in termination_clause.split('\n\n'):
154
+ if paragraph.strip():
155
+ elements.append(Paragraph(paragraph, styles['Normal']))
156
+ elements.append(Spacer(1, 6))
157
+ article_num += 1
158
+
159
+ # 11. Article - Loi applicable
160
+ law_clause = ContractTemplates.get_applicable_law_clause(article_num)
161
+ for paragraph in law_clause.split('\n\n'):
162
+ if paragraph.strip():
163
+ elements.append(Paragraph(paragraph, styles['Normal']))
164
+ elements.append(Spacer(1, 6))
165
+
166
+ # 12. Signatures
167
+ elements.append(Spacer(1, 20))
168
+ signatures = ContractTemplates.get_signatures_template(contract_type)
169
+ for paragraph in signatures.split('\n\n'):
170
+ if paragraph.strip():
171
+ elements.append(Paragraph(paragraph, styles['Normal']))
172
+ elements.append(Spacer(1, 8))
173
+
174
+ return elements
contract_previewer.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Module pour la prévisualisation des contrats avant génération du PDF.
3
+ """
4
+ from contract_templates import ContractTemplates
5
+ from utils import ensure_default_supports, sanitize_text
6
+
7
+
8
+ def preview_contract(contract_type, is_free, author_type, author_info,
9
+ work_description, image_description, supports,
10
+ additional_rights, remuneration, is_exclusive):
11
+ """
12
+ Génère un aperçu du contrat sous forme de texte.
13
+
14
+ Args:
15
+ contract_type (list): Liste des types de contrats sélectionnés
16
+ is_free (bool): True si la cession est gratuite, False sinon
17
+ author_type (str): Type d'auteur ("Personne physique" ou "Personne morale")
18
+ author_info (dict): Informations sur l'auteur
19
+ work_description (str): Description de l'œuvre
20
+ image_description (str): Description de l'image
21
+ supports (list): Liste des supports sélectionnés
22
+ additional_rights (list): Liste des droits supplémentaires sélectionnés
23
+ remuneration (str): Modalités de rémunération
24
+ is_exclusive (bool): True si la cession est exclusive, False sinon
25
+
26
+ Returns:
27
+ str: Aperçu du contrat
28
+ """
29
+ is_free = (is_free == "Gratuite")
30
+
31
+ # Ajouter les supports par défaut
32
+ final_supports = ensure_default_supports(supports)
33
+
34
+ # Initialiser l'aperçu avec le titre
35
+ apercu = ContractTemplates.get_title(contract_type) + "\n\n"
36
+
37
+ # Ajouter le préambule
38
+ apercu += ContractTemplates.get_preamble_text(contract_type, author_type, author_info)
39
+
40
+ # Article 1 - Objet
41
+ apercu += "Article 1 – OBJET\n"
42
+ if "Auteur (droits d'auteur)" in contract_type:
43
+ apercu += f"L'Auteur déclare être le créateur et titulaire exclusif des droits d'auteur sur l'œuvre suivante : {sanitize_text(work_description)}.\n"
44
+
45
+ if "Image (droit à l'image)" in contract_type:
46
+ apercu += f"Le Modèle autorise l'utilisation et l'exploitation de son image telle qu'elle apparaît dans les photographies/vidéos suivantes : {sanitize_text(image_description)}.\n"
47
+
48
+ apercu += "Par le présent contrat, "
49
+ if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
50
+ apercu += "l'Auteur cède au Cessionnaire certains droits sur son œuvre, et le Modèle autorise l'exploitation de son image, dans les conditions définies ci-après.\n\n"
51
+ elif "Auteur (droits d'auteur)" in contract_type:
52
+ apercu += "l'Auteur cède au Cessionnaire certains droits sur son œuvre dans les conditions définies ci-après.\n\n"
53
+ else:
54
+ apercu += "le Modèle autorise l'exploitation de son image dans les conditions définies ci-après.\n\n"
55
+
56
+ # Compteur d'articles
57
+ article_num = 2
58
+
59
+ # Article 2 - Droits cédés pour l'Auteur
60
+ if "Auteur (droits d'auteur)" in contract_type:
61
+ apercu += "Article 2 – ÉTENDUE DES DROITS CÉDÉS\n"
62
+ apercu += "L'Auteur cède au Cessionnaire, "
63
+
64
+ if is_exclusive:
65
+ apercu += "à titre exclusif, "
66
+ else:
67
+ apercu += "à titre non exclusif, "
68
+
69
+ if is_free:
70
+ apercu += "gratuitement et pour la durée précisée à l'article 3, les droits patrimoniaux suivants :\n\n"
71
+ apercu += "- Le droit de reproduction\n"
72
+ apercu += "- Le droit de représentation\n\n"
73
+ else:
74
+ apercu += "pour la durée précisée à l'article 3 et moyennant la rémunération précisée à l'article approprié, les droits patrimoniaux suivants :\n\n"
75
+
76
+ # Droits de base
77
+ apercu += "- Le droit de reproduction\n"
78
+ apercu += "- Le droit de représentation\n"
79
+
80
+ # Droits supplémentaires pour les cessions onéreuses
81
+ if "distribution" in additional_rights:
82
+ apercu += "- Le droit de distribution\n"
83
+
84
+ if "usage" in additional_rights:
85
+ apercu += "- Le droit d'usage\n"
86
+
87
+ if "adaptation" in additional_rights:
88
+ apercu += "- Le droit d'adaptation\n"
89
+
90
+ if "pret" in additional_rights:
91
+ apercu += "- Le droit de prêt\n"
92
+
93
+ if "location" in additional_rights:
94
+ apercu += "- Le droit de location\n"
95
+
96
+ if "suite" in additional_rights:
97
+ apercu += "- Le droit de suite (pour œuvres graphiques et plastiques)\n"
98
+
99
+ apercu += "\n"
100
+
101
+ # Clause d'exclusivité
102
+ if is_exclusive:
103
+ apercu += "Pendant la durée de la présente cession, l'Auteur s'engage à ne pas céder les mêmes droits à des tiers et à ne pas exploiter lui-même l'œuvre selon les modalités cédées au Cessionnaire.\n\n"
104
+ else:
105
+ apercu += "La présente cession étant non exclusive, l'Auteur conserve le droit d'exploiter l'œuvre et de céder les mêmes droits à des tiers.\n\n"
106
+
107
+ article_num += 1
108
+
109
+ # Article pour les droits à l'image
110
+ if "Image (droit à l'image)" in contract_type:
111
+ image_article_num = article_num if "Auteur (droits d'auteur)" in contract_type else 2
112
+ apercu += f"Article {image_article_num} – AUTORISATION D'EXPLOITATION DE L'IMAGE\n"
113
+
114
+ apercu += "Le Modèle autorise le Cessionnaire à fixer, reproduire et communiquer au public son image. "
115
+ apercu += "Cette autorisation est consentie "
116
+
117
+ if is_exclusive:
118
+ apercu += "à titre exclusif, "
119
+ else:
120
+ apercu += "à titre non exclusif, "
121
+
122
+ if is_free:
123
+ apercu += "gratuitement, "
124
+ else:
125
+ apercu += "moyennant la rémunération précisée à l'article approprié, "
126
+
127
+ apercu += "pour la durée et sur le territoire mentionnés ci-après.\n\n"
128
+
129
+ apercu += "Le Cessionnaire s'engage expressément à ne pas porter atteinte à la dignité, à l'honneur ou à la réputation du Modèle. "
130
+ apercu += "Les parties s'engagent mutuellement à ne pas tenir de propos dénigrants l'une envers l'autre.\n\n"
131
+
132
+ if is_exclusive:
133
+ apercu += "Le Modèle s'engage à ne pas autoriser l'exploitation de son image à des tiers pendant la durée du présent contrat.\n\n"
134
+ else:
135
+ apercu += "La présente autorisation étant non exclusive, le Modèle conserve le droit d'autoriser l'exploitation de son image à des tiers.\n\n"
136
+
137
+ article_num += 1
138
+
139
+ # Suite des articles (résumés pour l'aperçu)
140
+ apercu += f"Article {article_num} – DURÉE ET TERRITOIRE\n"
141
+ apercu += "Durée : 1 an, renouvelable par tacite reconduction\n"
142
+ apercu += "Territoire : monde entier\n\n"
143
+
144
+ article_num += 1
145
+ apercu += f"Article {article_num} – SUPPORTS D'EXPLOITATION\n"
146
+ supports_str = ", ".join(final_supports)
147
+ apercu += f"Supports autorisés : {supports_str}\n\n"
148
+
149
+ article_num += 1
150
+ apercu += f"Article {article_num} – RÉMUNÉRATION\n"
151
+ if is_free:
152
+ apercu += "La présente cession est consentie à titre gratuit.\n\n"
153
+ else:
154
+ apercu += f"Rémunération : {sanitize_text(remuneration)}\n\n"
155
+
156
+ # Aperçu des articles restants
157
+ article_num += 1
158
+ apercu += f"Article {article_num} – GARANTIES\n"
159
+ article_num += 1
160
+ apercu += f"Article {article_num} – RÉSILIATION\n"
161
+ article_num += 1
162
+ apercu += f"Article {article_num} – LOI APPLICABLE ET JURIDICTION COMPÉTENTE\n\n"
163
+
164
+ apercu += "Fait à ________________, le ________________\n\n"
165
+
166
+ if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
167
+ apercu += "L'Auteur et Modèle Le Cessionnaire"
168
+ elif "Auteur (droits d'auteur)" in contract_type:
169
+ apercu += "L'Auteur Le Cessionnaire"
170
+ else:
171
+ apercu += "Le Modèle Le Cessionnaire"
172
+
173
+ return apercu
contract_templates.py ADDED
@@ -0,0 +1,423 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Templates des différentes sections de contrats.
3
+ Ce module contient tous les textes de base pour les différentes sections des contrats.
4
+ """
5
+
6
+ from config import TELLERS_INFO, DEFAULT_DURATION, DEFAULT_RENEWAL, DEFAULT_TERRITORY
7
+
8
+
9
+ class ContractTemplates:
10
+ """Classe contenant tous les templates pour la génération des contrats."""
11
+
12
+ @staticmethod
13
+ def get_title(contract_type):
14
+ """
15
+ Retourne le titre du contrat en fonction du type.
16
+
17
+ Args:
18
+ contract_type (list): Liste des types de contrats sélectionnés
19
+
20
+ Returns:
21
+ str: Titre du contrat
22
+ """
23
+ if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
24
+ return "CONTRAT DE CESSION DE DROITS D'AUTEUR ET DE DROITS À L'IMAGE"
25
+ elif "Auteur (droits d'auteur)" in contract_type:
26
+ return "CONTRAT DE CESSION DE DROITS D'AUTEUR"
27
+ else:
28
+ return "CONTRAT DE CESSION DE DROITS À L'IMAGE"
29
+
30
+ @staticmethod
31
+ def get_preamble_text(contract_type, author_type, author_info):
32
+ """
33
+ Retourne le texte du préambule du contrat.
34
+
35
+ Args:
36
+ contract_type (list): Liste des types de contrats sélectionnés
37
+ author_type (str): Type d'auteur ("Personne physique" ou "Personne morale")
38
+ author_info (dict): Informations sur l'auteur
39
+
40
+ Returns:
41
+ str: Texte du préambule
42
+ """
43
+ # Partie commune à tous les contrats
44
+ preamble = "ENTRE LES SOUSSIGNÉS :\n\n"
45
+
46
+ # Informations sur l'auteur/modèle
47
+ if author_type == "Personne physique":
48
+ gentille = author_info.get("gentille", "M.")
49
+ nom = author_info.get("nom", "")
50
+ prenom = author_info.get("prenom", "")
51
+ date_naissance = author_info.get("date_naissance", "")
52
+ nationalite = author_info.get("nationalite", "")
53
+ adresse = author_info.get("adresse", "")
54
+ contact = author_info.get("contact", "")
55
+
56
+ preamble += f"{gentille} {prenom} {nom}"
57
+ if date_naissance:
58
+ preamble += f", né(e) le {date_naissance}"
59
+ if nationalite:
60
+ preamble += f", de nationalité {nationalite}"
61
+ preamble += f", domicilié(e) au {adresse}"
62
+ if contact:
63
+ preamble += f", joignable à {contact}"
64
+ else:
65
+ # Personne morale
66
+ nom_societe = author_info.get("nom_societe", "")
67
+ statut = author_info.get("statut", "")
68
+ rcs = author_info.get("rcs", "")
69
+ siege = author_info.get("siege", "")
70
+ contact = author_info.get("contact", "")
71
+
72
+ preamble += f"La société {nom_societe}, {statut}, immatriculée sous le numéro {rcs}, dont le siège social est situé {siege}"
73
+ if contact:
74
+ preamble += f", joignable à {contact}"
75
+
76
+ # Dénomination en fonction du type de contrat
77
+ if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
78
+ preamble += ", ci-après dénommé(e) \"l'Auteur et le Modèle\"\n\n"
79
+ elif "Auteur (droits d'auteur)" in contract_type:
80
+ preamble += ", ci-après dénommé(e) \"l'Auteur\"\n\n"
81
+ else:
82
+ preamble += ", ci-après dénommé(e) \"le Modèle\"\n\n"
83
+
84
+ # Informations sur Tellers (bénéficiaire)
85
+ preamble += f"{TELLERS_INFO['nom']}, {TELLERS_INFO['forme_juridique']} au capital de {TELLERS_INFO['capital']}, "
86
+ preamble += f"immatriculée sous le numéro {TELLERS_INFO['rcs']}, et dont le siège social est situé au : "
87
+ preamble += f"{TELLERS_INFO['siege']}, ci-après dénommée \"le Cessionnaire\"\n\n"
88
+
89
+ # Introduction commune
90
+ preamble += "IL A ÉTÉ CONVENU CE QUI SUIT :\n\n"
91
+
92
+ return preamble
93
+
94
+ @staticmethod
95
+ def get_object_clause(contract_type, work_description, image_description):
96
+ """
97
+ Retourne la clause d'objet du contrat.
98
+
99
+ Args:
100
+ contract_type (list): Liste des types de contrats sélectionnés
101
+ work_description (str): Description de l'œuvre
102
+ image_description (str): Description de l'image
103
+
104
+ Returns:
105
+ str: Clause d'objet
106
+ """
107
+ object_clause = "Article 1 – OBJET\n\n"
108
+
109
+ if "Auteur (droits d'auteur)" in contract_type:
110
+ object_clause += f"L'Auteur déclare être le créateur et titulaire exclusif des droits d'auteur sur l'œuvre suivante : {work_description}. "
111
+
112
+ if "Image (droit à l'image)" in contract_type:
113
+ object_clause += f"Le Modèle autorise l'utilisation et l'exploitation de son image telle qu'elle apparaît dans les photographies/vidéos suivantes : {image_description}. "
114
+
115
+ object_clause += "\nPar le présent contrat, "
116
+
117
+ if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
118
+ object_clause += "l'Auteur cède au Cessionnaire certains droits sur son œuvre, et le Modèle autorise l'exploitation de son image, dans les conditions définies ci-après."
119
+ elif "Auteur (droits d'auteur)" in contract_type:
120
+ object_clause += "l'Auteur cède au Cessionnaire certains droits sur son œuvre dans les conditions définies ci-après."
121
+ else:
122
+ object_clause += "le Modèle autorise l'exploitation de son image dans les conditions définies ci-après."
123
+
124
+ return object_clause
125
+
126
+ @staticmethod
127
+ def get_author_rights_clause(is_free, is_exclusive, additional_rights):
128
+ """
129
+ Retourne la clause des droits cédés pour le droit d'auteur.
130
+
131
+ Args:
132
+ is_free (bool): True si la cession est gratuite, False sinon
133
+ is_exclusive (bool): True si la cession est exclusive, False sinon
134
+ additional_rights (list): Liste des droits supplémentaires sélectionnés
135
+
136
+ Returns:
137
+ str: Clause des droits cédés
138
+ """
139
+ rights_clause = "Article 2 – ÉTENDUE DES DROITS CÉDÉS\n\n"
140
+
141
+ # Texte de base pour tous les contrats de droits d'auteur
142
+ rights_clause += "L'Auteur cède au Cessionnaire, "
143
+
144
+ if is_exclusive:
145
+ rights_clause += "à titre exclusif, "
146
+ else:
147
+ rights_clause += "à titre non exclusif, "
148
+
149
+ if is_free:
150
+ rights_clause += f"gratuitement et pour la durée précisée à l'article 3, les droits patrimoniaux suivants :\n\n"
151
+
152
+ # Droits limités pour cession gratuite
153
+ rights_clause += "- Le droit de reproduction : l'Auteur autorise le Cessionnaire à reproduire ou faire reproduire l'œuvre "
154
+ rights_clause += "par tous procédés techniques connus ou inconnus à ce jour, sur tous supports et en tous formats.\n\n"
155
+
156
+ rights_clause += "- Le droit de représentation : l'Auteur autorise le Cessionnaire à communiquer l'œuvre au public "
157
+ rights_clause += "par tous procédés connus ou inconnus à ce jour, notamment par diffusion en ligne sur Internet, "
158
+ rights_clause += "présentation publique, projection, ou tout autre moyen."
159
+ else:
160
+ rights_clause += f"pour la durée précisée à l'article 3 et moyennant la rémunération précisée à l'article approprié, les droits patrimoniaux suivants :\n\n"
161
+
162
+ # Droits de base (toujours présents)
163
+ rights_clause += "- Le droit de reproduction : l'Auteur autorise le Cessionnaire à reproduire ou faire reproduire l'œuvre "
164
+ rights_clause += "par tous procédés techniques connus ou inconnus à ce jour, sur tous supports et en tous formats.\n\n"
165
+
166
+ rights_clause += "- Le droit de représentation : l'Auteur autorise le Cessionnaire à communiquer l'œuvre au public "
167
+ rights_clause += "par tous procédés connus ou inconnus à ce jour, notamment par diffusion en ligne sur Internet, "
168
+ rights_clause += "présentation publique, projection, ou tout autre moyen.\n\n"
169
+
170
+ # Droits supplémentaires pour les cessions onéreuses
171
+ if "distribution" in additional_rights:
172
+ rights_clause += "- Le droit de distribution : l'Auteur autorise le Cessionnaire à distribuer l'original de l'œuvre "
173
+ rights_clause += "ou ses copies au public par la vente ou tout autre transfert de propriété.\n\n"
174
+
175
+ if "usage" in additional_rights:
176
+ rights_clause += "- Le droit d'usage : l'Auteur autorise le Cessionnaire à utiliser l'œuvre pour les besoins "
177
+ rights_clause += "propres du Cessionnaire ou de ses clients, dans un cadre correspondant à l'objet du présent contrat.\n\n"
178
+
179
+ if "adaptation" in additional_rights:
180
+ rights_clause += "- Le droit d'adaptation : l'Auteur autorise le Cessionnaire à modifier, transformer, arranger, "
181
+ rights_clause += "traduire l'œuvre ou à l'incorporer à d'autres œuvres, dans le respect du droit moral de l'Auteur.\n\n"
182
+
183
+ if "pret" in additional_rights:
184
+ rights_clause += "- Le droit de prêt : l'Auteur autorise le Cessionnaire à mettre l'œuvre à disposition pour un "
185
+ rights_clause += "usage déterminé et pour une durée limitée, sans contrepartie financière directe.\n\n"
186
+
187
+ if "location" in additional_rights:
188
+ rights_clause += "- Le droit de location : l'Auteur autorise le Cessionnaire à mettre à disposition l'œuvre pour "
189
+ rights_clause += "un usage temporaire et en échange d'une contrepartie économique.\n\n"
190
+
191
+ if "suite" in additional_rights:
192
+ rights_clause += "- Le droit de suite (pour œuvres graphiques et plastiques uniquement) : l'Auteur et le Cessionnaire "
193
+ rights_clause += "reconnaissent l'existence du droit de suite permettant à l'auteur de percevoir un pourcentage sur le "
194
+ rights_clause += "produit de toute revente de l'œuvre, conformément aux dispositions légales en vigueur.\n\n"
195
+
196
+ # Clause d'exclusivité ou non-exclusivité
197
+ if is_exclusive:
198
+ rights_clause += "Pendant la durée de la présente cession, l'Auteur s'engage à ne pas céder les mêmes droits à des tiers "
199
+ rights_clause += "et à ne pas exploiter lui-même l'œuvre selon les modalités cédées au Cessionnaire. Cette exclusivité "
200
+ rights_clause += "constitue un élément substantiel du présent contrat, sans lequel le Cessionnaire n'aurait pas contracté."
201
+ else:
202
+ rights_clause += "La présente cession étant non exclusive, l'Auteur conserve le droit d'exploiter l'œuvre et de céder "
203
+ rights_clause += "les mêmes droits à des tiers, sous réserve de ne pas nuire à l'exploitation des droits cédés au Cessionnaire."
204
+
205
+ return rights_clause
206
+
207
+ @staticmethod
208
+ def get_image_rights_clause(is_free, is_exclusive):
209
+ """
210
+ Retourne la clause des droits cédés pour le droit à l'image.
211
+
212
+ Args:
213
+ is_free (bool): True si la cession est gratuite, False sinon
214
+ is_exclusive (bool): True si la cession est exclusive, False sinon
215
+
216
+ Returns:
217
+ str: Clause des droits à l'image
218
+ """
219
+ image_clause = "Article 2 – AUTORISATION D'EXPLOITATION DE L'IMAGE\n\n"
220
+
221
+ image_clause += "Le Modèle autorise expressément le Cessionnaire à fixer, reproduire et communiquer au public son image telle que décrite à l'article 1. "
222
+ image_clause += "Cette autorisation comprend le droit de reproduire et de représenter l'image sur tous supports et par tous moyens, connus ou inconnus à ce jour. "
223
+ image_clause += "Cette autorisation est consentie "
224
+
225
+ if is_exclusive:
226
+ image_clause += "à titre exclusif, "
227
+ else:
228
+ image_clause += "à titre non exclusif, "
229
+
230
+ if is_free:
231
+ image_clause += "gratuitement, "
232
+ else:
233
+ image_clause += "moyennant la rémunération précisée à l'article approprié, "
234
+
235
+ image_clause += f"pour la durée et sur le territoire mentionnés ci-après.\n\n"
236
+
237
+ # Restrictions d'utilisation pour le droit à l'image
238
+ image_clause += "Le Cessionnaire s'engage expressément à ne pas porter atteinte à la dignité, à l'honneur ou à la réputation du Modèle. "
239
+ image_clause += "Les images ne pourront pas être utilisées dans un contexte diffamatoire, pornographique, ou contraire aux bonnes mœurs. "
240
+ image_clause += "Les parties s'engagent mutuellement à ne pas tenir de propos dénigrants l'une envers l'autre.\n\n"
241
+
242
+ # Clause d'exclusivité pour le droit à l'image
243
+ if is_exclusive:
244
+ image_clause += "Le Modèle s'engage à ne pas autoriser l'exploitation de son image, telle que décrite à l'article 1, "
245
+ image_clause += "à des tiers pendant la durée du présent contrat. Cette exclusivité constitue un élément substantiel du "
246
+ image_clause += "présent contrat, sans lequel le Cessionnaire n'aurait pas contracté."
247
+ else:
248
+ image_clause += "La présente autorisation étant non exclusive, le Modèle conserve le droit d'autoriser l'exploitation "
249
+ image_clause += "de son image à des tiers, sous réserve de ne pas nuire à l'exploitation des droits autorisés au Cessionnaire."
250
+
251
+ return image_clause
252
+
253
+ @staticmethod
254
+ def get_duration_territory_clause(article_num):
255
+ """
256
+ Retourne la clause de durée et territoire.
257
+
258
+ Args:
259
+ article_num (int): Numéro de l'article
260
+
261
+ Returns:
262
+ str: Clause de durée et territoire
263
+ """
264
+ duration_clause = f"Article {article_num} – DURÉE ET TERRITOIRE\n\n"
265
+
266
+ duration_clause += f"La présente cession est consentie pour une durée de {DEFAULT_DURATION} à compter de la date de signature du présent contrat. "
267
+ duration_clause += f"Elle se renouvellera automatiquement par {DEFAULT_RENEWAL}, "
268
+ duration_clause += "sauf dénonciation par l'une des parties par lettre recommandée avec accusé de réception au moins trois (3) mois avant l'expiration de la période en cours.\n\n"
269
+ duration_clause += f"La cession est consentie pour le {DEFAULT_TERRITORY}, compte tenu de la nature numérique des services fournis par le Cessionnaire, "
270
+ duration_clause += "susceptibles d'être accessibles à l'échelle mondiale."
271
+
272
+ return duration_clause
273
+
274
+ @staticmethod
275
+ def get_supports_clause(article_num, supports):
276
+ """
277
+ Retourne la clause des supports d'exploitation.
278
+
279
+ Args:
280
+ article_num (int): Numéro de l'article
281
+ supports (list): Liste des supports sélectionnés
282
+
283
+ Returns:
284
+ str: Clause des supports
285
+ """
286
+ supports_clause = f"Article {article_num} – SUPPORTS D'EXPLOITATION\n\n"
287
+
288
+ # Formatage de la liste des supports
289
+ supports_str = ", ".join(supports)
290
+
291
+ supports_clause += f"Le Cessionnaire est autorisé à exploiter l'œuvre et/ou l'image sur les supports suivants : {supports_str}.\n\n"
292
+ supports_clause += "Cette liste est limitative et le Cessionnaire s'engage à ne pas utiliser l'œuvre et/ou l'image sur d'autres supports "
293
+ supports_clause += "sans l'autorisation préalable et écrite du Cédant."
294
+
295
+ return supports_clause
296
+
297
+ @staticmethod
298
+ def get_remuneration_clause(article_num, is_free, remuneration):
299
+ """
300
+ Retourne la clause de rémunération.
301
+
302
+ Args:
303
+ article_num (int): Numéro de l'article
304
+ is_free (bool): True si la cession est gratuite, False sinon
305
+ remuneration (str): Modalités de rémunération
306
+
307
+ Returns:
308
+ str: Clause de rémunération
309
+ """
310
+ remuneration_clause = f"Article {article_num} – RÉMUNÉRATION\n\n"
311
+
312
+ if is_free:
313
+ remuneration_clause += "La présente cession est consentie à titre gratuit. "
314
+ remuneration_clause += "Aucune rémunération n'est due par le Cessionnaire. "
315
+ remuneration_clause += "Le Cédant déclare être pleinement informé de la portée de cette gratuité et y consentir expressément."
316
+ else:
317
+ remuneration_clause += f"En contrepartie de la présente cession, le Cessionnaire versera au Cédant la rémunération suivante : {remuneration}.\n\n"
318
+ remuneration_clause += "Cette rémunération inclut tout montant dû au titre de l'ensemble des droits cédés, tels que définis dans le présent contrat. "
319
+ remuneration_clause += "Le Cédant reconnaît que cette rémunération est conforme aux usages de la profession et proportionnée à l'exploitation prévue de l'œuvre."
320
+
321
+ return remuneration_clause
322
+
323
+ @staticmethod
324
+ def get_warranties_clause(article_num, contract_type):
325
+ """
326
+ Retourne la clause de garanties.
327
+
328
+ Args:
329
+ article_num (int): Numéro de l'article
330
+ contract_type (list): Liste des types de contrats sélectionnés
331
+
332
+ Returns:
333
+ str: Clause de garanties
334
+ """
335
+ warranties_clause = f"Article {article_num} – GARANTIES\n\n"
336
+
337
+ if "Auteur (droits d'auteur)" in contract_type:
338
+ warranties_clause += "L'Auteur garantit au Cessionnaire qu'il est bien titulaire des droits cédés et que l'œuvre n'enfreint pas les droits de tiers. "
339
+ warranties_clause += "L'Auteur garantit notamment que l'œuvre est originale et qu'il détient l'intégralité des droits de propriété intellectuelle sur celle-ci. "
340
+ warranties_clause += "Il garantit le Cessionnaire contre toute revendication, recours ou action que pourrait former toute personne physique ou morale "
341
+ warranties_clause += "estimant avoir des droits sur l'œuvre ou sur tout élément de celle-ci.\n\n"
342
+
343
+ if "Image (droit à l'image)" in contract_type:
344
+ warranties_clause += "Le Modèle garantit qu'il est libre de consentir à la présente autorisation et que son image n'est pas liée "
345
+ warranties_clause += "à d'autres engagements exclusifs incompatibles avec le présent contrat. "
346
+ warranties_clause += "Le Modèle garantit le Cessionnaire contre tout recours ou action que pourraient former des tiers à cet égard.\n\n"
347
+
348
+ warranties_clause += "Le Cessionnaire s'engage à mentionner le nom de l'Auteur lors de toute exploitation de l'œuvre, "
349
+ warranties_clause += "sauf lorsque cela est techniquement impossible ou inapproprié compte tenu du support d'exploitation."
350
+
351
+ return warranties_clause
352
+
353
+ @staticmethod
354
+ def get_termination_clause(article_num):
355
+ """
356
+ Retourne la clause de résiliation.
357
+
358
+ Args:
359
+ article_num (int): Numéro de l'article
360
+
361
+ Returns:
362
+ str: Clause de résiliation
363
+ """
364
+ termination_clause = f"Article {article_num} – RÉSILIATION\n\n"
365
+
366
+ termination_clause += "Le présent contrat pourra être résilié de plein droit par l'une des parties en cas d'inexécution "
367
+ termination_clause += "par l'autre partie de l'une de ses obligations. "
368
+ termination_clause += "Cette résiliation ne deviendra effective que trois mois après l'envoi par la partie plaignante "
369
+ termination_clause += "d'une lettre recommandée avec accusé de réception, exposant les motifs de la plainte, "
370
+ termination_clause += "à moins que, dans ce délai, la partie défaillante n'ait satisfait à ses obligations ou "
371
+ termination_clause += "n'ait apporté la preuve d'un empêchement consécutif à un cas de force majeure.\n\n"
372
+
373
+ termination_clause += "L'exercice de cette faculté de résiliation ne dispense pas la partie défaillante de remplir "
374
+ termination_clause += "les obligations contractées jusqu'à la date de prise d'effet de la résiliation et ce, "
375
+ termination_clause += "sous réserve des dommages éventuellement subis par la partie plaignante du fait de la résiliation anticipée du contrat."
376
+
377
+ return termination_clause
378
+
379
+ @staticmethod
380
+ def get_applicable_law_clause(article_num):
381
+ """
382
+ Retourne la clause de loi applicable.
383
+
384
+ Args:
385
+ article_num (int): Numéro de l'article
386
+
387
+ Returns:
388
+ str: Clause de loi applicable
389
+ """
390
+ law_clause = f"Article {article_num} – LOI APPLICABLE ET JURIDICTION COMPÉTENTE\n\n"
391
+
392
+ law_clause += "Le présent contrat est soumis à la loi française.\n\n"
393
+ law_clause += "En cas de litige sur l'interprétation ou l'exécution du présent contrat, les parties s'efforceront de résoudre leur différend à l'amiable. "
394
+ law_clause += "À défaut d'accord amiable dans un délai de trente (30) jours à compter de la notification du différend par l'une des parties à l'autre, "
395
+ law_clause += "tout litige sera soumis aux tribunaux compétents de Lyon, auxquels il est fait expressément attribution de compétence, "
396
+ law_clause += "y compris en cas de référé, d'appel en garantie ou de pluralité de défendeurs."
397
+
398
+ return law_clause
399
+
400
+ @staticmethod
401
+ def get_signatures_template(contract_type):
402
+ """
403
+ Retourne le template des signatures.
404
+
405
+ Args:
406
+ contract_type (list): Liste des types de contrats sélectionnés
407
+
408
+ Returns:
409
+ str: Template des signatures
410
+ """
411
+ signatures = "\n\nFait à ________________, le ________________\n\n"
412
+
413
+ # Adapter la signature en fonction du type de contrat
414
+ if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
415
+ signatures += "L'Auteur et Modèle Le Cessionnaire"
416
+ elif "Auteur (droits d'auteur)" in contract_type:
417
+ signatures += "L'Auteur Le Cessionnaire"
418
+ else:
419
+ signatures += "Le Modèle Le Cessionnaire"
420
+
421
+ signatures += "\n\n(Signature précédée de la mention « Lu et approuvé »)"
422
+
423
+ return signatures
interface.py ADDED
@@ -0,0 +1,359 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Module définissant l'interface utilisateur Gradio et l'arbre de décision du formulaire.
3
+ """
4
+ import gradio as gr
5
+ from utils import collect_author_info
6
+ from config import (CONTRACT_TYPES, CESSION_MODES, ADDITIONAL_RIGHTS,
7
+ AUTHOR_TYPES, CIVILITY_OPTIONS, SUPPORTS_OPTIONS)
8
+
9
+
10
+ def create_interface(generate_pdf_fn, preview_contract_fn):
11
+ """
12
+ Crée l'interface utilisateur Gradio avec l'arbre de décision pour le formulaire.
13
+
14
+ Args:
15
+ generate_pdf_fn: Fonction pour générer le PDF
16
+ preview_contract_fn: Fonction pour prévisualiser le contrat
17
+
18
+ Returns:
19
+ gr.Blocks: L'interface Gradio configurée
20
+ """
21
+ with gr.Blocks(title="Générateur de Contrats de Cession") as demo:
22
+ gr.Markdown("# Générateur de Contrats de Cession de Droits")
23
+ gr.Markdown("Cet outil vous permet de générer des contrats de cession de droits d'auteur et/ou de droits à l'image adaptés à votre situation.")
24
+
25
+ # Organisation en onglets
26
+ with gr.Tabs():
27
+ with gr.TabItem("Formulaire"):
28
+ # ===== ÉTAPE 1: TYPE DE CONTRAT =====
29
+ gr.Markdown("### 1. Type de contrat")
30
+ gr.Markdown("Cette première étape détermine le type de contrat à générer en fonction de la nature de l'œuvre.")
31
+ type_contrat = gr.CheckboxGroup(
32
+ CONTRACT_TYPES,
33
+ label="Quel type de contrat souhaitez-vous établir?",
34
+ value=["Auteur (droits d'auteur)"],
35
+ info="Sélectionnez 'Auteur' pour une œuvre protégée par le droit d'auteur, 'Image' pour l'utilisation de l'image d'une personne, ou les deux si nécessaire."
36
+ )
37
+
38
+ # ===== ÉTAPE 2: MODE DE CESSION =====
39
+ gr.Markdown("### 2. Mode de cession")
40
+ gr.Markdown("Le mode de cession détermine si la cession est gratuite ou onéreuse, ce qui influencera les droits cédés et les clauses applicables.")
41
+ type_cession = gr.Radio(
42
+ CESSION_MODES,
43
+ label="La cession se fait-elle à titre gratuit ou onéreux?",
44
+ value="Gratuite",
45
+ info="Une cession gratuite limite les droits cédés (reproduction et représentation uniquement). Une cession onéreuse permet d'étendre ces droits."
46
+ )
47
+
48
+ # ===== ÉTAPE 2.1: DROITS CÉDÉS (uniquement si onéreux) =====
49
+ with gr.Group(visible=False) as groupe_droits:
50
+ gr.Markdown("### 2.1 Droits cédés supplémentaires")
51
+ gr.Markdown("""
52
+ Pour une cession onéreuse, vous pouvez céder des droits supplémentaires en plus des droits de base:
53
+ - Le droit de reproduction et le droit de représentation sont toujours inclus
54
+ - Sélectionnez les droits supplémentaires que vous souhaitez céder
55
+ """)
56
+ droits_cedes = gr.CheckboxGroup(
57
+ ADDITIONAL_RIGHTS,
58
+ label="Sélectionnez les droits supplémentaires à céder",
59
+ info="Chaque droit sélectionné sera ajouté dans le contrat avec sa définition juridique précise."
60
+ )
61
+
62
+ # ===== ÉTAPE 2.2: EXCLUSIVITÉ (uniquement si onéreux) =====
63
+ with gr.Group(visible=False) as groupe_exclusivite:
64
+ gr.Markdown("### 2.2 Exclusivité")
65
+ gr.Markdown("""
66
+ L'exclusivité est une clause importante qui détermine si le cédant peut réutiliser ou céder à d'autres les mêmes droits pendant la durée du contrat.
67
+ """)
68
+ exclusivite = gr.Checkbox(
69
+ label="Souhaitez-vous établir une clause d'exclusivité?",
70
+ value=False,
71
+ info="Si coché, le cédant ne pourra pas céder les mêmes droits à d'autres personnes ni les utiliser lui-même pendant la durée du contrat."
72
+ )
73
+
74
+ # ===== ÉTAPE 3: INFORMATIONS SUR L'AUTEUR/MODÈLE =====
75
+ gr.Markdown("### 3. Informations sur l'auteur/modèle")
76
+ gr.Markdown("Ces informations identifient précisément le cédant dans le contrat.")
77
+ auteur_type = gr.Radio(
78
+ AUTHOR_TYPES,
79
+ label="L'auteur/modèle est-il une personne physique ou morale?",
80
+ value="Personne physique",
81
+ info="Une personne morale est une entreprise ou une association. Pour les personnes morales, assurez-vous qu'elles détiennent bien les droits (œuvre collective, logiciel, ou cession obtenue)."
82
+ )
83
+
84
+ # Champs pour personne physique (visibles par défaut)
85
+ with gr.Group() as groupe_personne_physique:
86
+ gentille = gr.Radio(
87
+ CIVILITY_OPTIONS,
88
+ label="Civilité",
89
+ value="M."
90
+ )
91
+ nom = gr.Textbox(
92
+ label="Nom",
93
+ placeholder="Nom de famille"
94
+ )
95
+ prenom = gr.Textbox(
96
+ label="Prénom",
97
+ placeholder="Prénom"
98
+ )
99
+ date_naissance = gr.Textbox(
100
+ label="Date de naissance (facultatif)",
101
+ placeholder="JJ/MM/AAAA"
102
+ )
103
+ nationalite = gr.Textbox(
104
+ label="Nationalité",
105
+ placeholder="Ex: française"
106
+ )
107
+ adresse = gr.Textbox(
108
+ label="Adresse complète",
109
+ placeholder="Numéro, rue, code postal, ville"
110
+ )
111
+ contact_physique = gr.Textbox(
112
+ label="Moyen de contact (email, téléphone)",
113
+ placeholder="Email et/ou téléphone"
114
+ )
115
+
116
+ # Champs pour personne morale (masqués par défaut)
117
+ with gr.Group(visible=False) as groupe_personne_morale:
118
+ nom_societe = gr.Textbox(
119
+ label="Nom de la société",
120
+ placeholder="Dénomination sociale"
121
+ )
122
+ statut = gr.Textbox(
123
+ label="Statut juridique",
124
+ placeholder="Ex: SARL, SAS, EURL, etc."
125
+ )
126
+ rcs = gr.Textbox(
127
+ label="Numéro RCS",
128
+ placeholder="Ex: 123 456 789 R.C.S. Paris"
129
+ )
130
+ siege = gr.Textbox(
131
+ label="Adresse du siège social",
132
+ placeholder="Adresse complète du siège"
133
+ )
134
+ contact_morale = gr.Textbox(
135
+ label="Moyen de contact (email, téléphone)",
136
+ placeholder="Email et/ou téléphone"
137
+ )
138
+
139
+ # ===== ÉTAPE 4: DESCRIPTION DE L'ŒUVRE (si contrat droits d'auteur) =====
140
+ with gr.Group() as groupe_description_oeuvre:
141
+ gr.Markdown("### 4. Description de l'œuvre")
142
+ gr.Markdown("""
143
+ Décrivez précisément l'œuvre concernée. Cette description sera intégrée dans le contrat pour identifier sans ambiguïté l'objet de la cession.
144
+ """)
145
+ description_oeuvre = gr.Textbox(
146
+ label="Description de l'œuvre",
147
+ placeholder="Titre, format, dimensions, support, technique utilisée, date de création, etc.",
148
+ lines=5,
149
+ info="Plus la description est précise, plus le contrat sera sécurisé juridiquement."
150
+ )
151
+
152
+ # ===== ÉTAPE 5: DESCRIPTION DE L'IMAGE (si contrat droit à l'image) =====
153
+ with gr.Group(visible=False) as groupe_description_image:
154
+ gr.Markdown("### 5. Description des images")
155
+ gr.Markdown("""
156
+ Décrivez précisément les images ou vidéos concernées par la cession du droit à l'image.
157
+ """)
158
+ description_image = gr.Textbox(
159
+ label="Description des images/vidéos",
160
+ placeholder="Ex: Séance photo réalisée le [date] à [lieu], comprenant X photographies où apparaît [nom du modèle]",
161
+ lines=5,
162
+ info="Précisez le contexte, la date et le lieu de prise de vue, le nombre d'images concernées, etc."
163
+ )
164
+
165
+ # ===== ÉTAPE 6: SUPPORTS D'EXPLOITATION =====
166
+ gr.Markdown("### 6. Supports d'exploitation")
167
+ gr.Markdown("""
168
+ Sélectionnez les supports sur lesquels l'œuvre ou l'image pourra être exploitée.
169
+ Le site web et Discord de Tellers sont automatiquement inclus.
170
+ """)
171
+ supports = gr.CheckboxGroup(
172
+ SUPPORTS_OPTIONS,
173
+ label="Sur quels supports les droits seront-ils exploités?",
174
+ value=["Réseaux sociaux (Facebook, Instagram, Twitter, etc.)"],
175
+ info="Vous pouvez sélectionner plusieurs supports. Le site web et Discord de Tellers sont toujours inclus."
176
+ )
177
+
178
+ # ===== ÉTAPE 7: RÉMUNÉRATION (uniquement si onéreux) =====
179
+ with gr.Group(visible=False) as groupe_remuneration:
180
+ gr.Markdown("### 7. Rémunération")
181
+ gr.Markdown("""
182
+ Pour une cession onéreuse, précisez les modalités de rémunération.
183
+ Cela peut être un montant forfaitaire ou proportionnel aux recettes.
184
+ """)
185
+ remuneration = gr.Textbox(
186
+ label="Modalités de rémunération",
187
+ placeholder="Ex: 500€ versés à la signature, 5% des recettes versés trimestriellement",
188
+ lines=3,
189
+ info="La rémunération doit être précise pour être juridiquement valable: montant, date(s) de paiement, modalités."
190
+ )
191
+
192
+ # ===== BOUTONS D'ACTION =====
193
+ gr.Markdown("### Génération du contrat")
194
+ with gr.Row():
195
+ preview_btn = gr.Button("Prévisualiser le contrat", variant="secondary")
196
+ generate_btn = gr.Button("Générer le contrat PDF", variant="primary")
197
+
198
+ # ===== ONGLET PRÉVISUALISATION =====
199
+ with gr.TabItem("Prévisualisation"):
200
+ apercu_contrat = gr.Textbox(
201
+ label="Aperçu du contrat",
202
+ lines=25,
203
+ max_lines=50,
204
+ interactive=False
205
+ )
206
+
207
+ # ===== ONGLET TÉLÉCHARGEMENT =====
208
+ with gr.TabItem("Téléchargement"):
209
+ pdf_output = gr.File(label="Contrat de cession prêt à télécharger")
210
+
211
+ # ===== DÉFINITION DES INTERACTIONS CONDITIONNELLES =====
212
+
213
+ # 1. Visibilité des champs en fonction du type de contrat
214
+ def update_groups_type_contrat(type_selection):
215
+ """Met à jour la visibilité des champs selon le type de contrat sélectionné."""
216
+ show_auteur = "Auteur (droits d'auteur)" in type_selection
217
+ show_image = "Image (droit à l'image)" in type_selection
218
+
219
+ return {
220
+ groupe_description_oeuvre: gr.update(visible=show_auteur),
221
+ groupe_description_image: gr.update(visible=show_image)
222
+ }
223
+
224
+ type_contrat.change(
225
+ fn=update_groups_type_contrat,
226
+ inputs=type_contrat,
227
+ outputs=[groupe_description_oeuvre, groupe_description_image]
228
+ )
229
+
230
+ # 2. Visibilité des champs en fonction du type de cession (gratuite/onéreuse)
231
+ def update_groups_type_cession(cession_type):
232
+ """Met à jour la visibilité des champs selon le type de cession sélectionné."""
233
+ is_onereux = cession_type == "Onéreuse"
234
+ return {
235
+ groupe_droits: gr.update(visible=is_onereux),
236
+ groupe_exclusivite: gr.update(visible=is_onereux),
237
+ groupe_remuneration: gr.update(visible=is_onereux)
238
+ }
239
+
240
+ type_cession.change(
241
+ fn=update_groups_type_cession,
242
+ inputs=type_cession,
243
+ outputs=[groupe_droits, groupe_exclusivite, groupe_remuneration]
244
+ )
245
+
246
+ # 3. Changement de formulaire selon le type d'auteur (physique/morale)
247
+ def update_groups_type_auteur(auteur_type_val):
248
+ """Met à jour la visibilité des champs selon le type d'auteur sélectionné."""
249
+ is_physique = auteur_type_val == "Personne physique"
250
+ return {
251
+ groupe_personne_physique: gr.update(visible=is_physique),
252
+ groupe_personne_morale: gr.update(visible=not is_physique)
253
+ }
254
+
255
+ auteur_type.change(
256
+ fn=update_groups_type_auteur,
257
+ inputs=auteur_type,
258
+ outputs=[groupe_personne_physique, groupe_personne_morale]
259
+ )
260
+
261
+ # 4. Prévisualisation du contrat
262
+ def handle_preview(type_contrat_val, type_cession_val, auteur_type_val,
263
+ gentille_val, nom_val, prenom_val, date_naissance_val, nationalite_val, adresse_val, contact_physique_val,
264
+ nom_societe_val, statut_val, rcs_val, siege_val, contact_morale_val,
265
+ description_oeuvre_val, description_image_val, supports_val, droits_cedes_val, remuneration_val, exclusivite_val):
266
+ """Gère la prévisualisation du contrat."""
267
+ # Collecter les informations sur l'auteur/modèle
268
+ is_physical_person = (auteur_type_val == "Personne physique")
269
+
270
+ data = {
271
+ "gentille": gentille_val,
272
+ "nom": nom_val,
273
+ "prenom": prenom_val,
274
+ "date_naissance": date_naissance_val,
275
+ "nationalite": nationalite_val,
276
+ "adresse": adresse_val,
277
+ "contact_physique": contact_physique_val,
278
+ "nom_societe": nom_societe_val,
279
+ "statut": statut_val,
280
+ "rcs": rcs_val,
281
+ "siege": siege_val,
282
+ "contact_morale": contact_morale_val
283
+ }
284
+
285
+ auteur_info = collect_author_info(is_physical_person, data)
286
+
287
+ # Est-ce que la cession est gratuite ?
288
+ est_gratuit = (type_cession_val == "Gratuite")
289
+
290
+ # Générer l'aperçu du contrat
291
+ apercu = preview_contract_fn(
292
+ type_contrat_val, est_gratuit, auteur_type_val, auteur_info,
293
+ description_oeuvre_val, description_image_val, supports_val,
294
+ droits_cedes_val, remuneration_val, exclusivite_val
295
+ )
296
+
297
+ return apercu
298
+
299
+ preview_btn.click(
300
+ fn=handle_preview,
301
+ inputs=[
302
+ type_contrat, type_cession, auteur_type,
303
+ gentille, nom, prenom, date_naissance, nationalite, adresse, contact_physique,
304
+ nom_societe, statut, rcs, siege, contact_morale,
305
+ description_oeuvre, description_image, supports, droits_cedes, remuneration, exclusivite
306
+ ],
307
+ outputs=apercu_contrat
308
+ )
309
+
310
+ # 5. Génération du PDF
311
+ def handle_generate_pdf(type_contrat_val, type_cession_val, auteur_type_val,
312
+ gentille_val, nom_val, prenom_val, date_naissance_val, nationalite_val, adresse_val, contact_physique_val,
313
+ nom_societe_val, statut_val, rcs_val, siege_val, contact_morale_val,
314
+ description_oeuvre_val, description_image_val, supports_val, droits_cedes_val, remuneration_val, exclusivite_val):
315
+ """Gère la génération du PDF."""
316
+ # Collecter les informations sur l'auteur/modèle
317
+ is_physical_person = (auteur_type_val == "Personne physique")
318
+
319
+ data = {
320
+ "gentille": gentille_val,
321
+ "nom": nom_val,
322
+ "prenom": prenom_val,
323
+ "date_naissance": date_naissance_val,
324
+ "nationalite": nationalite_val,
325
+ "adresse": adresse_val,
326
+ "contact_physique": contact_physique_val,
327
+ "nom_societe": nom_societe_val,
328
+ "statut": statut_val,
329
+ "rcs": rcs_val,
330
+ "siege": siege_val,
331
+ "contact_morale": contact_morale_val
332
+ }
333
+
334
+ auteur_info = collect_author_info(is_physical_person, data)
335
+
336
+ # Est-ce que la cession est gratuite ?
337
+ est_gratuit = (type_cession_val == "Gratuite")
338
+
339
+ # Générer le PDF
340
+ pdf_path = generate_pdf_fn(
341
+ type_contrat_val, est_gratuit, auteur_type_val, auteur_info,
342
+ description_oeuvre_val, description_image_val, supports_val,
343
+ droits_cedes_val, remuneration_val, exclusivite_val
344
+ )
345
+
346
+ return pdf_path
347
+
348
+ generate_btn.click(
349
+ fn=handle_generate_pdf,
350
+ inputs=[
351
+ type_contrat, type_cession, auteur_type,
352
+ gentille, nom, prenom, date_naissance, nationalite, adresse, contact_physique,
353
+ nom_societe, statut, rcs, siege, contact_morale,
354
+ description_oeuvre, description_image, supports, droits_cedes, remuneration, exclusivite
355
+ ],
356
+ outputs=pdf_output
357
+ )
358
+
359
+ return demo
pdf_generator-py.py ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Module pour la génération des contrats en format PDF.
3
+ """
4
+ import io
5
+ from reportlab.pdfgen import canvas
6
+ from reportlab.lib.pagesizes import A4
7
+ from reportlab.lib.units import mm
8
+ from reportlab.platypus import SimpleDocTemplate
9
+ from reportlab.pdfbase import pdfform
10
+ from reportlab.lib.colors import black
11
+
12
+ from config import PDF_CONFIG
13
+ from contract_builder import ContractBuilder
14
+ from utils import create_temp_file, ensure_default_supports
15
+
16
+
17
+ def generate_pdf(contract_type, is_free, author_type, author_info,
18
+ work_description, image_description, supports,
19
+ additional_rights, remuneration, is_exclusive):
20
+ """
21
+ Génère un PDF du contrat avec des champs interactifs.
22
+
23
+ Args:
24
+ contract_type (list): Liste des types de contrats sélectionnés
25
+ is_free (bool): True si la cession est gratuite, False sinon
26
+ author_type (str): Type d'auteur ("Personne physique" ou "Personne morale")
27
+ author_info (dict): Informations sur l'auteur
28
+ work_description (str): Description de l'œuvre
29
+ image_description (str): Description de l'image
30
+ supports (list): Liste des supports sélectionnés
31
+ additional_rights (list): Liste des droits supplémentaires sélectionnés
32
+ remuneration (str): Modalités de rémunération
33
+ is_exclusive (bool): True si la cession est exclusive, False sinon
34
+
35
+ Returns:
36
+ str: Chemin vers le fichier PDF généré
37
+ """
38
+ # Conversion des paramètres
39
+ is_free_bool = (is_free == "Gratuite")
40
+ is_exclusive_bool = bool(is_exclusive)
41
+
42
+ # Ajouter les supports par défaut
43
+ final_supports = ensure_default_supports(supports)
44
+
45
+ # Créer un nom de fichier temporaire pour le PDF
46
+ output_filename = create_temp_file(prefix="contrat_cession_", suffix=".pdf")
47
+
48
+ # Générer le contenu du contrat
49
+ contract_elements = ContractBuilder.build_contract_elements(
50
+ contract_type, is_free_bool, author_type, author_info,
51
+ work_description, image_description, final_supports,
52
+ additional_rights, remuneration, is_exclusive_bool
53
+ )
54
+
55
+ # Créer un document PDF
56
+ buffer = io.BytesIO()
57
+ doc = SimpleDocTemplate(buffer, pagesize=A4,
58
+ rightMargin=PDF_CONFIG['margin_right']*mm,
59
+ leftMargin=PDF_CONFIG['margin_left']*mm,
60
+ topMargin=PDF_CONFIG['margin_top']*mm,
61
+ bottomMargin=PDF_CONFIG['margin_bottom']*mm)
62
+
63
+ # Construire le document avec tous les éléments
64
+ doc.build(contract_elements)
65
+
66
+ # Ajouter des champs interactifs pour les signatures
67
+ buffer.seek(0)
68
+ buffer_champs = io.BytesIO()
69
+
70
+ p = canvas.Canvas(buffer_champs, pagesize=A4)
71
+ form = p.acroForm
72
+
73
+ # Déterminer le nom du cédant en fonction du type de contrat
74
+ if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
75
+ cedant_label = "l'Auteur et Modèle"
76
+ elif "Auteur (droits d'auteur)" in contract_type:
77
+ cedant_label = "l'Auteur"
78
+ else:
79
+ cedant_label = "le Modèle"
80
+
81
+ # Champ pour le lieu (position sur dernière page)
82
+ form.textfield(name='lieu', tooltip='Lieu de signature',
83
+ x=80, y=140, width=100, height=15,
84
+ borderWidth=0, forceBorder=True)
85
+
86
+ # Champ pour la date
87
+ form.textfield(name='date', tooltip='Date de signature',
88
+ x=230, y=140, width=100, height=15,
89
+ borderWidth=0, forceBorder=True)
90
+
91
+ # Champ pour la mention "Lu et approuvé" du cédant
92
+ form.textfield(name='mention_cedant', tooltip='Mention "Lu et approuvé"',
93
+ x=70, y=95, width=150, height=15,
94
+ borderWidth=0, forceBorder=True)
95
+
96
+ # Champ pour la mention "Lu et approuvé" du cessionnaire
97
+ form.textfield(name='mention_cessionnaire', tooltip='Mention "Lu et approuvé"',
98
+ x=350, y=95, width=150, height=15,
99
+ borderWidth=0, forceBorder=True)
100
+
101
+ # Champs pour les signatures
102
+ form.textfield(name='signature_cedant', tooltip=f'Signature de {cedant_label}',
103
+ x=70, y=60, width=150, height=30,
104
+ borderWidth=0, forceBorder=True)
105
+
106
+ form.textfield(name='signature_cessionnaire', tooltip='Signature du Cessionnaire',
107
+ x=350, y=60, width=150, height=30,
108
+ borderWidth=0, forceBorder=True)
109
+
110
+ # Ajouter des champs pour le paraphe sur chaque page
111
+ # Ces champs sont placés en bas de chaque page pour permettre le paraphe
112
+ page_count = doc.page_count
113
+ for page in range(1, page_count):
114
+ p.showPage() # Aller à la page suivante
115
+ form.textfield(name=f'paraphe_cedant_{page}', tooltip=f'Paraphe {cedant_label} - page {page}',
116
+ x=70, y=30, width=50, height=20,
117
+ borderWidth=0, forceBorder=True)
118
+ form.textfield(name=f'paraphe_cessionnaire_{page}', tooltip=f'Paraphe Cessionnaire - page {page}',
119
+ x=350, y=30, width=50, height=20,
120
+ borderWidth=0, forceBorder=True)
121
+
122
+ # Finaliser et sauvegarder le PDF
123
+ p.save()
124
+
125
+ # Sauvegarder le PDF dans un fichier temporaire
126
+ with open(output_filename, 'wb') as f:
127
+ f.write(buffer.getvalue())
128
+ f.write(buffer_champs.getvalue())
129
+
130
+ return output_filename
131
+
132
+
133
+ def add_interactive_fields(pdf_path, contract_type):
134
+ """
135
+ Ajoute des champs interactifs à un PDF existant.
136
+
137
+ Args:
138
+ pdf_path (str): Chemin vers le PDF
139
+ contract_type (list): Liste des types de contrats sélectionnés
140
+
141
+ Returns:
142
+ str: Chemin vers le PDF avec champs interactifs
143
+ """
144
+ # Ce code peut être utilisé si on veut ajouter des champs à un PDF existant
145
+ # plutôt que de les créer en même temps
146
+ output_filename = create_temp_file(prefix="contrat_interactif_", suffix=".pdf")
147
+
148
+ p = canvas.Canvas(output_filename, pagesize=A4)
149
+ form = p.acroForm
150
+
151
+ # Déterminer le nom du cédant en fonction du type de contrat
152
+ if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
153
+ cedant_label = "l'Auteur et Modèle"
154
+ elif "Auteur (droits d'auteur)" in contract_type:
155
+ cedant_label = "l'Auteur"
156
+ else:
157
+ cedant_label = "le Modèle"
158
+
159
+ # Ajouter des champs similaires à ceux de la fonction generate_pdf
160
+ # Ici, on assume que le PDF a une structure similaire
161
+
162
+ # Sauvegarder le PDF
163
+ p.save()
164
+
165
+ return output_filename
readme.md ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Générateur de Contrats de Cession de Droits
2
+
3
+ Ce projet propose un générateur interactif de contrats de cession de droits d'auteur et de droits à l'image, conçu pour Tellers. L'application génère automatiquement des contrats juridiquement rigoureux adaptés aux besoins spécifiques de chaque situation.
4
+
5
+ ## Structure du projet
6
+
7
+ Le projet est organisé de manière modulaire pour une meilleure séparation des responsabilités :
8
+
9
+ - `app.py` - Point d'entrée principal de l'application
10
+ - `interface.py` - Définition de l'interface utilisateur Gradio
11
+ - `config.py` - Configuration et constantes du projet
12
+ - `utils.py` - Fonctions utilitaires
13
+ - `contract_templates.py` - Templates des différentes sections de contrats
14
+ - `contract_builder.py` - Construction du contrat à partir des templates
15
+ - `contract_previewer.py` - Prévisualisation du contrat
16
+ - `pdf_generator.py` - Génération du PDF final avec champs interactifs
17
+
18
+ ## Fonctionnalités
19
+
20
+ - Création de contrats de cession de droits d'auteur
21
+ - Création de contrats de droit à l'image
22
+ - Génération de contrats combinés (droits d'auteur + droits à l'image)
23
+ - Adaptation automatique des clauses selon le type de cession (gratuit/onéreux)
24
+ - Gestion des clauses d'exclusivité
25
+ - Support pour les auteurs personnes physiques ou morales
26
+ - Prévisualisation du contrat avant génération
27
+ - Export au format PDF avec champs interactifs pour les signatures et paraphes
28
+
29
+ ## Arbre de décision du formulaire
30
+
31
+ 1. **Type de contrat**
32
+ - Droits d'auteur
33
+ - Droit à l'image
34
+ - Les deux
35
+
36
+ 2. **Mode de cession**
37
+ - Gratuite (limite les droits à la reproduction et représentation)
38
+ - Onéreuse (permet d'étendre les droits et l'exclusivité)
39
+
40
+ 3. **Droits supplémentaires** (si cession onéreuse)
41
+ - Distribution
42
+ - Usage
43
+ - Adaptation
44
+ - Prêt
45
+ - Location
46
+ - Droit de suite (œuvres graphiques et plastiques)
47
+
48
+ 4. **Exclusivité** (si cession onéreuse)
49
+ - Avec exclusivité
50
+ - Sans exclusivité
51
+
52
+ 5. **Informations sur l'auteur/modèle**
53
+ - Personne physique (civilité, nom, prénom, etc.)
54
+ - Personne morale (société, statut juridique, RCS, etc.)
55
+
56
+ 6. **Description de l'œuvre/image**
57
+ - Description précise de l'œuvre (si droits d'auteur)
58
+ - Description précise des images/vidéos (si droit à l'image)
59
+
60
+ 7. **Supports d'exploitation**
61
+ - Multiples options (réseaux sociaux, applications, etc.)
62
+ - Site web et Discord toujours inclus
63
+
64
+ 8. **Rémunération** (si cession onéreuse)
65
+ - Modalités de paiement (montant, échéancier, etc.)
66
+
67
+ ## Déploiement sur Hugging Face Spaces
68
+
69
+ 1. Créez un nouveau Space sur Hugging Face (https://huggingface.co/spaces/new)
70
+ 2. Sélectionnez "Gradio" comme type d'application
71
+ 3. Téléchargez tous les fichiers Python (.py) et requirements.txt
72
+ 4. L'application sera automatiquement déployée et accessible via l'URL de votre Space
73
+
74
+ ## PDF interactifs générés
75
+
76
+ Les PDF générés par l'application comprennent :
77
+ - Des champs de texte pour le lieu et la date de signature
78
+ - Des champs pour la mention "Lu et approuvé"
79
+ - Des champs de signature pour le cédant et le cessionnaire
80
+ - Des champs pour les paraphes sur chaque page
81
+
82
+ ## Notes légales
83
+
84
+ Les contrats générés par cet outil sont conçus selon les principes juridiques français applicables aux cessions de droits d'auteur (Code de la propriété intellectuelle) et aux droits à l'image. Pour des situations spécifiques ou complexes, il est recommandé de consulter un professionnel du droit.
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ gradio==4.10.0
2
+ reportlab==4.0.4
utils.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Fonctions utilitaires utilisées dans l'application.
3
+ """
4
+ import os
5
+ import tempfile
6
+ import re
7
+ from config import DEFAULT_SUPPORTS
8
+
9
+
10
+ def collect_author_info(is_physical_person, data):
11
+ """
12
+ Collecte les informations sur l'auteur/modèle selon son type.
13
+
14
+ Args:
15
+ is_physical_person (bool): True si l'auteur est une personne physique, False sinon
16
+ data (dict): Dictionnaire contenant les données du formulaire
17
+
18
+ Returns:
19
+ dict: Les informations formatées sur l'auteur/modèle
20
+ """
21
+ author_info = {}
22
+
23
+ if is_physical_person:
24
+ # Personne physique
25
+ author_info = {
26
+ "gentille": data.get("gentille", "M."),
27
+ "nom": data.get("nom", ""),
28
+ "prenom": data.get("prenom", ""),
29
+ "date_naissance": data.get("date_naissance", ""),
30
+ "nationalite": data.get("nationalite", ""),
31
+ "adresse": data.get("adresse", ""),
32
+ "contact": data.get("contact_physique", "")
33
+ }
34
+ else:
35
+ # Personne morale
36
+ author_info = {
37
+ "nom_societe": data.get("nom_societe", ""),
38
+ "statut": data.get("statut", ""),
39
+ "rcs": data.get("rcs", ""),
40
+ "siege": data.get("siege", ""),
41
+ "contact": data.get("contact_morale", "")
42
+ }
43
+
44
+ return author_info
45
+
46
+
47
+ def ensure_default_supports(selected_supports):
48
+ """
49
+ S'assure que les supports par défaut sont inclus dans la liste des supports sélectionnés.
50
+
51
+ Args:
52
+ selected_supports (list): Liste des supports sélectionnés par l'utilisateur
53
+
54
+ Returns:
55
+ list: Liste des supports incluant les supports par défaut
56
+ """
57
+ # Création d'une copie de la liste pour ne pas modifier l'original
58
+ supports = selected_supports.copy() if selected_supports else []
59
+
60
+ # Vérification que les supports par défaut sont inclus
61
+ for default_support in DEFAULT_SUPPORTS:
62
+ # Vérification que le support n'est pas déjà présent sous une forme quelconque
63
+ if not any(default_support.lower() in support.lower() for support in supports):
64
+ supports.append(default_support)
65
+
66
+ return supports
67
+
68
+
69
+ def sanitize_text(text):
70
+ """
71
+ Nettoie le texte pour éviter les problèmes d'affichage dans le PDF.
72
+
73
+ Args:
74
+ text (str): Texte à nettoyer
75
+
76
+ Returns:
77
+ str: Texte nettoyé
78
+ """
79
+ if not text:
80
+ return ""
81
+
82
+ # Remplace les caractères spéciaux qui pourraient poser problème
83
+ text = re.sub(r'[^\x00-\x7F]+', ' ', text)
84
+
85
+ # Limite la longueur des lignes pour éviter les débordements
86
+ text = '\n'.join(line if len(line) < 80 else line[:77] + '...'
87
+ for line in text.split('\n'))
88
+
89
+ return text
90
+
91
+
92
+ def create_temp_file(prefix="contrat_", suffix=".pdf"):
93
+ """
94
+ Crée un fichier temporaire.
95
+
96
+ Args:
97
+ prefix (str): Préfixe du nom du fichier
98
+ suffix (str): Suffixe du nom du fichier
99
+
100
+ Returns:
101
+ str: Chemin vers le fichier temporaire
102
+ """
103
+ temp_dir = tempfile.gettempdir()
104
+ filename = f"{prefix}{tempfile.NamedTemporaryFile().name}{suffix}"
105
+ return os.path.join(temp_dir, os.path.basename(filename))
106
+
107
+
108
+ def format_supports_list(supports):
109
+ """
110
+ Formate la liste des supports pour l'affichage dans le contrat.
111
+
112
+ Args:
113
+ supports (list): Liste des supports
114
+
115
+ Returns:
116
+ str: Liste des supports formatée
117
+ """
118
+ if not supports:
119
+ return "site web et Discord de Tellers"
120
+
121
+ # Formate la liste des supports en une chaîne lisible
122
+ return ", ".join(supports)